
Running a PHP application on Docker containers (PHP-FPM, Nginx, PostgreSQL)
Over the past year, software for automating deployment in a virtualization environment at the operating system level has been gaining momentum. This article will serve as an example for beginners in this field how to pack your application in Docker containers.
In its classic form, a PHP application consists of the following components:
In our example, we will use Nginx, PostgreSQL and PHP-FPM.
To get started, we need Docker. You can download it on the official Docker website .
Docker creates images based on DockerFile files, which describes the functionality. We will create 3 images for our components.
In this DockerFile, we create the www-data user with group 82 and install Nginx. The last line of COPY assumes that your application configuration is in the config / website.conf folder. It will be copied to /etc/nginx/conf.d/website.conf.
In this image, we will build on the postgres: 9.5.2 image and run the command to determine the locale and language.
This image will serve us mainly for our application. First we install everything we need for PHP and PHP-FPM. Next, we copy the current application folder to / usr / src / app, where our application will be located. At the very end, we run PHP-FPM.
And so, we have DockerFiles based on which we must create images. Images are created very simply. It is enough to execute the following commands:
In the future, I advise you to add --no-cache to these commands so that each time you do not compile the components.
We create images, attach them to our account on the Docker Hub. Now, we need to send our images to the repository in the Docker Hub. We execute the following commands:
We are almost there! It remains for us to download the images from the repository and run them. Download them using the following commands:
It remains to run them. This is just as easy.
Voila! Our application runs on Docker containers. And yet, for all novice readers, I would definitely check out the Docker documentation .
I wish you all success in mastering new technologies!
In its classic form, a PHP application consists of the following components:
- Web server
- DBMS
- Php application
In our example, we will use Nginx, PostgreSQL and PHP-FPM.
1. Install Docker
To get started, we need Docker. You can download it on the official Docker website .
2. Creating images
Docker creates images based on DockerFile files, which describes the functionality. We will create 3 images for our components.
DockerFileNginx
FROM nginx:mainline-alpine
RUN set -ex \
&& addgroup -g 82 -S www-data \
&& adduser -u 82 -D -S -G www-data www-data \
&& mkdir -p /etc/pki/nginx/ \
&& apk update \
&& apk --no-cache add --update openssl \
&& openssl dhparam -out /etc/pki/nginx/dhparams.pem 4096 \
&& sed -i -e 's/user\s*nginx;/user www-data www-data;/g' /etc/nginx/nginx.conf \
&& sed -i -e 's/worker_processes\s*1;/worker_processes auto;/g' /etc/nginx/nginx.conf \
&& rm -rf /var/cache/apk/*
COPY config/website.conf /etc/nginx/conf.d/website.conf
In this DockerFile, we create the www-data user with group 82 and install Nginx. The last line of COPY assumes that your application configuration is in the config / website.conf folder. It will be copied to /etc/nginx/conf.d/website.conf.
DockerFilePostgresql
FROM postgres:9.5.2
RUN localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8
ENV LANG en_US.utf8
In this image, we will build on the postgres: 9.5.2 image and run the command to determine the locale and language.
Dockerfile
FROM alpine:edge
# Timezone
ENV TIMEZONE Europe/Moscow
ENV PHP_MEMORY_LIMIT 1024M
ENV MAX_UPLOAD 128M
ENV PHP_MAX_FILE_UPLOAD 128
ENV PHP_MAX_POST 128M
RUN set -ex \
&& addgroup -g 82 -S www-data \
&& adduser -u 82 -D -S -G www-data www-data \
&& echo "@testing http://dl-4.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \
&& apk update \
&& apk upgrade \
&& apk add --update tzdata \
&& cp /usr/share/zoneinfo/${TIMEZONE} /etc/localtime \
&& echo "${TIMEZONE}" > /etc/timezone \
&& apk --update add --no-cache php7-fpm@testing php7-mcrypt@testing php7-openssl@testing php7-json@testing php7-mysqli@testing php7-session@testing php7-gd@testing php7-xmlreader@testing php7-xmlrpc@testing \
php7-zip@testing php7-iconv@testing php7-curl@testing php7-zlib@testing php7@testing php7-ctype@testing php7-pgsql@testing php7-pdo_pgsql@testing bash rsync \
&& sed -i -e "s/;daemonize\s*=\s*yes/daemonize = no/g" /etc/php7/php-fpm.conf \
&& sed -i -e "s/listen\s*=\s*127.0.0.1:9000/listen = [::]:9000/g" /etc/php7/php-fpm.d/www.conf \
&& sed -i -e "s/;chdir\s*=\s*\/var\/www/chdir = \/usr\/src\/app/g" /etc/php7/php-fpm.d/www.conf \
&& sed -i -e "s/user\s*=\s*nobody/user = www-data/g" /etc/php7/php-fpm.d/www.conf \
&& sed -i -e "s/group\s*=\s*nobody/group = www-data/g" /etc/php7/php-fpm.d/www.conf \
&& sed -i -e "s/;clear_env\s*=\s*no/clear_env = no/g" /etc/php7/php-fpm.d/www.conf \
&& sed -i -e "s/;catch_workers_output\s*=\s*yes/catch_workers_output = yes/g" /etc/php7/php-fpm.d/www.conf \
&& sed -i "s|;date.timezone =.*|date.timezone = ${TIMEZONE}|" /etc/php7/php.ini \
&& sed -i "s|memory_limit =.*|memory_limit = ${PHP_MEMORY_LIMIT}|" /etc/php7/php.ini \
&& sed -i "s|upload_max_filesize =.*|upload_max_filesize = ${MAX_UPLOAD}|" /etc/php7/php.ini \
&& sed -i "s|max_file_uploads =.*|max_file_uploads = ${PHP_MAX_FILE_UPLOAD}|" /etc/php7/php.ini \
&& sed -i "s|post_max_size =.*|post_max_size = ${PHP_MAX_POST}|" /etc/php7/php.ini \
&& sed -i "s/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/" /etc/php7/php.ini \
&& apk del tzdata \
&& rm -rf /var/cache/apk/*
COPY . /usr/src/app
RUN chown -R www-data:www-data /usr/src/app
EXPOSE 9000
CMD ["php-fpm7"]
This image will serve us mainly for our application. First we install everything we need for PHP and PHP-FPM. Next, we copy the current application folder to / usr / src / app, where our application will be located. At the very end, we run PHP-FPM.
Creating DockerFile-based Images
And so, we have DockerFiles based on which we must create images. Images are created very simply. It is enough to execute the following commands:
docker build -t myusername/myproject-nginx:latest -f DockerfileNginx .
docker build -t myusername/myproject-postgresql:latest -f DockerfilePostgreSql .
docker build -t myusername/myproject:latest .
In the future, I advise you to add --no-cache to these commands so that each time you do not compile the components.
We create images, attach them to our account on the Docker Hub. Now, we need to send our images to the repository in the Docker Hub. We execute the following commands:
docker push myusername/myproject-nginx:latest
docker push myusername/myproject-postgresql:latest
docker push myusername/myproject:latest
Running images on the server
We are almost there! It remains for us to download the images from the repository and run them. Download them using the following commands:
docker pull myusername/myproject-nginx:latest
docker pull myusername/myproject-postgresql
docker pull myusername/myproject
It remains to run them. This is just as easy.
docker run —name myproject-nginx -d -p 80:80 myusername/myproject-nginx:latest
docker run —name myproject-postgresql9.5.2 -d -p 5432:5432 myusername/myproject-postgresql9.5.2:latest
docker run —name myproject -d -p 9000:9000 myusername/myproject:latest
Voila! Our application runs on Docker containers. And yet, for all novice readers, I would definitely check out the Docker documentation .
I wish you all success in mastering new technologies!