8

I want to copy all files during the installation process in docker-compose.yml file.

If I run:

$ git clone https://github.com/laravel/laravel.git laravel-app
$ cd laravel-app
$ docker run --rm -v $(pwd):/app composer install

It will copy all new files from container to host during the installation process in the docker container.

So I will see new vendor folder and composer.lock file in my laravel-app directory after installation.


But if I setup volume in docker-compose.yml:

version: '3'
services:

  #PHP Service
  app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: app
    restart: unless-stopped
    tty: true
    environment:
      SERVICE_NAME: app
      SERVICE_TAGS: dev
    working_dir: /var/www
    volumes:
      - ./:/var/www
      - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
    networks:
      - app-network

And then setup installation process in Dockerfile:

FROM php:7.4.4-fpm

# Set working directory
WORKDIR /var/www

# Install dependencies
RUN apt-get update && apt-get install -y

# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# Copy existing application directory contents
COPY . /var/www

# Install composer.json dependencies
RUN composer install # <<-- !this one!

It will not copy vendor folder and composer.lock file back to my host.

Hot to make it happen?

mr.boris
  • 3,667
  • 8
  • 37
  • 70
  • 1
    Have you tried running composer install before the copy? Just a thought. Let me answer if it's correct – Jonathan Apr 16 '20 at 22:54
  • 2
    Your problem stems from a misunderstanding in how volumes work during **build-time** vs **run-time**. I had this same problem a short time ago, and it took me a while to figure out. The problem is, [volumes don't take effect during the build phase](https://vsupalov.com/cache-docker-build-dependencies-without-volume-mounting/). Anything that you create during a build almost seemingly "disappears" until you re-run the commands via `docker run` or `docker-compose run`. There's a couple of ways around this, but it could get pretty hairy depending on what you want to do. – maiorano84 Apr 16 '20 at 23:27
  • If you want to get files to install onto the host machine automagically when running the container, you'll want to create a custom Entrypoint script. This executes during run-time, and you can set up your own custom Bash / Shell scripts to execute any commands you need before running the command the user specifies. In this case, you can check for the existence of the necessary file structure, and if it doesn't exist, the files will be created in the working directory and automatically saved to the volume mount. – maiorano84 Apr 16 '20 at 23:30
  • @Jonathan yes, but it fails because `composer install` process requires all files of git repo cloned before (application directory contents), not just `composer.json` file. – mr.boris Apr 17 '20 at 07:13
  • @maiorano84 thank you for explanation. I got it a couple of hours after :) So, is there any possibility to force copying files back to host during `docker-compose` build process? It would be very handy. May be I should specify just some flag? Or can I add one more command after `RUN composer install` step like so `COPY app:/var/www/. ./` ? – mr.boris Apr 17 '20 at 07:19
  • @mr.boris As of today, nothing stable. There's an [answer here](https://stackoverflow.com/questions/26050899/how-to-mount-host-volumes-into-docker-containers-in-dockerfile-during-build) that goes into greater detail about this and some possible build steps you might be able to use as experimental features, but I've personally never known about or used them before. – maiorano84 Apr 17 '20 at 13:57

2 Answers2

4

how about add composer docker image to your docker compose, and run command install

version: '3'
services:
    #PHP Service
    #your php image

    # composer
    composer:
      image: composer/composer
      volumes:
        - ./:/var/www
      command: install
Aswita Hidayat
  • 129
  • 1
  • 5
  • 1
    Thanks for idea, it's even clearer approach to include composer into project. But I think it will not solve the main problem because `docker-compose` still will not copy files to the host during building the image as @maiorano84 mentioned before. – mr.boris Apr 17 '20 at 10:03
3
  • You copy all build context into your image /var/www

  • You run composer install from the image, so vendor and composer.lock only exist in the image, not on your host

  • You bind mount your current directory(which has composer.json but not vendor and composer.lock) to /var/www, so it replaces the image /var/www

You know your issue, the fix depends on what you want to do exactly, tell me in a comment.

Tip: You should use Docker multi-stage builds to install Composer into your image. It's much cleaner than the curl

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

COPY . /var/www/

RUN composer install --no-scripts --no-suggest --optimize-autoloader
Shizzen83
  • 3,325
  • 3
  • 12
  • 32
  • Thanks for multi-stage build tip. I want to copy files from container to host during docker-compose build on step `RUN composer install` automatically. Something like `COPY app:/var/www/. ./` may be. – mr.boris Apr 17 '20 at 07:08