The
article on Habré discussed the “docker way” (TM), which says: one container is one process.
one process per containerEach container should have only one concern
It makes it easier to scale horizontally and reuse containers. For instance, there are three containers for each instance.
You may have heard that there should be “one process per container”. It is not necessarily true. In addition to the process of spraying, there could be some processes of their own accord. For instance, Celery can spawn multiple processes, or Apache might create a process per request. It is not a hard and fast rule. Keep it clean and modular as possible.
')
If you can use container lines, you can use.
Following this principle when completing nginx is fraught with two consequences. Configuring the interaction of nginx and php-fpm in different processes through a unix socket is a
bit more complicated than it might seem. And the
rotation of the logs , which in a normal installation is “out of the box”, cannot be carried out in principle, because requires sending a USR1 nginx signal, for which another process is needed.
As a result of the discussion, it became clear that instead of sending the USR1 nginx signal, add the copytruncate option to the logrotate configuration. So in the container there is no need to run multiple processes. However, all actions on the startup setup of log rotation on cron will still need to be performed not inside the container, but on the host where the container works. When running both a web server and log rotation in a single container, a separate configuration of the rotation on the host is no longer required.
The above links provide solutions. But the first time it did not work, and I had to look for reasons. Therefore, besides the links, I present the results of my experiments. In order to be able to get acquainted with the method of
protection against DDoS-attacks, openresty will be launched instead of the nginx server (build of nginx from Taobao with the Lua scripting engine). This server has a different location to the file directories compared to nginx. But everything else is absolutely identical.
First, create a docker-compose.yml file in the project root directory:
version: "3" services: app: build: context: ./docker/php # dockerfile: docker/php/Dockerfile args: UID: "3000" working_dir: /app nginx: build: context: ./docker/nginx # dockerfile: docker/nginx/Dockerfile args: UID: "3000" ports: - 8000:80
We assume that container creation scripts will be stored in docker / php / Dockerfile and docker / nginx / Dockerfile files. The name of the Dockerfile is the default name, therefore there is no need to explicitly set it in the configuration.
Create a docker / php / Dockerfile file:
FROM php:7-fpm ARG UID RUN addgroup --gid $UID --system app \ && adduser --uid $UID --system --disabled-login --disabled-password --gid $UID app
The php: 7-fpm image is loaded and a user is created with the identifier specified by the UID parameter (in docker-compose.yml UID: 3000) with the name app in the app group. This is needed to set permissions to read the socket from the container where openresty will be launched.
In order to get the log rotation in nginx or openresty, it is necessary that the container does not shut down when restarting the web server, as well as that cron is running in the same container. That is, it will not be a single-process container, but otherwise it will not work. It is recommended to run multiple processes through supervisor.
Create a docker / nginx / Dockerfile file:
FROM openresty/openresty:xenial RUN apt-get update && apt-get install -y supervisor cron logrotate COPY ./supervisord.conf /etc/supervisor/conf.d/supervisord.conf COPY ./logrotate.conf /etc/logrotate.conf COPY ./cron.d /etc/cron.d/nginx ARG UID RUN mkdir -p /var/log/supervisor \ && chmod 644 /etc/logrotate.conf && chown root:root /etc/logrotate.conf \ && chmod 644 /etc/cron.d/nginx && chown root:root /etc/cron.d/nginx \ && addgroup --gid $UID --system app \ && adduser --uid $UID --system --disabled-login --disabled-password --gid $UID app ENTRYPOINT ["/usr/bin/supervisord"]
At first, all necessary programs are integrated. Then the configuration files from the ./docker/nginx/ directory are copied to the container's internal file system. Further, some of these files are assigned 644 rights (otherwise the system will not rotate the logs). And it also creates a user and app group with the same ID (UID: 3000).
It is also necessary to create several configuration files.
The docker / php / zz-docker.conf file (the name of zz-docker.conf is present in the configuration of the php image: 7-fpm. This is not described anywhere and can change. Unfortunately, there are no detailed descriptions of images at the moment, and have to investigate them after downloads from repository):
[global] daemonize = no [www] ;listen = [::]:9000 # Don't need this listen = /sock/docker.sock listen.owner = app listen.group = app listen.mode = 0660
The parameter
listen = /sock/docker.sock
will be the same as in the nginx configuration.
The main configuration file nginx will have to be rewritten. in openresty, it does not contain the necessary parameters, and this is the location of the logs, the process identifier, the user (app), and the directory with the virtual server configurations (/conf.d).
user app; error_log /var/log/nginx/error.log debug; pid /var/run/nginx.pid; http { access_log /var/log/nginx/access.log; include mime.types; default_type application/octet-stream; server { listen 80; server_name localhost; location / { root html; } } include /usr/local/openresty/nginx/conf/conf.d/*; }
Create a virtual server with the server.conf configuration:
server { listen 80; server_name local; root /usr/share/nginx/html; disable_symlinks off; client_max_body_size 50M; location ~ (/assets|/favicon.ico) { try_files /build$uri $uri =404; } location / { try_files $uri /app.php$is_args$args; } location ~ \.php$ { fastcgi_pass unix:/sock/docker.sock; try_files $fastcgi_script_name =500; fastcgi_split_path_info ^(.+\.php)(/.*)$; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } }
We
unix:/sock/docker.sock
proxy not through a port, but through a
unix:/sock/docker.sock
socket
unix:/sock/docker.sock
.
Now create the logrotate.conf file:
/var/log/nginx/*.log { size=1k missingok rotate 8 notifempty sharedscripts postrotate [ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid` endscript }
And the task for cron:
SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin MAILTO=""
File size size = 1k and rotation rotation every minute (* * * * *) is not for a working server, but only for the rotation of logs to be observed at the minimum time. The logrotate command copies logs to archive files. But until nginx is restarted, the real creation of a new empty log file will not happen. In order for nginx to open the logs again, the awesome command
kill -USR1 `cat /var/run/nginx.pid`
.
Finally, the supervisor configuration:
[supervisord] nodaemon=true logfile=/dev/null [program:nginx] command=/usr/local/openresty/bin/openresty -g 'daemon off;' [program:cron] command=cron -f
It doesn't matter where all these configuration files are located, because all paths are specified in the COPY statements from the Dockerfile, and in the volumes values from the docker-compose.yml. Now you need to be patient and write down all the necessary paths in docker-compose.yml.
version: "3" services: app: build: context: ./docker/php args: UID: "3000" working_dir: /app volumes: - ./:/app - ./html:/usr/share/nginx/html - ./docker/php/zz-docker.conf:/usr/local/etc/php-fpm.d/zz-docker.conf - ./docker/sock:/sock expose: - 9000 links: - mysql nginx: build: context: ./docker/nginx args: UID: "3000" ports: - 8000:80 volumes: - ./:/app/ - ./html/:/usr/share/nginx/html/ - ./docker/nginx/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf - ./docker/nginx/conf.d/:/usr/local/openresty/nginx/conf/conf.d/ - ./docker/nginx/log/:/var/log/nginx/ - ./lua/:/usr/share/nginx/lua/ - ./docker/sock/:/sock/ links: - app depends_on: - app
Now you can add Lua scripts (see the
article on Habré ).
apapacy@gmail.com
January 27, 2018