Running 'composer install' when container is created

The issue i’m facing is with either Dockerfile and docker-compose.yml file. My project is Laravel Lumen API
I’m trying to do a “composer install” in my project but for some reason it always results in either:

  1. vendor directory is not created or errors out about not finding a vendor directory
  2. vendor directory is created but it keeps running in an endless loop, running “composer install” forever

Here is my Dockerfile:

FROM "php:8.0.12-fpm"

# Arguments defined in docker-compose.yml
ARG user=user1
ARG uid=1000

# Install system dependencies
RUN apt-get update && apt-get install -y \
    git \
    curl \
    libpng-dev \
    libonig-dev \
    libxml2-dev \
    zip \
    unzip \
    vim

RUN apt-get update

# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

# Install PHP extensions
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd

# Create system user to run Composer and Artisan Commands
RUN useradd -G www-data,root -u $uid -d /home/$user $user
RUN mkdir -p /home/$user/.composer && \
    chown -R $user:$user /home/$user 


# Set working directory
WORKDIR /var/www
# Install composer
COPY --from=composer /usr/bin/composer /usr/bin/composer

USER $user

docker-compose.yml

version: "3.7"
services:
  app:
    build:
      args:
        user: user1
        uid: 1000
      context: ./
      dockerfile: Dockerfile
    container_name: backend-app
    restart: unless-stopped
    working_dir: /var/www/
    volumes:
      - ./:/var/www
    command: sh -c "composer install --ignore-platform-reqs && php artisan key:generate"
    networks:
      - backoffice

  nginx:
     image: nginx:1.17-alpine
     container_name: backend-nginx
     restart: unless-stopped
     ports:
       - "8000:80"
     volumes:
       - ./:/var/www
       - ./docker-compose/nginx:/etc/nginx/conf.d
     networks:
       - backoffice

  db:
    image: mysql:5.7
    container_name: backend-db
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: backend_db
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_PASSWORD: secret
      MYSQL_USER: dbuser
      SERVICE_NAME: mysql
    volumes:
      - ./docker-compose/mysql:/docker-entrypoint-initdb.d
    networks:
      - backoffice

networks:
  backoffice:
    driver: bridge

this command in docker-compose.yml:

command: sh -c "composer install --ignore-platform-reqs && php artisan key:generate"

results in the container installing and reinstalling composer install over and over, it never stops
if i try to put “RUN composer install” in my Dockerfile, the vendor directory doesnt get created.

i already tried dozens of ways in stackoverflow but the issue persists, composer install keeps looping.
My goal is to create the container and have the vendor directory created when the container is created,
I can simply bash into the container and run “composer install” and it runs fine, but i would like to automate this when the container is built without me having to get into the container and manually do a “composer install”.
Any hints/tips are welcome

Of course, because your restart policy makes sure the container is restarted right after the installation is finished.

I am sure it is created but then you mount your project folder into the container and overwrite everything.

You have the following options:

  • you use your docker image in production without mounting any folder to overwrite /var/www
  • use it in the development stage and run a container instance from the image, copy the vendor folder out from the container to the host and you can mount it back
  • mount only subdirectories like web and src or any subdirectory next to vendor but not the project root. It would work with symfony so I assume it works with Laraver too.

Hi,
I’m inside the container. But I can’t find the right Dockerfile.
When I locate the dockerfile, I have more than 6 files. I don’t know which to use.

Is it another way to do it without the Dockerfile ???

To do what? This topic is about PHP Composer. Can you explain what your problem is with composer? What do you need Dockerfile and why do you want to find it inside a container?

volumes:

  • .:/var/www
    - /var/www/vendor/

This prevents the first volume from overriding the contents.

1 Like