I have a pretty straightforward Dockerfile based on Thelia's and Composer's. I want it to do as much setup as possible, so to that end, I am installing composer
in the PATH
within the container and then trying to run composer install
. However, at that point, it seems my local/mounted files don't exist within the container yet (see output from RUN echo pwd: ...
below).
The build fails with this error message:
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
Note that building without the RUN composer install
instruction and then running docker-compose exec web composer install
works.
Does the mount declared in docker-compose.yml not take effect until the image has been completely built? Do I need to explicitly COPY
my local files for them to be visible during the build process?
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
web:
build: ./docker/php
ports:
- "8002:80"
links:
- mariaDB
environment:
SYMFONY_ENV: dev
command: /usr/sbin/apache2ctl -D FOREGROUND
volumes:
- .:/var/www/html
mariaDB:
...
COPY
ing files explicitlyI added a COPY . /var/www/html
after the VOLUME
and WORKDIR
instructions, and noticed something weird. Now the RUN pwd: ...
instruction echoes:
pwd: /var/www/html
ls: Dockerfile config docker-php-pecl-install
This is the contents of my docker/php directory, not the project root!
Full(ish) directory structure:
.
├── 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
So my revised question is: how do I tell Docker to COPY
from the context in which I run docker-compose
? I thought this was the default behavior for docker-compose
, and that's how it's worked for me on past projects...
You define a docker-compose 1.7 file with:
web:
build: ./docker/php
which results basically in:
docker build -f ./docker/php/Dockerfile ./docker/php/
So basically the build path is the context of the build process.
If you really want to define the context, you have to upgrade your docker-compose defintion to at least v2 or v3.
There you should be able to do:
version: '2'
services:
web:
build:
context: ./
dockerfile: ./docker/php/Dockerfile
I would advise against that as:
.dockerignore
file would help, but you would have to use it as a whitelist instead of a blacklist.If you want to build multiple php containers that all install dependencies with your docker-php-pecl-install
file, I advise you to not inject a god context, but that your rather create a base php image from its own Dockerfile, which you then reference in the in the other's containers Dockerfile as the FROM
source. That base image can be an unrelated project, all you need it do to is built an image, and reused in different other php projects.
If you want to reuse that image in your entire company, it's helpful to setup a private docker registry, where you and your team can push and pull images from.