PHP(Phalcon) + Nginx + Mysql with Docker compose - Part 1
DockerHi, I'm Lovefield.
With the recent I use of Docker, the blog has also been changed to Docker-based. This blog is based on Phalcon. Phalcon was a more challenging framework than we thought. It took a lot of trials and errors to get Phalcon on the Docker before he could make it. This article is going to talk about how to utilize Phalcon in a Docker environment.
First the directory structure, I assign one folder per container considering the management aspect when using docker-compose.
- mysql
-data
- php
-asset
- nginx
-asset
-log
- phalcon
docker-compose.yml
The “mysql/data” folder is a space for string DB data, used to keep data intact with or without container behavior. The asset folder in the “php” folder is the place where ini files are created. The .conf will also be created for the “nginx” folder.The reason for creating a separate “phalcon” folder is to distinguish between the actual drive file and the setup file.
Now, write the docker-compose.yml
file.
version: "3"
services:
mysql:
php:
nginx:
Write "3" in "version" to use the latest version. We will use a total of 3 containers, so please write "mysql", "php", and "nginx" in "services".
Shall we set up the "mysql" container first?
```
mysql:
container_name: mysql
image: mysql:8.0.22
environment:
MYSQL_DATABASE: app
MYSQL_USER: user
MYSQL_PASSWORD: user_pw
MYSQL_ROOT_PASSWORD: root_pw
command: ["mysqld", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"]
volumes:
- ./mysql/data:/var/lib/mysql:rw
ports:
- "3306:3306"
restart: always
logging:
options:
max-size: "1m"
max-file: "3"
```
Type "mysql:8.0.22" in the "image" entry to use Mysql 8. It means that "mysql:8.0.22" is taken from the list in the Docker image hub and used.
The "environment" entry sets the factors to be used within the container.
The name of the DB is "MYSQL_DATABASE".
Username as "MYSQL_USER".
User password with "MYSQL_PASSWORD".
Set the root account password to "MYSQL_ROOT_PASSWORD".
The "command" entry is a command to execute after the container is executed. Mysql 8 is set to character set to utf8 by default, but it adds related commands just in case.The "volume" entry is a list that will match the path within the container with the current directory. Write "./mysql/data:/var/lib/mysql:rw" to place all data in the relevant folder. At the end, ":rw" is an option that grants permission to read and write.
The "ports" entry matches the external port with the internal port of the container.
The "restart" entry is an option to restart when the container is stopped due to a problem.
The "logging" entry is literally to log, this time saving up to 1mb records per file and limiting it to up to three.
Next, let's set up a "php" container.
php:
container_name: php
build:
context: ./php
dockerfile: dockerfile
args:
- WITH_XDEBUG=true
working_dir: /var/www/html
volumes:
- ./php/asset/timezone.ini:/usr/local/etc/php/conf.d/timezone.ini
- ./php/asset/file.ini:/usr/local/etc/php/conf.d/file.ini
- ./phalcon:/var/www/html:rw
command: bash -c "php-fpm"
restart: always
logging:
options:
max-size: "1m"
max-file: "3"
The "php" container is difficult to use images. You are going to use the docker file for additional settings, so please specify the docker file as a "build" entry instead of an "image"."args" is the factor to use when executing dockerfile. We need to install Xdebug to debug php. But, there is no reason to run a heavy Xdebug on a real server. "args" is a factor for whether or not Xdebug is installed.
In the "php" folder, create a dockerfile to use in the container.
# using php7.4-fpm image
FROM php:7.4-fpm
# install default library
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libpng-dev \
zlib1g-dev \
g++ \
libicu-dev \
libmcrypt4 \
libzip-dev \
&& docker-php-ext-install pdo_mysql \
&& docker-php-ext-install mysqli \
&& docker-php-ext-install zip
# install composer
RUN curl -sSL https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Whether or not to install Xdebug
ARG WITH_XDEBUG=false
# install Xdebug
RUN set -eux; \
if [ $WITH_XDEBUG = "true" ] ; then \
pecl install xdebug; \
docker-php-ext-enable xdebug; \
echo "error_reporting = E_ALL" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini; \
echo "display_startup_errors = On" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini; \
echo "display_errors = On" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini; \
echo "xdebug.remote_enable=1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini; \
echo "xdebug.idekey=PHPSTORM" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini; \
echo "xdebug.remote_host=host.docker.internal" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini; \
fi ;
# phalcon version setting
ARG PSR_VERSION=1.0.0
ARG PHALCON_VERSION=4.0.5
ARG PHALCON_EXT_PATH=php7/64bits
RUN set -xe && \
# install PSR
curl -LO https://github.com/jbboehr/php-psr/archive/v${PSR_VERSION}.tar.gz && \
tar xzf ${PWD}/v${PSR_VERSION}.tar.gz && \
# install Phalcon
curl -LO https://github.com/phalcon/cphalcon/archive/v${PHALCON_VERSION}.tar.gz && \
tar xzf ${PWD}/v${PHALCON_VERSION}.tar.gz && \
docker-php-ext-install -j $(getconf _NPROCESSORS_ONLN) \
${PWD}/php-psr-${PSR_VERSION} \
${PWD}/cphalcon-${PHALCON_VERSION}/build/${PHALCON_EXT_PATH} \
&& \
# remove tmp file
rm -r \
${PWD}/v${PSR_VERSION}.tar.gz \
${PWD}/php-psr-${PSR_VERSION} \
${PWD}/v${PHALCON_VERSION}.tar.gz \
${PWD}/cphalcon-${PHALCON_VERSION} \
&& \
php -m
Next, create ini, the php settings file that you linked to the "volume" entry. You must create timezone.ini and file.ini in the "php/asset" folder, respectively.
; timezone.ini
date.timezone=Asia/Seoul
; file.ini
upload_max_filesize=10M
post_max_size=10M
I changed the timezone on the php to "Asia/Seoul" in Korean time and set the maximum upload file capacity to 10MB.
Lastly, set the "nginx" container.
nginx:
container_name: nginx
image: nginx:1.17.8
command: ["nginx", "-g", "daemon off;"]
working_dir: /var/www/html
depends_on:
- php
- mysql
volumes:
- ./nginx/asset/:/etc/nginx/conf.d/
- ./nginx/log:/var/log/nginx/:rw
- ./phalcon:/var/www/html:rw
ports:
- "80:80"
links:
- php
restart: always
logging:
options:
max-size: "1m"
max-file: "3"
Use "depends_on" to set the "nginx" container to run after the "php" container and the "mysql" container have been run.
Link to the "php" container via "links".
Use the folder "./nginx/log:/var/log/:rw" for "volume" to logging.
Files running the actual app use the folder "./palcon:/var/www/html:rw" and files setting nginx use the folder "./nginx/asset/:/etc/nginx/conf.d/".
Now create the file default.conf
in the folder "nginx/asset" that you set up nginx.
server {
listen 80;
root /var/www/html/public;
index index.html index.htm index.php;
server_name localhost;
client_max_body_size 10M;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
location / {
try_files $uri $uri/ /index.php?_url=$uri&$args;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index /index.php;
fastcgi_connect_timeout 60s;
fastcgi_read_timeout 60s;
fastcgi_buffers 256 4k;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
docker-compose connected the external port from 80 to the internal port 80, so port is 80.
The reason why root is "/var/www/html/public" is because of the folder structure in Phalcon.
Write down each path to logging and create a location.
The most important part of this is "fastcgi_pass". You must write down the name and port of the container containing php. Write "Container name:port" to locate the address of the container name within the docker and connect it to the port of that address. PHP uses 9000 port basically, so please connect it to 9000 port.
We're all set now. Try the first run with the command 'docker-compose up-d'.If you don't give me the "-d" option, it won't run as a daemon and the maintain server.(CAUTION: If there is insufficient RAM when installing xdebug or phalcon, an error can occur. A minimum of 4gb RAM is required)
Once the command is functioning normally, you can see the screen above.
Now use docker-compose ps
to check the status of the containers.
If the state is up and ports are connected normally, it is a success.
The basic procedure is over, and the setting after the docker-compose up command is explained in the next article.