Docker - Execute command after mounting a volume

Viewed 27618

I have the following Dockerfile for a php runtime based on the official [php][1] image.

FROM php:fpm
WORKDIR /var/www/root/
RUN apt-get update && apt-get install -y \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        libmcrypt-dev \
        libpng12-dev \
        zip \
        unzip \
    && docker-php-ext-install -j$(nproc) iconv mcrypt \
    && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
    && docker-php-ext-install -j$(nproc) gd \
    && docker-php-ext-install mysqli \
    && docker-php-ext-enable opcache \
    && php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
    && php -r "if (hash_file('SHA384', 'composer-setup.php') === '669656bab3166a7aff8a7506b8cb2d1c292f042046c5a994c43155c0be6190fa0355160742ab2e1c88d40d5be660b410') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
    && php composer-setup.php \
    && php -r "unlink('composer-setup.php');" \
    && mv composer.phar /usr/local/bin/composer

I am having trouble running composer install.

I am guessing that the Dockerfile runs before a volume is mounted because I receive a composer.json file not found error if adding:

...
&& mv composer.phar /usr/local/bin/composer \
&& composer install

to the above.

But, adding the following property to docker-compose.yml:

command: sh -c "composer install && composer require drush/drush"

seems to terminate the container after the command finishes executing.

Is there a way to:

  • wait for a volume to become mounted
  • run composer install using the mounted composer.json file
  • have the container keep running afters

?

4 Answers

I've been down this rabbit hole for 5 hours, all of the solutions out there are way too complicated. The easiest solution is to exclude vendor or node_modules and similar directories from volume.

#docker-compose.yml
volumes:
      - .:/srv/app/
      - /srv/app/vendor/

So this will map current project directory but exclude its vendor subdirectory. Dont forget the trailing slash!

So now you can easily run composer install in dockerfile and when docker mounts your volume it will ignore vendor directory.

To execute a command after you have mounted a volume on a docker container

Assuming that you are fetching dependencies from a public repo

docker run --interactive -t --privileged --volume ${pwd}:/xyz composer /bin/sh -c 'composer install'

For fetching dependencies from a private git repo, you would need to copy/create ssh keys, I guess that should be out of scope of this question.

Related