3

I am continuing on the road to learn Docker and how to deal with images and containers. I am working on an image to be used by me at work. This is the Dockerfile:

FROM ubuntu:trusty
...
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \
    chown www-data /usr/local/bin/composer && composer --version

RUN composer global require sebastian/phpcpd && \
    composer global require phpmd/phpmd && \
    composer global require squizlabs/php_codesniffer
...

It works but each time I build an image I am seeing the annoying message about composer run as root user, which is not bad at all but I would like to change this behavior just for fun :) and learning.

I would like to create and keep (for another usage, maybe for other tasks as well) a user docker-dev for running this task. This user should have a home directory and composer should install libraries globally but under this user home directory.

Right now composer gets installed under /root/.composer and every library is installed there. I would like to turn it into /home/docker-dev/.composer and then have the libraries installed there.

I have read a lot of docs about this topic:

..and many more, but this is a lot of information and is confusing.

Can anybody help me to make those changes for creating the user and installing composer libraries under its home directory, in my Dockerfile?

Note: I have removed the irrelevant part from the Dockerfile so the post is not too long.

Update

After the solution provided this is what I have tried without success:

# This still running as root because we need to move composer to /user/local/bin
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \
    chown www-data /usr/local/bin/composer && composer --version

# I am adding a docker-dev user
RUN useradd docker-dev

# Switch to RUN the next command as the recently created user
USER docker-dev

# Run the command in verbose mode (just for debug)
RUN composer global --verbose require sebastian/phpcpd && \
    composer global --verbose require phpmd/phpmd && \
    composer global --verbose require squizlabs/php_codesniffer

And this is the output from console:

Step 8 : RUN composer global --verbose require sebastian/phpcpd &&     composer global --verbose require phpmd/phpmd &&     composer global --verbose require pdepend/pdepend &&     composer global --verbose require squizlabs/php_codesniffer &&     composer global --verbose require phpunit/phpunit
 ---> Running in 0f203e1760a4
                                               
  [ErrorException]                              
  chdir(): No such file or directory (errno 2)                                               

Exception trace:
 () at phar:///usr/local/bin/composer/src/Composer/Command/GlobalCommand.php:74
 Composer\Util\ErrorHandler::handle() at n/a:n/a
 chdir() at phar:///usr/local/bin/composer/src/Composer/Command/GlobalCommand.php:74
 Composer\Command\GlobalCommand->run() at phar:///usr/local/bin/composer/vendor/symfony/console/Application.php:847
 Symfony\Component\Console\Application->doRunCommand() at phar:///usr/local/bin/composer/vendor/symfony/console/Application.php:192
 Symfony\Component\Console\Application->doRun() at phar:///usr/local/bin/composer/src/Composer/Console/Application.php:231
 Composer\Console\Application->doRun() at phar:///usr/local/bin/composer/vendor/symfony/console/Application.php:123
 Symfony\Component\Console\Application->run() at phar:///usr/local/bin/composer/src/Composer/Console/Application.php:104
 Composer\Console\Application->run() at phar:///usr/local/bin/composer/bin/composer:43
 require() at /usr/local/bin/composer:24

global <command-name> [<args>]...

I am not sure if the problem is with permissions, what do you think?

Kamafeather
  • 8,663
  • 14
  • 69
  • 99
ReynierPM
  • 17,594
  • 53
  • 193
  • 363

1 Answers1

1

In your Dockerfile - Use a RUN command to create the user:

RUN useradd userToRunComposer

Then use the USER command in your Dockerfile, after creating it.

USER userToRunComposer
RUN curl -sS https://getcomposer.org/instal...
RUN composer global require se...

You could also take a different approach by creating the user inside the container, then committing the image:

docker exec -ti <my container name> /bin/bash
userAdd userToRunComposer

And then do a: docker commit <my container id> <myimagename> to avoid having to create the user every single time

See this question.

Community
  • 1
  • 1
STLMikey
  • 1,210
  • 7
  • 19
  • I believe that `RUN useradd userToRunComposer` will create the following directory `/home/userToRunComposer`, I am right? if so this user will only live for the composer task or it will be keep on the final image? What happen with the content downloaded to `/home/userToRunComposer`? – ReynierPM Sep 27 '16 at 17:13
  • Take a look to the update on the OP, I have added the output regarding your suggested changes – ReynierPM Sep 27 '16 at 17:40
  • content saved/created to non-volmounted directories will be maintained in the image – STLMikey Sep 27 '16 at 17:40
  • I think the new user doesn't know about the composer executable, can you add it to the path? or is /usr/local/bin in the path? – STLMikey Sep 27 '16 at 17:43
  • Not sure about how to achieve this in a container but just for shot, will this work: `RUN export PATH=$PATH:/usr/local/bin`? – ReynierPM Sep 27 '16 at 17:44
  • I'm not sure on that one, what if instead of `RUN composer global` you tried `RUN /usr/local/bin/composer global` – STLMikey Sep 27 '16 at 17:47
  • I suggest to do `USER userToRunComposer`, `ENV COMPOSER_HOME=/home/userToRunComposer/.composer` and `ENV PATH="/home/userToRunComposer/.composer/vendor/bin:${PATH}"`, to install deps with the correct rights into the user home, so it is reachable as non-root. The user will of course stay in the image and won't be available only for composer. Usually the `userToRunComposer` should be the non-root user that runs the application; or at least that is how I do it. – Kamafeather Aug 12 '21 at 15:37