Why is my volume not copying over to its docker container? - php

I am trying to run a webserver container with nginx and a php-fpm server running a Laravel application. The directory houses a frontend and backend directory so my paths are not off in the configuration files.
I setup a docker-compose.yml file
version: '2'
services:
webserver:
build:
context: ./
dockerfile: webserver.docker
volumes:
- /home/colesam/Documents/code/todo/backend:/var/www
ports:
- "8080:80"
links:
- backend
backend:
build:
context: ./
dockerfile: backend.docker
volumes:
- ./home/colesam/Documents/code/todo/backend:/var/www
And php-fpm Dockerfile (backend.docker)
FROM php:7.2-fpm
RUN apt-get update -y && apt-get install -y libmcrypt-dev openssl
RUN pecl install mcrypt-1.0.2
RUN docker-php-ext-enable mcrypt
RUN docker-php-ext-install pdo mbstring
RUN apt-get install -y apt-transport-https
RUN apt-get install -y curl
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
RUN chown -R www-data:www-data /var/www
VOLUME ["/var/www"]
RUN ls -al /var/www
WORKDIR /var/www
RUN composer install
And the nginx webserver Dockerfile (webserver.docker)
FROM nginx:1.10
ADD ./vhost.conf /etc/nginx/conf.d/default.conf
WORKDIR /var/www
For some reason when I run docker-compose up -d --build I always fail at this step of the build process:
Step 13/13 : RUN composer install
---> Running in 65bb97f03004
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Composer could not find a composer.json file in /var/www
To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section
ERROR: Service 'backend' failed to build: The command '/bin/sh -c composer install' returned a non-zero code: 1
From the last line of the output it looks like it failed because /var/www/was empty and didn't have the files copied over like composer.json. I looked around a lot and this stackoverflow issue seemed to be the most related to what was happening but I think I'm already following everything the accepted answer suggests.
Do I need to include a COPY or ADD command even though I'm mounting the folder through a volume?

The build phase does not see any mounted volumes. The only thing that is available to "build" are the things defined in the backend.docker and in the compose section of build:
build:
context: ./
dockerfile: backend.docker
Do I need to include a COPY or ADD command even though I'm mounting the folder through a volume?
Yes, modify your backend.docker similar to this
...
WORKDIR /var/www
ADD composer.json .
RUN composer install

Related

failed to solve: executor failed running [/bin/sh -c composer install]: exit code: 1

Trying to run composer install during docker compose build from inside the php container, but it errors out at the end acting like the composer.json file isn't there. However if I comment out the last line in the Dockerfile (ie. RUN composer install), then do something like, docker exec -it <container name> bash, manually run composer install from inside the container where /var/www/html/composer.json does in fact exist it works.
Dockerfile
FROM php:7.4-apache
COPY --from=composer /usr/bin/composer /usr/bin/composer
RUN docker-php-ext-install pdo_mysql mysqli
RUN a2enmod rewrite
WORKDIR /var/www/html
## install and run composer so that this test is self contained
RUN apt-get update
RUN apt-get install -y git
RUN composer install
Produces the following
=> ERROR [stage-0 8/8] RUN composer install 0.5s
------
> [stage-0 8/8] RUN composer install:
#0 0.437 Do not run Composer as root/super user! See https://getcomposer.org/root for details
#0 0.446 Composer could not find a composer.json file in /var/www/html
#0 0.446 To initialize a project, please create a composer.json file. See https://getcomposer.org/basic-usage
------
failed to solve: executor failed running [/bin/sh -c composer install]: exit code: 1
In case it's important this is the docker-compose.yml file
version: "3.9"
services:
php:
build: ./docker/php
volumes:
- ./src:/var/www/html
ports:
- 8080:80
restart: unless-stopped
mysql:
image: mariadb
volumes:
- ./docker/sql:/docker-entrypoint-initdb.d/
ports:
- 3306:3306
environment:
MARIADB_ROOT_PASSWORD: xxx
MARIADB_DATABASE: xxx
MARIADB_USER: xxx
MARIADB_PASSWORD: xxx
restart: unless-stopped
You're already pretty close with your container build directives, it's just that I'd say you only need the composer.json during the build and you actually need to have the vendor folder in the service container afterwards.
It's bascially two commands:
First update the build instructions:
<<'DOCKERFILE' tee Dockerfile >/dev/null && git add Dockerfile && git commit -m 'add composer install to build'
ARG ver=7.4
FROM php:$ver-cli
COPY --from=composer /usr/bin/composer /usr/bin/composer
COPY composer.json composer.json
RUN set -ex ; \
apt-get update ; \
apt-get install -y git zip ; \
composer -n validate --strict ; \
composer -n install --no-scripts --ignore-platform-reqs --no-dev
ARG ver=7.4
FROM php:$ver-apache
RUN set -ex ; \
docker-php-ext-install pdo_mysql mysqli ; \
a2enmod rewrite
COPY --from=0 vendor vendor
DOCKERFILE
Then build the container (this time with the composer.json file):
git archive --format tar HEAD Dockerfile composer.json | docker build --no-cache --rm --force-rm --tag my:build -
You'll see it run through. And given the composer.json file actually exists for the build context, then validates within the build container and you don't have any networking issues this should do it. You have not shared your build context properties, so this is the bare minimum for composer in docker (Dockerfile + composer.json).
Mind the PHP version in use, you find it parameterized so that the version can be controlled. Time to step away from PHP 7.4 which is going EOL soon. Docker Compose supports build parameters so you can do that in different working trees.
And here the takeaway: If you want more files from context, add them to the context and remember that when you need to copy from the context into the container again, there must be no --from option, that is only to copy from other containers (either intermediate stages or from the container repository). You can control all that with the Dockerfile as you had it already and additionally shown again above.

Using RUN in Dockerfile to install Laravel inside a php image is not working

I am trying to install Laravel inside a php container using this line on my Dockerfile:
RUN composer create-project laravel/laravel=8.* . --prefer-dist
My goal is to install it on my container directory /var/www/html. My first assumption is that by using . , the command ran on the current working directory, which is /var/www/html itself. And actually, it works when I go inside the container and run the command there. But, when building using the Dockerfile, seems that it doesn't install anything anywhere. On the contrary, the message I got on the terminal looked like the command ran successfully:
=> [stage-0 6/6] RUN composer create-project laravel/laravel=8.* . --prefer-dist
Currently my docker-compose.yaml looked like this:
version: '3.8'
services:
# PHP + Apache Service
php-apache:
build:
context: ./php-apache
working_dir: /var/www/html
ports:
- 80:80
volumes:
- ./src/:/var/www/html
- ./php-apache/apache2.conf:/etc/apache2/apache2.conf
- ./php-apache/000-default.conf:/etc/apache2/sites-available/000-default.conf
depends_on:
mysql:
condition: service_healthy
# other services and volumes...
Also my Dockerfile:
FROM php:8.1-apache
# Mysql driver on php
RUN docker-php-ext-install pdo pdo_mysql mysqli
# Composer
RUN apt-get update && apt-get install -y git zip
COPY --from=composer:2.2.2 /usr/bin/composer /usr/bin/composer
# Node.js
RUN apt-get update && apt-get install -y nodejs npm
# Laravel
RUN composer create-project laravel/laravel=8.* . --prefer-dist
I already set the working_dir to /var/www/html. Why is that the case here?
You could use the entry point script to run scripts after the container has started.
Create a bash script in the same location where you have Dockerfile.
start-container.sh
#!/usr/bin/env bash
#This will try to install laravel in /var/www/html/new-laravel if folder does not exists
composer create-project laravel/laravel=8.* /var/www/html/new-laravel --prefer-dist
#If your container gets exited, then consider restarting apache, here is an #example
#service php7.4-fpm start && nginx -g "daemon off;"
Remember to make the bash script executable, run the command before you run docker-compose build
chmod u+x start-container.sh
Then in your Dockerfile towards the end add:
ENTRYPOINT ["start-container"]
Then:
docker-compose stop && docker-compose build && docker-compose up -d

composer install not working php-alpine docker

I am using php FPM alpine container with nginx alpine container for my laravel application.
Here is my Dockerfile,
FROM php:7.4-fpm-alpine
WORKDIR /usr/src/app
# install composer
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
RUN php composer-setup.php --install-dir=/usr/local/bin --filename=composer
RUN php -r "unlink('composer-setup.php');"
# copy files
COPY ./ /usr/src/app/
# install packages
ENV COMPOSER_ALLOW_SUPERUSER 1
RUN composer install
Here is my docker-compose file,
version: "3.7"
services:
web:
image: nginx:1.19-alpine
ports:
- 80:80
volumes:
- ../api:/usr/src/app
- ./site.conf:/etc/nginx/conf.d/site.conf
depends_on:
- api
api:
build: ../api
volumes:
- ../api:/usr/src/app
When I run docker-compose up --build the container build process works as you can see in the attached screenshot but the vendor directory was never created by the composer!?
Is it a known issue while using PHP FPM Alpine containers?
Also, when I access into the container using this command
docker exec -it docker_api_1 /bin/ash
and run composer install manually then everything works. Any suggestions are appreciated.
This is the error message when i visit the site. It can't find the composer autoload.php file,

Composer install with dockerfile

I'm pretty new with docker, I try to automatically execute composer install within my Dockerfile but it seems that I can't cd into my application while installing, what's wrong? Or maybe there is another better way to do that?
my docker-compose.yml
version: "3.1"
services:
app:
image: nginx:alpine
container_name: app
working_dir: /application
volumes:
- ./Projects/app:/application/app
- ./Docker/nginx/app.conf:/etc/nginx/conf.d/app.conf
ports:
- "8080:8080"
php-fpm-app:
build: Docker/php-fpm-app
container_name: php-fpm-app
working_dir: /application
volumes:
- ./Projects:/application
- ./Docker/php-fpm-app/php-ini-overrides.ini:/etc/php/7.2/fpm/conf.d/99-overrides.ini
my Dockerfile
FROM phpdockerio/php72-fpm:latest
WORKDIR "/application"
# Fix debconf warnings upon build
ARG DEBIAN_FRONTEND=noninteractive
RUN mkdir -p /var/www/.composer \
&& chown -R www-data:www-data /var/www/.composer
USER www-data
RUN cd /application/app; composer install
The output after I run this command:
docker-compose up -d
Step 6/6 : RUN cd /application/app; composer install
---> Running in ac53e653af46
/bin/sh: 1: cd: can't cd to /application/app
Composer could not find a composer.json file in /application
To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section
ERROR: Service 'php-fpm-app' failed to build: The command '/bin/sh -c cd /application/app; composer install' returned a non-zero code: 1
If I try to remove the last line from my Dockerfile, once it's up and running if I run this command:
docker-compose exec --user www-data php-fpm-app bash -c 'cd
/application/app && composer install'
It works, I don't understand why I can't do this with my Dockerfile.
===========================
Finally
I find a way to execute a script but I don't see the output, so if the script last for many secondes/minutes I won't know when it's done.
ADD ./setup.sh /setup.sh
RUN chmod +x /setup.sh
CMD ["sh", "/setup.sh"]
I decided to execute this script manually once all it's up and running
sh ./setup.sh
You should not run composer install in Dockerfile. It will fail because you have not created/synced volume from the local to container yet. Thus all files including composer.json is not placed under /var/www/html.
What you can do is to add 1 line (command) into your docker-compose.yaml file inside the service eg.
services:
api-php-fpm:
build: ./docker/php-fpm
command: sh -c "composer install"
This is because the volumes aren't mounted until the build is complete. Just use COPY to copy only the composer.json into the folder, and run the composer install as normal.
Referencing the Documentation for Dockerfiles you need to edit your Dockerfile.
it should be:
WORKDIR /application/app
RUN composer install
Does this fix your problem?

Docker - Using Composer inside PHP container

I want to be able to use composer install inside my php-fpm container. My current setup:
docker-compose.yml
version: '2'
services:
web:
image: nginx
ports:
- "80:80"
volumes:
- ./public:/var/www/html
- ./vhost.conf:/etc/nginx/conf.d/vhost.conf
fpm:
image: php:fpm
volumes:
- ./public:/var/www/html
expose:
- 9000
composer:
restart: 'no'
image: composer/composer
command: install --working-dir=/var/www/html
volumes_from:
- fpm
But obviously my command: install is happening in the composer container and doesnt have the required php extensions to complete the install.
And composer install inside php-fpm container says composer is not installed
Somehow google doesn't have an answer for this from what I have seen.
You just need to install composer inside your fpm container.
Something like
FROM php:5.6-fpm
...
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
&& php composer-setup.php --install-dir=/usr/local/bin --filename=composer \
&& php -r "unlink('composer-setup.php');"
A more sexy way yo add composer into your image :
# Install Composer
ADD https://getcomposer.org/installer /tmp/composer-setup.php
RUN php /tmp/composer-setup.php --install-dir /usr/local/bin/ --filename composer \
&& rm /tmp/composer-setup.php
Note that composer can be useful for development images (eg: For Continuous Integration or tests). A production image should not have composer inside... Only the generated vendors :)
Actually what I would suggest would be a separate lightweight php-cli container just to run composer (and other commands). It doesn't have to run a "persistent" way. If interested have a look how I did my image for running php tasks like composer or phpunit.
docker run -ti --rm -v /path/to/your/project:/app kmwrona/ci-stack /usr/bin/composer install --quiet
docker run -ti --rm -v /path/to/your/project:/app kmwrona/ci-stack /usr/bin/composer dump-autoload --optimize
docker run -ti -a STDOUT -v /path/to/your/project:/app kmwrona/ci-stack /usr/bin/phpunit --log-junit /app/junit.xml --testdox-html /app/unit-tests-html-report.html

Categories