I have an assessment in which I have to create a Docker container with CakePHP. I already have a working Docker container with CakePHP and I run the following commands for my container:
docker-compose build
docker-compose run cakephp composer install --no-interaction
docker-compose run cakephp bin/cake migrations migrate
docker-compose run cakephp bin/cake migrations seed
docker-compose up
The goal is to reduce the process down to only running the single command docker-compose up to be able to start testing the container. I'm very new to both Docker and CakePHP so I'm not sure how to do this.
Any help is greatly appreciated!
Dockerfile
#start with our base image (the foundation) - version 7.1.29
FROM php:7.1.29-apache
#install all the system dependencies and enable PHP modules
RUN apt-get update && apt-get install -y \
gcc \
make \
autoconf \
libc-dev \
pkg-config \
libicu-dev \
libpq-dev \
libmcrypt-dev \
mysql-client \
git \
zip \
unzip \
&& rm -r /var/lib/apt/lists/* \
&& docker-php-ext-configure pdo_mysql --with-pdo-mysql=mysqlnd \
&& docker-php-ext-install \
intl \
mbstring \
mcrypt \
pcntl \
pdo_mysql \
pdo_pgsql \
pgsql \
opcache
RUN set -eux; apt-get update; apt-get install -y libzip-dev zlib1g-dev; docker-php-ext-install zip
#install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer
ENV COMPOSER_ALLOW_SUPERUSER=1
#set our application folder as an environment variable
ENV APP_HOME /var/www/html
#change uid and gid of apache to docker user uid/gid
RUN usermod -u 1000 www-data && groupmod -g 1000 www-data
#change the web_root to laravel /var/www/html/public folder
RUN sed -i -e "s/html/html\/webroot/g" /etc/apache2/sites-enabled/000-default.conf
# enable apache module rewrite
RUN a2enmod rewrite && \
echo "ServerName localhost" >> /etc/apache2/apache2.conf
#copy source files and run composer
COPY . $APP_HOME
# install all PHP dependencies
RUN composer install --no-interaction
#change ownership of our applications
RUN chown -R www-data:www-data $APP_HOME
docker-compose.yml
version: '2'
services:
cakephp:
build: .
depends_on:
- mysql
links:
- "mysql"
ports:
- "4000:80"
volumes:
- .:/var/www/html/
environment:
- SECURITY_SALT= *some salt here*
- MYSQL_URL=mysql
- MYSQL_USERNAME=root
- MYSQL_PASSWORD=root
mysql:
image: mysql:5.6
volumes:
- mysql-data:/var/lib/mysql
environment:
- MYSQL_DATABASE=cakephp
- MYSQL_ROOT_PASSWORD=root
volumes:
mysql-data:
Option 1
What I usually do to reduce my commands when handling Docker and Docker Compose in general is using a Makefile.
So, in your case, you could write something like:
Makefile
SUDO := $(shell groups | grep -q docker || echo sudo)
.PHONY: start
start:
$(SUDO) docker-compose build \
&& $(SUDO) docker-compose run cakephp composer install --no-interaction \
&& $(SUDO) docker-compose run cakephp bin/cake migrations migrate \
&& $(SUDO) docker-compose run cakephp bin/cake migrations seed \
&& $(SUDO) docker-compose up
All you would have to do then is putting this file in your project folder and run make start.
(The $(SUDO) part ensures that you can run this comfortably even with a user that is not in the docker group.)
Option 2
To really just run docker-compose up (perhaps with --build flag), you would have to write a little script that you COPY into the Docker image (you're already doing that with COPY . $APP_HOME – provided that you put this script at where your Docker build context points to) and then use it as ENTRYPOINT.
Something like this should work for you.
entrypoint.sh:
#!/bin/sh
set -e
cakephp composer install --no-interaction
cakephp bin/cake migrations migrate
cakephp bin/cake migrations seed
exec "$#"
In your Dockerfile, you would then have to put ENTRYPOINT ["/bin/sh", "entrypoint.sh"]
Related
I am trying to build and use a dockerized laravel app in an azure pipeline, but I get the error
Verifying lock file contents can be installed on current platform.
Package operations: 163 installs, 0 updates, 0 removals
In Filesystem.php line 268:
/var/www/app/vendor does not exist and could not be created.
when trying to install composer dependencies after building the image. The setup is pretty standard, I've tried so many different things but to no avail.
Dockerfile
FROM php:8.1-apache
RUN apt update
RUN apt-get install -y --no-install-recommends \
g++ \
libicu-dev \
libpq-dev \
libzip-dev \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
git \
lsb-release \
gnupg \
zip
RUN docker-php-ext-install \
intl \
opcache \
pdo \
pdo_mysql \
zip \
exif \
gd
RUN pecl install \
pcov \
xdebug
WORKDIR /var/www/app
RUN usermod -a -G www-data www-data
RUN chown root:root /var/www
RUN chown -R www-data:www-data /var/www/app
RUN chmod -R 755 /var/www/app
RUN mkdir /var/www/app/vendor
RUN chmod -R 775 /var/www/app/vendor
RUN chown -R www-data:www-data /var/www/app/vendor
RUN a2enmod rewrite
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
USER www-data
docker-compose
version: '3.8'
services:
database:
image: mysql:8.0
container_name: database
environment:
- MYSQL_DATABASE=app
- MYSQL_ROOT_PASSWORD=root
volumes:
- ./infrastructure/mysql-data:/var/lib/mysql
ports:
- '3306:3306'
api:
container_name: api
build:
context: ./infrastructure/php
ports:
- '8080:80'
volumes:
- ./server:/var/www/app
- ./infrastructure/apache/default.conf:/etc/apache2/sites-enabled/000-default.conf
depends_on:
- database
mailhog:
image: mailhog/mailhog:latest
container_name: mailhog
ports:
- '1025:1025'
- '8025:8025'
azure-pipelines.yml
trigger:
- develop
pool:
vmImage: ubuntu-latest
steps:
- script: make up
displayName: 'Build'
- script: |
docker-compose exec -T api composer install
make db_reset
displayName: 'Install'
- script: |
make analyse
displayName: 'Analyse backend'
Makefile
DOCKER_COMPOSE = docker-compose
COMPOSER ?= composer
PHP_CMD = php
PHP_SERVICE = api
up:
#echo "\n==> Docker container building and starting ..."
$(DOCKER_COMPOSE) up --build -d
db_reset:
$(DOCKER_COMPOSE) exec -T api php artisan migrate:fresh
$(DOCKER_COMPOSE) exec -T api php artisan passport:install
$(DOCKER_COMPOSE) exec -T api php artisan db:seed
analyse:
$(DOCKER_COMPOSE) exec -T -u root api php artisan ide-helper:models -W
$(DOCKER_COMPOSE) exec -T -u root api ./vendor/bin/php-cs-fixer fix app
$(DOCKER_COMPOSE) exec -T -u root api ./vendor/bin/phpstan analyse --memory-limit=2G -c phpstan.neon
I really don't know what I am doing wrong. Any help is appreciated
My project is throwing the next error after restarting the docker container:
Warning: require(/var/www/ /var/www/
/vendor/composer/./symfony/polyfill-php80/bootstrap.php): Failed to
open stream: No such file or directory in
'vendor/composer/autoload_real.php line 71
My Dockerfile:
FROM php:8.0-fpm
# Copy composer.lock and composer.json
COPY composer.lock composer.json /var/www/project/
# Set working directory
WORKDIR /var/www/project
# Install dependencies
RUN apt-get update && apt-get install -y \
build-essential \
libpng-dev \
libjpeg62-turbo-dev \
libfreetype6-dev \
locales \
zip \
jpegoptim optipng pngquant gifsicle \
vim \
unzip \
git \
curl \
libicu-dev \
libonig-dev \
libzip-dev
# install node
RUN curl -sL https://deb.nodesource.com/setup_current.x | bash -
RUN apt-get install -y nodejs
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Install extensions
RUN docker-php-ext-install pdo_mysql zip exif pcntl
RUN docker-php-ext-configure gd --enable-gd --with-freetype=/usr/include/ --with-jpeg=/usr/include/
RUN docker-php-ext-install gd
RUN docker-php-ext-configure intl
RUN docker-php-ext-install intl
RUN pecl install xdebug && docker-php-ext-enable xdebug
RUN echo 'xdebug.client_port=9000' >> /usr/local/etc/php/php.ini
RUN echo 'xdebug.mode=debug' >> /usr/local/etc/php/php.ini
RUN echo 'xdebug.discover_client_host=true' >> /usr/local/etc/php/php.ini
RUN echo 'memory_limit = 4G' >> /usr/local/etc/php/conf.d/docker-php-memlimit.ini;
# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Add user for laravel application
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www
# Copy existing application directory permissions
COPY --chown=www:www . /var/www/project
RUN composer install
RUN npm install
RUN npm run dev
RUN php artisan storage:link
ENV PATH="vendor/bin:${PATH}"
# Change current user to www
USER www
RUN composer global require tightenco/tlint
ENV PATH="${PATH}:/home/www/.composer/vendor/bin"
# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]
My docker-compose:
...
project:
build:
context: ./project/.
dockerfile: Dockerfile
image: project:v0
restart: unless-stopped
tty: true
environment:
PHP_IDE_CONFIG: serverName=docker_project
XDEBUG_CONFIG: remote_host=172.17.0.1
SERVICE_NAME: project
SERVICE_TAGS: dev
volumes:
- /var/www/project/vendor/
- ./project:/var/www/project
- ./project/.docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini
networks:
- project-network
...
Inside container run ls vendor/symfony before restarting the container:
And after:
The error is solving if remove the vendor directory and run composer install.
I'm not a Jedi of the Docker.
Thanks for any help/suggestion!
In your volume section, you are mounting the host machine folder ./project to your container's /var/www/project:
volumes:
- /var/www/project/vendor/
- ./project:/var/www/project
- ./project/.docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini
The vendor folder is built inside of you container by the RUN command. It's probably still there. But when you run docker-compose up, you instructed it to mask whatever inside with your host's ./project folder when running it. So the container don't see anything that you built before hand.
My advice is to only mount the folder that you need to change from time to time. For example:
volumes:
- /var/www/project/vendor/
# You're probably uploading files here
- ./project/public/assets:/var/www/project/public/assets
# Note: You might need to mount some other files / folders that changes
- ./project/.docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini
Then the container will properly use the prebuilt /vendor while storing the thing that you need to keep in host.
For who are facing the same issue, just map the project folder except vendor folder:
services:
app:
volumes:
.:/var/www/html
/var/www/html/vendor
...
If you want to have all vendor files in the host machine, just copy them from the container to your host machine, so IDE (Like PHPSTORM) can identify composer packages:
$ cd /your/project/host/path
$ docker cp $(docker-compose ps -q app):/var/www/html/vendor .
We are running a laravel application by docker. We are creating a docker container using PHP-FPM (php:7.0-fpm official image) & NGINX. We use a common .env file for both docker and laravel applications.
we up & running our application by - docker-compose --env-file=./.env -f docker-compose.yml up -d
But the problem is when we change our .env file, the application not detected the change. We want to get every .env file change without re-creating the container.
Dockerfile -
FROM php:7.0-fpm
# PHP_CPPFLAGS are used by the docker-php-ext-* scripts
ENV PHP_CPPFLAGS="$PHP_CPPFLAGS -std=c++11"
# Install dependencies
RUN apt-get update && apt-get install -y \
nginx \
libpng-dev \
zlib1g-dev \
libsasl2-dev \
libssl-dev \
libjpeg62-turbo-dev \
libfreetype6-dev \
libpng-dev \
libxpm-dev \
libvpx-dev \
libxml2-dev \
libicu-dev \
git
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Install extensions
RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/
RUN docker-php-ext-configure intl
RUN docker-php-ext-install -j$(nproc) pdo_mysql mbstring zip calendar soap gd intl
# Install mongodb extension
RUN pecl install mongodb-1.4.4 \
&& echo "extension=mongodb.so" > /usr/local/etc/php/conf.d/mongo.ini
# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer --version=1.8.6
RUN composer global require hirak/prestissimo
COPY entrypoint.sh /etc/entrypoint.sh
RUN chmod +x /etc/entrypoint.sh
RUN usermod -u 1000 www-data
# Set working directory
WORKDIR /var/www
EXPOSE 80 443
Docker Compose -
version: '3.5'
services:
api-service:
environment:
SERVICE_NAME: app
VIRTUAL_HOST: ${API_DOMAIN}
working_dir: /var/www
entrypoint: /etc/entrypoint.sh
volumes:
- ../../:/var/www
- ../nginx/conf.d/nginx-local.conf:/etc/nginx/sites-enabled/default
- ../php/local.ini:/usr/local/etc/php/conf.d/local.ini
- ../php/memory_limit.ini:/usr/local/etc/php/conf.d/memory_limit.ini
- ../php/php.ini:/usr/local/etc/php/conf.d/php.override.ini
- ../php/www.conf:/usr/local/etc/php-fpm.d/www.conf
ports:
- ${PORT}:80
networks:
api-service-network:
external:
name: ${EXTERNAL_NETWORK}
entrypoint -
#!/usr/bin/env bash
service nginx start
php-fpm
So is it possible to reload ENV (on local development by PHP-FPM) without recreating the container.
Try using env_file in docker-compose
Maybe can help you
Not able to run make install from docker file, not sure where I am going wrong.
Getting below error message when docker-compose build is run in ubuntu
Step 6/10 : RUN make install
---> Running in c8f67e8de3b5
make: *** No rule to make target 'install'. Stop.
ERROR: Service 'web' failed to build:
The command '/bin/sh -c make install' returned a non-zero code: 2
I have the below structure where server is laravel project and in root there is a docker-compose.yml file.
Below is the structure of server folder
docker-compose.yml file
version: '3'
services:
web:
image: api_server
container_name: api_server
build:
context: ./server/release
ports:
- 9000:80
volumes:
- ./server:/var/www/app
Dockerfile
FROM php:7.3.1-apache-stretch
RUN apt-get update -yqq && \
apt-get install -y apt-utils zip unzip && \
apt-get install -y nano && \
apt-get install -y libzip-dev libpq-dev libpng-dev&& \
a2enmod rewrite && \
docker-php-ext-install gd mbstring && \
docker-php-ext-install pdo_pgsql && \
docker-php-ext-install pgsql && \
docker-php-ext-configure zip --with-libzip && \
docker-php-ext-install zip && \
rm -rf /var/lib/apt/lists/*
RUN php -r "readfile('http://getcomposer.org/installer');" | php -- --install-dir=/usr/bin/ --filename=composer
COPY default.conf /etc/apache2/sites-enabled/000-default.conf
WORKDIR /var/www/app
RUN make install
RUN chown -R www-data:www-data /var/www/app/
RUN chmod -R 777 /var/www/app/storage
CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
EXPOSE 80
server/Makefile
install:
# some other commands
composer install
refresh:
# For testing
php artisan migrate:refresh
php artisan db:seed
make run:
php artisan migrate:status
php artisan serve
Basically if I comment RUN make install and RUN chmod -R 777 /var/www/app/storage commands from Dockerfile it works. To test i'll get into the container and run the above 2 commands manually then it works by showing the default laravel page.
So I feel trying to run the above 2 commands from Dockerfile i guess source code isn't available at that point.
I am trying to setup Docker for my application relying on an LEMP stack. To this end, I plan to use Docker compose in order to spawn one container for Nginx, one for PHP-FPM and one for MySQL.
This is all working well for the basic illustration use-cases found in the online tutorials, but when I try to apply it to my use-case, I struggle with a design issue.
To give a bit of context, my web application relies on Composer for PHP dependencies and Gulp+Bower for CSS/JS dependencies (and LESS compilation, assets minimization, etc.).
The problem is that I need to build the application (i.e. install all dependencies and run some gulp tasks) and provide the result of this build to both Nginx and PHP-FPM containers.
Here is what I have come to so far:
docker-compose.yml:
version: "3"
networks:
database:
server:
volumes:
mysql-data:
source:
services:
php:
build: .
volumes:
- source:/app:ro
restart: always
networks:
- database
- server
depends_on:
- mysql
mysql:
image: mysql:5.7
volumes:
- mysql-data:/var/lib/mysql
restart: always
networks:
- database
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_USER: test
MYSQL_PASSWORD: test
MYSQL_DATABASE: test
nginx:
image: nginx
volumes:
- source:/app:ro
restart: always
networks:
- server
depends_on:
- php
Dockerfile:
FROM php:7.1-fpm
WORKDIR /app
# Install dependencies
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -
RUN apt-get update && apt-get install -y \
git \
nodejs \
zip
RUN curl -sL https://getcomposer.org/installer | php -- --install-dir /usr/bin --filename composer
# Get application dependencies
COPY composer.json ./
RUN composer install -o
COPY package.json gulpfile.js bower.json ./
RUN npm install
RUN npm run gulp
RUN npm run rev
# Copy application
COPY . ./
However, as a Docker beginner, I am not sure it is right to rely on a volume for the build result of the application, or to have the build steps part of one of the containers running the application.
Thanks in advance for any help or advice!
Nicolas
However, as a Docker beginner, I am not sure it is right to rely on a volume for the build result of the application, or to have the build steps part of one of the containers running the application.
Short answer: Named volumes are the correct way to handle this.
In previous versions of compose, you would use the volumes-from option to reference an existing volume in a different container. This is deprecated in v3, being replaced by named volumes which you appear to be implementing correctly. I mention volumes-from because I think it does a good job of showing the intention of volumes - to persist data between containers - where named volumes is a bit less descriptive.
Look this for PHP7-FPM - NGINX - MySQL - ELK : https://github.com/maxpou/docker-symfony
And this for container management : https://portainer.io
My custom docker file with Node / Gulp
/php7-fpm/Dockerfile
FROM php:7.0-fpm
RUN apt-get update && apt-get install -y \
git \
unzip \
wget \
ntp \
gnupg
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash -
RUN apt-get install -y nodejs
RUN npm config set registry "http://registry.npmjs.org/"
RUN npm install -g gulp bower
# Install Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
RUN composer --version
# Set timezone
RUN rm /etc/localtime
RUN ln -s /usr/share/zoneinfo/Europe/Paris /etc/localtime
RUN "date"
# Type docker-php-ext-install to see available extensions
RUN docker-php-ext-install pdo_mysql
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libmcrypt-dev \
libpng-dev \
&& docker-php-ext-install -j$(nproc) iconv mcrypt \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j$(nproc) gd
# install xdebug
#RUN pecl install xdebug
#RUN docker-php-ext-enable xdebug
#RUN echo "error_reporting = E_ALL" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
#RUN echo "display_startup_errors = On" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
#RUN echo "display_errors = On" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
#RUN echo "xdebug.remote_enable=1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
#RUN echo "xdebug.remote_connect_back=1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
#RUN echo "xdebug.idekey=\"PHPSTORM\"" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
#RUN echo "xdebug.remote_port=9001" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN apt-get update \
&& apt-get -y install \
libmagickwand-dev \
--no-install-recommends \
&& pecl install imagick \
&& docker-php-ext-enable imagick \
&& rm -r /var/lib/apt/lists/*
RUN echo "file_uploads = On\n" \
"memory_limit = 500M\n" \
"upload_max_filesize = 500M\n" \
"post_max_size = 500M\n" \
"max_execution_time = 600\n" \
> /usr/local/etc/php/conf.d/uploads.ini
RUN echo "realpath_cache_ttl = 7200\n" \
"realpath_cache_size = 4M\n" \
> /usr/local/etc/php/conf.d/opti-symfony.ini
RUN echo "date.timezone=Europe/Paris" \
> /usr/local/etc/php/conf.d/time-zone.ini
RUN docker-php-ext-install opcache
WORKDIR /var/www/symfony
If you have an error gives us ;)
Happy Docker