Running composer install within a Dockerfile

DockerComposer PhpDocker Compose

Docker Problem Overview


I'm trying to Dockerize my laravel app. The app is already built and in git, but I .gitignore my vendor folder. I've added a Dockerfile, which looks like this:

FROM php:7.1-fpm-alpine

RUN apk update && apk add curl && \
  curl -sS https://getcomposer.org/installer | php \
  && chmod +x composer.phar && mv composer.phar /usr/local/bin/composer

RUN apk --no-cache add --virtual .build-deps $PHPIZE_DEPS \
  && apk --no-cache add --virtual .ext-deps libmcrypt-dev freetype-dev \
  libjpeg-turbo-dev libpng-dev libxml2-dev msmtp bash openssl-dev pkgconfig \
  && docker-php-source extract \
  && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ \
                                   --with-png-dir=/usr/include/ \
                                   --with-jpeg-dir=/usr/include/ \
  && docker-php-ext-install gd mcrypt mysqli pdo pdo_mysql zip opcache \
  && pecl install mongodb redis xdebug \
  && docker-php-ext-enable mongodb \
  && docker-php-ext-enable redis \
  && docker-php-ext-enable xdebug \
  && docker-php-source delete \
  && apk del .build-deps

WORKDIR /var/www/html

COPY composer.json composer.lock ./
RUN composer install --no-scripts --no-autoloader

COPY . .
RUN chmod +x artisan

RUN composer dump-autoload --optimize && composer run-script post-install-cmd

CMD php artisan serve --host 0.0.0.0 --port 5001

When I build, this seems to work great. I see the dependencies getting downloaded, I see the autoload file being generated in the output. However, once the build is complete, the vendor folder is not actually there. I'm guessing it was all done in an intermediate container which was then removed? So when I run docker-compose up, I get: Fatal error: require(): Failed opening required '/var/www/html/bootstrap/../vendor/autoload.php'

This thread seems to point to the issue - possibly - but doesn't really provide a solution: https://stackoverflow.com/questions/43769756/composer-install-doesnt-install-packages-when-running-in-dockerfile

Docker Solutions


Solution 1 - Docker

This took a lot of digging for someone new to Docker :) Thanks to @iurii-drozdov for pointing me in the right direction with the comment about the docker-compose.yml.

In my docker-compose.yml, I was mounting my host working dir into /var/www/html. This happened after the build. So composer ran the install, installed all the dependencies correctly on build, and then, when running docker-compose up, I was mounting my host dir into the container and wiping all those changes out.

The solution was to run composer install after mounting the volume. It's straight forward enough to do this by simply exec'ing into the container after bringing it up - running composer and any other package managers - then finally running the web server.

However, I found a neater solution. I changed my final CMD in the Dockerfile to:

CMD bash -c "composer install && php artisan serve --host 0.0.0.0 --port 5001"

This will run composer install and bring up the web server as a final part of the docker-compose up.

Credit for the solution here: https://stackoverflow.com/questions/44864852/docker-execute-command-after-mounting-a-volume

Solution 2 - Docker

You can also use the official dockerhub composer image.

This is an example of a multi-stage build with composer running first in a separate container. The resulting /app/vendor is copied to wherever you want in your final image.

FROM composer as builder
WORKDIR /app/
COPY composer.* ./
RUN composer install
...
FROM php:7.1-fpm-alpine
...
COPY --from=builder /app/vendor /var/www/vendor

Solution 3 - Docker

If you don't want to have the command in the Dockerfile, we found that the simplest way was to add this to our docker-compose file:

composer_installation:
  container_name: composer_installation
  image: composer
  volumes:
    - ./:/app
  command: composer install --ignore-platform-reqs

The update is a bit slow, probably because it is syncing with the PHP container.

Solution 4 - Docker

As per the recommendations from https://hub.docker.com/_/composer

Run

WORKDIR /your/base/path
COPY --from=composer /usr/bin/composer /usr/bin/composer
RUN composer install

Solution 5 - Docker

I use this command and it generates the vendor :)

docker run --rm -it --volume $(pwd):/app prooph/composer:7.2 install --ignore-platform-reqs

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJBxOnlineView Question on Stackoverflow
Solution 1 - DockerJBxOnlineView Answer on Stackoverflow
Solution 2 - DockerPhilView Answer on Stackoverflow
Solution 3 - DockerKien TranView Answer on Stackoverflow
Solution 4 - DockerjontroView Answer on Stackoverflow
Solution 5 - DockerjaumebalustView Answer on Stackoverflow