简体   繁体   中英

How to install composer dependencies in a container?

What I'm trying to do

I'm trying to dockerize this php application builded on CodeIgniter 4. This app have the following dependencies which are normally installed via composer:

"require": {
    "php": "^7.3 || ^8.0",
    "myth/auth": "dev-develop",
    "codeigniter4/framework": "^4.1",
    "codeigniter4/translations" : "^4.0"
},

The project structure is organized as follows:

docker
    database
    nginx
    php-fpm
    docker-compose.yml
src
    ... app files ...
tests
composer.json

inside the docker-compose.yml I have a service called php-fpm which copies all the app files to /var/www/html that is the nginx public directory:

php-fpm:
  container_name: boilerplate_app
  build:
    context: ./php-fpm
  volumes:
    - ../src:/var/www/html

What I need to do is install the application dependencies using composer.

What I tried

Initially, I though to do this inside the Dockerfile available in php-fpm folder:

FROM php:8.0.2-fpm-alpine

RUN docker-php-ext-install pdo_mysql
RUN docker-php-ext-install mysqli    

# Install Composer
COPY --from=composer /usr/bin/composer /usr/bin/composer

RUN composer require --working-dir=../../ app/boilerplate

COPY ./config/php.ini /usr/local/etc/php/

CMD ["php-fpm"]

EXPOSE 9000

Essentially I have installed composer in the container and then I tried to install all the dependencies from the composer.json file available in the root of the project.

The issue

Unfortunately, when I run the command docker-compose up --build this error is raised:

No composer.json present in the current directory (./composer.json), this may be the cause of the following exception.

seems that the container cannot access to the composer.json file or I'm doing something bad with the path parameter working-dir .

So, I though to another solution, define another container inside docker-compose.yml which have the composer instance separated:

composer:
  image: composer:2.0.9
  command: ["composer", "require", "app/boilerplate"]
  volumes:
    - /var/www/html

This should read the composer.json file from the root and then should install all the dependencies through the command composer require app/boilerplate , but again, the same error is raised:

Composer could not find a composer.json file in /app .

This is the full docker-compose.yml :

version: '3'

services:
  php-fpm:
    container_name: boilerplate_app
    build:
      context: ./php-fpm
    volumes:
      - ../src:/var/www/html

  nginx:
    container_name: boilerplate_nginx
    build:
      context: ./nginx
    volumes:
      - ../src:/var/www/html
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/sites/:/etc/nginx/sites-available
      - ./nginx/conf.d/:/etc/nginx/conf.d
    ports:
      - "8881:80"
      - "8882:443"
    depends_on:
      - php-fpm

  database:
    container_name: boilerplate_db
    build:
      context: ./database
    environment:
      - MYSQL_DATABASE=boilerplate_db
      - MYSQL_ROOT_PASSWORD=test
      - MYSQL_USER=foo
      - MYSQL_PASSWORD=test
    volumes:
      - ./database/data.sql:/docker-entrypoint-initdb.d/data.sql

  composer:
    image: composer:2.0.9
    command: ["composer", "require", "app/boilerplate"]
    volumes:
      - /var/www/html

and this is the composer.json file:

{
    "name": "app/boilerplate",
    "description": "CodeIgniter4 Boilerplate based on AdminLTE 3 with user management, roles, permissions, ...",
    "require": {
        "php": "^7.3 || ^8.0",
        "myth/auth": "dev-develop",
        "codeigniter4/framework": "^4.1",
        "codeigniter4/translations" : "^4.0"
    },
    "require-dev": {
        "phpunit/phpunit": "^9.1",
        "fakerphp/faker": "^1.13"
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "autoload": {
        "psr-4": {
            "app\\boilerplate\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    },
    "scripts": {
        "post-update-cmd": [
          "@composer dump-autoload"
        ],
        "test": "phpunit --colors=always -vvv"
    }
}

what I can do for fix the problem?

Folder structure image preview:

在此处输入图像描述

Seems you have a couple of problems.

First, you are relying on bind mounts. But those are available at run-time , but not at build-time .

So you need to copy the composer.* files to your docker image before you run composer install .

And then, you'll have trouble doing so because you moved the build context to a subdirectory of your project, which would make copying files from parent directories problematic.

To begin with, change the build context, and simply reference the Dockerfile you need to build your project:

services:
  php-fpm:
    container_name: boilerplate_app
    build:
      dockerfile: ./php-fpm/Dockerfile
      context: .
    volumes:
      - ./src:/var/www/html
# the rest of your docker-compose.yml

After you do this, you need to adjust your Dockerfile to account that now its build context is one directory up, and add the required COPY statements.

I've also updated the dockerfile to take advantage of Docker multi-stage process

FROM composer:2 as composer_stage

RUN rm -rf /var/www && mkdir -p /var/www/html
WORKDIR /var/www/html

COPY composer.json composer.lock ./

# This are production settings, I'm running with 'no-dev', adjust accordingly 
# if you need it
RUN composer install --ignore-platform-reqs --prefer-dist --no-scripts --no-progress --no-interaction --no-dev --no-autoloader

RUN composer dump-autoload --optimize --apcu --no-dev

FROM php:8.0.2-fpm-alpine

WORKDIR /var/www/html

RUN docker-php-ext-install pdo_mysql
RUN docker-php-ext-install mysqli

COPY php-fpm/config/php.ini /usr/local/etc/php/

COPY --from=composer_stage /var/www/html /var/www/html

COPY src src/

CMD ["php-fpm"]

EXPOSE 9000

I've also added a COPY statement to copy your projects src dir, because otherwise the image you are building has your composer dependencies, and nothing else. This way your application is a properly self-contained container (no pun intended).

You should also make sure src mountpoints. Since those do not really pertain to image building , but are only used when you are actually running the container, I didn't review them very carefully.

Dockerize/containerize an application is first and foremost about building the correct image, then you'll need to create the appropriate usage documentation

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM