Another Docker article for a newbie [nginx + php-fpm + postgresql + mongodb]

Good day to all. Inspired by a whole set of articles on the topic of raising the environment on the docker, I decided to share my experience on this issue.
I’ll make a reservation right away, this article is “from a newbie to a newbie”, so I’ll try to tell in detail about all the difficulties and issues that I had in setting up the environment in Docker.
Welcome to cat!
So, all that I will describe below, I will do on the laptop of the famous “fruit company”, but since I did the same on VDS under Centos 7 earlier, I will do a little digression with a description of how I did it on VDS .
We will begin naturally in registration on docker hub, which will act as a version control system, but only for our containers. Docker hub with free use allows you to have only 1 private repository, so we will mark each individual image with the appropriate tags - nginx, php7-fpm. I will not describe the creation of a repository, I think no one will have problems with this.
Now we can install docker itself on our workstation - in my case, this description is here .
When installing Docker on a Mac, we immediately have the docker toolbox installed , which contains the docker-compose tool we need . We will use it to combine our containers about a common environment.
yum -y install python-pip
pip install docker-composeNext, log in to our Docker:
docker loginNow our private repositories are available to us (although the truth is empty there), the truth is empty there now, but we will fix it soon :)
For my project I made the following file structure:
├── contaners # Директория с кастомными образами для docker
│ ├── fpm
│ │ ├── Dockerfile
│ │ └── conf
│ │ └── fpm.conf # Необходимые настройки fpm, у меня файл пустой:)
│ └── nginx
│ ├── Dockerfile
│ └── conf
│ └── nginx.conf
├── database # Директоря для хранения баз данных
├── docker-compose.yml
├── logs # Директоря для хранения логов
└── php-code # Директоря с php кодом
├── html
└── index.phpFor the project, I will use custom images for nginx and fpm, so I put them in separate directories. Custom images are described using the Dockerfile . Here are mine:
FROM php:fpm
MAINTAINER nickname
RUN apt-get update && apt-get install -y \
libmcrypt-dev \
&& apt-get install -y libpq-dev \
&& docker-php-ext-install -j$(nproc) mcrypt \
&& pecl install mongodb
&& docker-php-ext-enable mongodb
RUN docker-php-ext-install mbstring
RUN docker-php-ext-install exif
RUN docker-php-ext-install opcache
RUN docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \
&& docker-php-ext-install pgsql pdo_pgsql
COPY conf/ /usr/local/etc/php-fpm.d/
CMD ["php-fpm"]
FROM nginx:latest
MAINTAINER nickname
COPY ./conf /etc/nginx/conf.d/ server {
listen 80;
index index.php index.html;
server_name localhost;
error_log /etc/logs/nginx/nginx_error.log;
access_log /etc/logs/nginx/nginx_access.log;
root /var/www;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass fpm:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
The script from the official PHP image from the Docker Hub makes it easy to install the necessary extensions:
docker-php-ext-installor
docker-php-ext-enable # в случае, если расширение уже установлено (как у меня через pecl)All the preparatory work has been carried out, now we need to describe how our containers will interact. As I already wrote, we will do this through docker-compose and the interaction rules must be described in the docker-compose.yml file . Here is my:
nginx:
dockerfile: ./Dockerfile # путь до докер файла указываем относительно директории в build
build: ./contaners/nginx
ports:
- 80:80
volumes:
- ./logs:/etc/logs/nginx
volumes_from:
- fpm:rw
environment:
- NGINX_HOST=localhost
- NGINX_PORT=80
command: nginx -g "daemon off;" # Можно было указать в докер-фале, но можно и здесь)
links:
- fpm
fpm:
dockerfile: ./Dockerfile
build: ./contaners/fpm
volumes:
- ./php-code:/var/www:rwNow you can run our containers:
docker-compose up -dThat's all, our containers work and link, but I did something wrong, namely - we always refer to the Dockerfile to launch the container, this is not very convenient. Let's do it like this:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2d6263b52380 test_nginx "nginx -g 'daemon off" 8 minutes ago Up 8 minutes 443/tcp, 0.0.0.0:8080->80/tcp test_nginx_1
04370a9e1c73 test_fpm "php-fpm" 8 minutes ago Up 8 minutes 9000/tcp test_fpm_1
docker tag 2d6263b52380 my-login/repo:nginx
docker tag 2d6263b52380 my-login/repo:fpm
docker push my-login/repo:nginx
docker push my-login/repo:php7-fpmNow our containers are managed through the docker hub and Dockerfiles we no longer need.
Fix docker-compose.yml:
nginx:
image: my-login/repo:nginx
ports:
- 80:80
volumes:
- ./logs:/etc/logs/nginx
volumes_from:
- fpm:rw
environment:
- NGINX_HOST=localhost
- NGINX_PORT=80
command: nginx -g "daemon off;" # Можно было указать в докер-фале, но можно и здесь)
links:
- fpm
fpm:
image: my-login/repo:php7-fpm
volumes:
- ./php-code:/var/www:rwAnd now I realized that I forgot to add the pcntl extension for php. But this is easy to fix.
First, connect to the desired container:
docker exec -it 04370a9e1c73 bashAnd add the necessary extension:
docker-php-ext-install pcntlWell, we added it to the container, but we wanted to use the docker hub as a VCS - so we need to commit the changes:
docker commit -m "added pcntl ext" 04370a9e1c73 my-login/repo:php7-fpmand push to the repository:
docker push my-login/repo:php7-fpmAdd more database containers (postgresql and mongodb):
nginx:
image: my-login/repo:nginx
ports:
- 80:80
volumes:
- ./logs:/etc/logs/nginx
volumes_from:
- fpm:rw
environment:
- NGINX_HOST=localhost
- NGINX_PORT=80
command: nginx -g "daemon off;"
links:
- fpm
fpm:
image: my-login/repo:php7-fpm
volumes:
- ./php-code:/var/www:rw
links:
- mongo
- postgres
mongo:
image: mongo
ports:
- 27017:27017 # Проброс портов для внешнего доступа
volumes:
- ./database/mongo:/data/db
postgres:
image: postgres:latest
ports:
- 5432:5432 # Проброс портов для внешнего доступа
volumes:
- ./database/postgres:/data/postgres
environment:
POSTGRES_PASSWORD:
POSTGRES_USER: postgres
PGDATA : /data/postgres And now we execute:
docker-compose up -dDocker will add us new containers to already launched ones. But I opened the ports for external access, but we specified the password only for PostgreSql, we need to do the same for mongodb - how to do it (and not only) is described in detail here .
docker exec -it some-mongo mongo admin
connecting to: admin
> db.createUser({ user: 'jsmith', pwd: 'some-initial-password', roles: [ { role: "userAdminAnyDatabase", db: "admin" } ] });
Successfully added user: {
"user" : "jsmith",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
]
}Databases from php are now available on postgres and mongo hosts respectively, i.e. to connect, for example, to mongodb, we must write the following:
$manager = new MongoDB\Driver\Manager("mongodb://mongo:27017");That's all, thanks for your attention. Please note that everything described is solely my own experience and does not claim to be the ideal approach to setting up the environment through docker.