2
votes

I cannot seem to run composer install in Dockerfile but I can in the container after building an image and running the container.

Here's the command from Dockerfile:

RUN composer require drupal/video_embed_field:1.5
RUN composer install --no-autoloader --no-scripts --no-progress

The output is:

Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Nothing to install or update

But after running the container with docker-compose:

...
drupal:
    image: docker_image
    container_name: container
    ports:
      - 8081:80
    volumes:
      - ./container/modules:/var/www/html/web/modules

    links:
      # Link the DB container:
      - db

running docker exec composer install will install the packages correctly:

Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Package operations: 1 installs, 0 updates, 0 removals
...
Generating autoload files

I am assuming that the composer.json and composer.lock files are correct because I can run the composer install command in the container without any further effort, but only after the container is running.

Update Tried combining the composer commands with:

RUN composer require drupal/video_embed_field:1.5 && composer install

Same issue, "Nothing to install or update". Ultimately I would like to continue using seperate RUN statements in Dockerfile to take advantage of docker caching.

2
Try to use only one RUN, like RUN composer...&& composer...user2915097
Tried it, no luck. Updated question to include details.Chris Mitchell
That is because your composer.lock and composer.json are on the mounted volume, I guess ? Then, the reason is the mount actually happen after you image is created, so after your two RUN statementsβ.εηοιτ.βε
So you're saying the composer.lock and .json files do not exist until after docker image is created? Is this because of the mount?Chris Mitchell
Yes indeed. If you do a COPY of those files that may actual get you somewhere. That said, the mounted source folder will totally override the mounting point so you could end up expecting a vendor folder and not have it. What you should ideally do is to have it as the ENTRYPOINT, this one actually happens at the last step of the container bootingβ.εηοιτ.βε

2 Answers

7
votes

Your issue is coming from the fact that, docker-compose is meant to orchestrate multiple docker container build and run at the same time and it somehow is not really showing easily what it does behind the scene to people starting with docker.

Behind a docker-compose up there are four steps:

  • docker-compose build if needed, and if there is no existing image(s) yet, create the image(s)
  • docker-compose create if needed, and if there is no container(s) existing yet, create the container(s)
  • docker-compose start start existing container(s)
  • docker-compose logs logs stderr and stdout of the containers

So what you have to spot on there, is the fact that action contained into you Dockerfile are executed at the image creation step.
When mounting folders is executed at start of containers step.

So when you try to use a RUN command, part of the image creation step, on files like composer.lock and composer.json that are mounted on starting step, you end up having nothing to install via composer because your files are not mounted anywhere yet.

If you do a COPY of those files that may actual get you somewhere, because you will then have the composer files as part of your image.

This said, be careful that the mounted source folder will totally override the mounting point so you could end up expecting a vendor folder and not have it.
What you should ideally do is to have it as the ENTRYPOINT, this one happens at the last step of the container booting.

Here is for a little developing comparison: a docker image is to a docker container what a class is to an instance of an class — an object.
Your container are all created from images built possibly long time before.
Most of the steps in your Dockerfile happens at image creation and not at container boot time.
While most of the instruction of docker-compose are aimed at the automatisation of the container build, which include the mounting of folders.

0
votes

Just noting a docker-compose.yml approach to the issue when the volume mount overwrites the composer files inside the container:

docker-compose.yml

environment:
  PROJECT_DIR: /var/www/html
volumes:
  - ./php/docker/entrypoint/90-composer-install.sh:/docker-entrypoint-init.d/90-composer-install.sh

composer-install.sh

#!/usr/bin/env bash

cd ${PROJECT_DIR}
composer install

This runs composer install after the build, using the docker-entrypoint-init.d shell script