为什么 composer 在我的 Docker 容器中找不到 composer.json 文件?
Why can't composer find a composer.json file inside my Docker container?
我有一个基于 Thelia's and Composer's 的非常简单的 Docker 文件。我希望它尽可能多地进行设置,因此为此,我在容器内的 PATH
中安装 composer
,然后尝试 运行 composer install
。但是,那时,容器中似乎还没有我的 local/mounted 文件(请参阅下面 RUN echo pwd: ...
的输出)。
构建失败并显示此错误消息:
Composer could not find a composer.json file in /var/www/html
To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section
ERROR: Service 'web' failed to build: The command '/bin/sh -c composer install' returned a non-zero code: 1
请注意,在没有 RUN composer install
指令的情况下构建然后 运行ning docker-compose exec web composer install
可以工作。
docker-compose.yml中声明的挂载是不是镜像构建完成后才会生效?我是否需要明确 COPY
我的本地文件才能在构建过程中看到它们?
Docker文件:
FROM php:5.6-apache
COPY docker-php-pecl-install /usr/local/bin/
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libmcrypt-dev \
libpng12-dev \
libicu-dev \
git \
zip \
libzip-dev \
&& docker-php-ext-install intl pdo_mysql mcrypt mbstring zip calendar \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install gd \
&& docker-php-pecl-install xdebug-2.3.3
RUN a2enmod rewrite
RUN usermod -u 1000 www-data
COPY config/php.ini /usr/local/etc/php/
COPY config/vhost/vhost.conf /etc/apache2/sites-enabled/
# Expose webroot
VOLUME /var/www/html
WORKDIR /var/www/html
COPY . /var/www/html # Added at Edit 1
# Allow Composer to be run as root
ENV COMPOSER_ALLOW_SUPERUSER 1
# Setup the Composer installer
RUN curl -o /tmp/composer-setup.php https://getcomposer.org/installer \
&& curl -o /tmp/composer-setup.sig https://composer.github.io/installer.sig \
&& php -r "if (hash('SHA384', file_get_contents('/tmp/composer-setup.php')) !== trim(file_get_contents('/tmp/composer-setup.sig'))) { unlink('/tmp/composer-setup.php'); echo 'Invalid installer' . PHP_EOL; exit(1); }" \
&& php /tmp/composer-setup.php \
&& chmod a+x composer.phar \
&& mv composer.phar /usr/local/bin/composer
# Install composer dependencies
RUN echo pwd: `pwd` && echo ls: `ls` # outputs:
# pwd: /var/www/html
# ls:
RUN composer install
docker-compose.yml:
web:
build: ./docker/php
ports:
- "8002:80"
links:
- mariaDB
environment:
SYMFONY_ENV: dev
command: /usr/sbin/apache2ctl -D FOREGROUND
volumes:
- .:/var/www/html
mariaDB:
...
编辑 1 - 在COPY
显式编辑文件后
我在 VOLUME
和 WORKDIR
指令后添加了一个 COPY . /var/www/html
,发现有些奇怪。现在 RUN pwd: ...
指令回显:
pwd: /var/www/html
ls: Dockerfile config docker-php-pecl-install
这是我的docker/php目录的内容,不是项目根目录!
完整(大概)目录结构:
.
├── LICENSE.txt
├── Readme.md
├── Thelia
├── bin
│ └── ...
├── bootstrap.php
├── cache
│ └── ...
├── change-version.sh
├── composer.json
├── composer.lock
├── docker
│ └── php
│ ├── Dockerfile
│ ├── config
│ └── docker-php-pecl-install
├── docker-compose.yml
├── lib
│ └── Thelia
│ └── Project
├── local
│ └── ...
├── log
├── templates
│ └── ...
├── vendor
│ └── ...
└── web
├── favicon.ico
├── index.php
├── index_dev.php
└── robots.txt
所以我修改后的问题是:如何从我 运行 docker-compose
的上下文中告诉 Docker 到 COPY
? 我认为这是 docker-compose
的默认行为,这就是我在过去项目中的工作方式...
您定义了一个 docker-compose 1.7 文件:
web:
build: ./docker/php
这基本上导致:
docker build -f ./docker/php/Dockerfile ./docker/php/
所以基本上构建路径是构建过程的上下文。
如果你真的想定义上下文,你必须将你的 docker-compose 定义升级到至少 v2 or v3。
你应该可以做到:
version: '2'
services:
web:
build:
context: ./
dockerfile: ./docker/php/Dockerfile
我建议不要这样做:
- 每当编辑 Dockerfile 时,您总是必须记住父文件夹的上下文结构,这将很难维护
- 随着上下文变得越来越大,您将通过向容器构建的上下文发送大量数据来减慢构建过程。
.dockerignore
文件会有所帮助,但您必须将其用作白名单而不是黑名单。
如果你想构建多个 php 容器,这些容器都使用你的 docker-php-pecl-install
文件安装依赖项,我建议你不要注入上帝上下文,而是创建一个基础 php 图像来自它自己的 Dockerfile,然后您在其他容器 Dockerfile 中将其引用为 FROM
源。该基础图像可以是一个不相关的项目,您需要做的就是构建一个图像,并在不同的其他 php 项目中重复使用。
如果您想在整个公司重复使用该映像,设置私有 docker 注册表会很有帮助,您和您的团队可以从中推送和拉取映像。
我有一个基于 Thelia's and Composer's 的非常简单的 Docker 文件。我希望它尽可能多地进行设置,因此为此,我在容器内的 PATH
中安装 composer
,然后尝试 运行 composer install
。但是,那时,容器中似乎还没有我的 local/mounted 文件(请参阅下面 RUN echo pwd: ...
的输出)。
构建失败并显示此错误消息:
Composer could not find a composer.json file in /var/www/html
To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section
ERROR: Service 'web' failed to build: The command '/bin/sh -c composer install' returned a non-zero code: 1
请注意,在没有 RUN composer install
指令的情况下构建然后 运行ning docker-compose exec web composer install
可以工作。
docker-compose.yml中声明的挂载是不是镜像构建完成后才会生效?我是否需要明确 COPY
我的本地文件才能在构建过程中看到它们?
Docker文件:
FROM php:5.6-apache
COPY docker-php-pecl-install /usr/local/bin/
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libmcrypt-dev \
libpng12-dev \
libicu-dev \
git \
zip \
libzip-dev \
&& docker-php-ext-install intl pdo_mysql mcrypt mbstring zip calendar \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install gd \
&& docker-php-pecl-install xdebug-2.3.3
RUN a2enmod rewrite
RUN usermod -u 1000 www-data
COPY config/php.ini /usr/local/etc/php/
COPY config/vhost/vhost.conf /etc/apache2/sites-enabled/
# Expose webroot
VOLUME /var/www/html
WORKDIR /var/www/html
COPY . /var/www/html # Added at Edit 1
# Allow Composer to be run as root
ENV COMPOSER_ALLOW_SUPERUSER 1
# Setup the Composer installer
RUN curl -o /tmp/composer-setup.php https://getcomposer.org/installer \
&& curl -o /tmp/composer-setup.sig https://composer.github.io/installer.sig \
&& php -r "if (hash('SHA384', file_get_contents('/tmp/composer-setup.php')) !== trim(file_get_contents('/tmp/composer-setup.sig'))) { unlink('/tmp/composer-setup.php'); echo 'Invalid installer' . PHP_EOL; exit(1); }" \
&& php /tmp/composer-setup.php \
&& chmod a+x composer.phar \
&& mv composer.phar /usr/local/bin/composer
# Install composer dependencies
RUN echo pwd: `pwd` && echo ls: `ls` # outputs:
# pwd: /var/www/html
# ls:
RUN composer install
docker-compose.yml:
web:
build: ./docker/php
ports:
- "8002:80"
links:
- mariaDB
environment:
SYMFONY_ENV: dev
command: /usr/sbin/apache2ctl -D FOREGROUND
volumes:
- .:/var/www/html
mariaDB:
...
编辑 1 - 在COPY
显式编辑文件后
我在 VOLUME
和 WORKDIR
指令后添加了一个 COPY . /var/www/html
,发现有些奇怪。现在 RUN pwd: ...
指令回显:
pwd: /var/www/html
ls: Dockerfile config docker-php-pecl-install
这是我的docker/php目录的内容,不是项目根目录!
完整(大概)目录结构:
.
├── LICENSE.txt
├── Readme.md
├── Thelia
├── bin
│ └── ...
├── bootstrap.php
├── cache
│ └── ...
├── change-version.sh
├── composer.json
├── composer.lock
├── docker
│ └── php
│ ├── Dockerfile
│ ├── config
│ └── docker-php-pecl-install
├── docker-compose.yml
├── lib
│ └── Thelia
│ └── Project
├── local
│ └── ...
├── log
├── templates
│ └── ...
├── vendor
│ └── ...
└── web
├── favicon.ico
├── index.php
├── index_dev.php
└── robots.txt
所以我修改后的问题是:如何从我 运行 docker-compose
的上下文中告诉 Docker 到 COPY
? 我认为这是 docker-compose
的默认行为,这就是我在过去项目中的工作方式...
您定义了一个 docker-compose 1.7 文件:
web:
build: ./docker/php
这基本上导致:
docker build -f ./docker/php/Dockerfile ./docker/php/
所以基本上构建路径是构建过程的上下文。
如果你真的想定义上下文,你必须将你的 docker-compose 定义升级到至少 v2 or v3。
你应该可以做到:
version: '2'
services:
web:
build:
context: ./
dockerfile: ./docker/php/Dockerfile
我建议不要这样做:
- 每当编辑 Dockerfile 时,您总是必须记住父文件夹的上下文结构,这将很难维护
- 随着上下文变得越来越大,您将通过向容器构建的上下文发送大量数据来减慢构建过程。
.dockerignore
文件会有所帮助,但您必须将其用作白名单而不是黑名单。
如果你想构建多个 php 容器,这些容器都使用你的 docker-php-pecl-install
文件安装依赖项,我建议你不要注入上帝上下文,而是创建一个基础 php 图像来自它自己的 Dockerfile,然后您在其他容器 Dockerfile 中将其引用为 FROM
源。该基础图像可以是一个不相关的项目,您需要做的就是构建一个图像,并在不同的其他 php 项目中重复使用。
如果您想在整个公司重复使用该映像,设置私有 docker 注册表会很有帮助,您和您的团队可以从中推送和拉取映像。