Мы продолжаем цикл обучающих статей для начинающих системных администраторов: если вы являетесь опытным админом, можете смело пропустить этот материал. В этой статье мы разберем docker-compose.

Напомню, что цель серии - не показать, как развернуть идеальное окружение, а лишь указать на нюансы в работе и защитить начинающих специалистов от базовых ошибок при настройке.

Ссылки на наши предыдущие статьи:
Настройка LEMP сервера с помощью docker для простых проектов. Часть первая: База

Настройка LEMP сервера для простых проектов. Инструкция для самых маленьких. Часть первая

Итак, в этой статьей рассмотрим следующие пункты:

  1. docker-compose.

    1. Чем удобен docker-compose?

    2. Установка.

    3. Подготовка.

  2. Приступаем к написанию yml-файла.

    Пункт 1. Указание версии.

    Пункт 2. Объявляем сервисы.

    Пункт 3. Объявляем контейнеры.

    Пункт 4. Локальная сеть контейнеров.

    Пункт 4.1. Основные конфигурации и ключи файла docker-compose.

    Пункт 5. Пишем nginx.

    Пункт 6. Пишем php-fpm.

    Пункт 7. Пишем mysql.

    Пункт 8. Общий итог docker-compose.yml.

docker-compose.

Чем удобен docker-compose?

docker-compose позволяет управлять всеми контейнерами из одного файла (файл - формата yml). Теперь не нужно будет писать кучу docker run и длинные команды для запуска контейнеров: достаточно будет лишь запустить одну команду docker-compose up, после чего все контейнеры будут подняты без нашего вмешательства, причем со всеми  настройками, которые будут прописаны в yml-файле. Также docker-compose позволяет взаимодействовать с системой управления репозиториями программного кода. Например: gitlab.

Установка.

Для начала установим инструмент. Загружаем текущую стабильную версию:

сurl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

Делаем скачанный файл исполняемым:

chmod +x /usr/local/bin/docker-compose

Проверяем:

#:/# docker-compose --version 
docker-compose version 1.29.2, build 5becea4c

Все установлено и работает.

Подготовка:

Какие сервисы понадобятся?

  1. frontend: nginx.

  2. backend: php8.1-fpm.

  3. База данных: mysql.

Первым делом подготовим директории для работы. Для начала создадим директорию, где будет лежать docker-compose.yml. Мы приняли за стандарт, что в нашей компании все файлы docker-compose находится в директории /var/apps/. Создаем директорию и переходим в нее:

mkdir /var/apps
cd /var/apps

Создаем директорию проекта:

mkdir DOMAIN_NAME
cd DOMAIN_NAME/

Создаем файл docker-compose.yml:

touch docker-compose.yml

Теперь создадим директорию где будут хранится наши конфигурационные файлы площадок, конфигурации php.ini и так далее:

mkdir volumes

Давайте заранее создадим все директории и конфигурации наших сервисов:

cd volumes/
mkdir etc build
  1. etc - директория с конфигурационными файлами сервисов;

  2. build - директория с файлами Dockerfile в котором будут хранится все команды для сборки образа.

Далее:

mkdir etc/nginx etc/mysql etc/php-fpm8.1
mkdir etc/nginx/sites-enabled etc/nginx/ssl etc/mysql/conf.d etc/php-fpm8.1/fpm.pool.d
touch etc/nginx/nginx.conf etc/nginx/sites-enabled/DOMAIN_NAME.conf etc/mysql/conf.d/config-file.cnf etc/php-fpm8.1/php.ini etc/php-fpm8.1/fpm.pool.d/DOMAIN_NAME.conf
mkdir build/nginx build/php-fpm8.1 build/mysql
touch build/nginx/Dockerfile build/php-fpm8.1/Dockerfile build/mysql/Dockerfile

Получилась такая структура директорий:

  • app/ 

  • volumes/ (директория с конфигурационным файлами)

  • build/ (директория c Dockerfile для наших контейнеров)

    • mysql/
      Dockerfile

    • nginx/
      Dockerfile

    • php-fpm8.1/
      Dockerfile

  • etc/ (директория с конфигурационными файлами для наших сервисов)

    • mysql/

      • config-file.cnf

    • nginx/

      • sites-enabled/

        • ​​​DOMAIN_NAME.conf

      • nginx.conf

    • php-fpm8.1/

      • fpm.pool.d/

        • DOMAIN_NAME.conf

      • php.ini

  • docker-compose.yml

Ну или так:

В ./app/volumes/etc/mysql/config-file.cnf можно указывать все необходимые настройки для mysql. В нашем случае мы добавим:

[mysqld]
port = 3310
wait_timeout = 9000000
max_allowed_packet = 1024M
innodb_buffer_pool_size = 512M
innodb_log_buffer_size = 256M
innodb_log_file_size = 1G
innodb_write_io_threads = 16
innodb_flush_log_at_trx_commit = 0
net_read_timeout=500
net_write_timeout=500
interactive_timeout=600
connect_timeout=500
skip-log-bin
# Slow query settings:
slow_query_log=1
slow_query_log_file=/var/log/mysql/slow.log
long_query_time=2
# Error query settings:
log_error=/var/log/mysql/mysql_error.log
general_log_file=/var/log/mysql/mysql.log
general_log=1

В ./app/volumes/etc/nginx/nginx.conf можно указывать все необходимые настройки для nginx и площадки. В этом случае мы добавим:

nginx.conf:
user  nginx;worker_processes  6;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
events {  
	worker_connections  16384;
}

http {
include       /etc/nginx/mime.types;
default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '                      '$status $body_bytes_sent "$http_referer" '                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    ### gzip    gzip on;
    gzip_disable "msie6";

    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;

    client_body_buffer_size         1m;
    client_max_body_size            75m;
    
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    sendfile        on;
    #tcp_nopush     on;
    #gzip  on;

    include /etc/nginx/sites-enabled/*.conf;
    
    }

Файл площадки ./app/volumes/etc/nginx/sites-enabled/DOMAIN_NAME.conf можно взять из предыдущей статьи.

В ./app/volumes/etc/php-fpm8.1/fpm.pool.d/DOMAIN_NAME.conf добавляем настройки для php-fpm площадки:

[DOMAIN_NAME]
	listen = 172.16.1.5:9010   ;ip адрес и порт на котором будет находится php-fpm площадки.
	listen.mode = 0666
	user = DOMAIN_NAME   ;Пользователь площадки.
	group = DOMAIN_NAME  ;Группа пользователя площадки.
  pm = dynamic
  pm.max_children = 50
  pm.start_servers = 1
  pm.min_spare_servers = 1
  pm.max_spare_servers = 35
  pm.max_requests = 500
  request_terminate_timeout = 5m
  request_slowlog_timeout = 2s
  slowlog = /var/log/php/php-fpm.slow.log
  php_admin_value[opcache.max_accelerated_files] = 20000
  php_admin_value[realpath_cache_size] = 4096K
  php_admin_value[realpath_cache_ttl] = 600
  php_admin_flag[display_errors] = off;
  php_admin_value[error_log] = /var/www/DOMAIN_NAME/log/php-fpm/fpm-php.log
  php_admin_flag[log_errors] = on
  php_admin_value[open_basedir] = /var/www/DOMAIN_NAME
  php_admin_value[upload_tmp_dir] = /var/www/DOMAIN_NAME/upload
  php_admin_value[session.save_path] = /var/www/DOMAIN_NAME/sess

В ./app/volumes/etc/php-fpm8.1/php.ini можно добавлять все настройки для php. В нашем случае мы добавим:

upload_max_filesize = 500
Mmax_file_uploads = 20
post_max_size = 500
Mmemory_limit = 4096
Mdate.timezone = Europe/Moscow

Перед дальнейшими работами очистим все образы, собранные ранее в предыдущей статье. Для этого действия подойдет команда: 

docker system prune --volumes --all

Эта команда очищает все образы не запущенных контейнеров. Важное уточнение - именно не запущенных!

Смотрим запущенные контейнеры:

docker ps
CONTAINER ID   IMAGE                       COMMAND                  CREATED        STATUS                          PORTS                                                                      NAMES
5f3353afe4fc   nginx:stable                "/docker-entrypoint.…"   4 months ago   Up About a minute               0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   nginx
88c83f238c5c   php-fpm                     "/docker-entrypoint.…"   4 months ago   Up About a minute               9000/tcp                                                                   php-fpm

Для остановки всех контейнеров можно использовать команду:

docker stop $(docker ps -a -q)
docker stop $(docker ps -a -q)
5f3353afe4fc
88c83f238c5c

Далее очищаем образы командой docker system prune --volumes --all:

:~# docker system prune --volumes --all
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all volumes not used by at least one container
  - all images without at least one container associated to them
  - all build cache
Are you sure you want to continue? [y/N] y

Deleted Containers:
d25fadd1ace48b1e1d7285c79c924928fd2df54395f3cab9d1184bf25745404f
a156787f2e2d20585272f90b86fbfd82c6ff28fd6bd3e17785be1530e0dcf433
034a89f5322498cd272436515a43a9d82e0f32cdbd2da230a8211f1af7134619
c422454c2b997aec3e473998b3f51cbe5b322c00c094de9bfc20aba3af403830
5f3353afe4fc381fb2aa554700fb0a37ef378e923b5662241549722b243f84ea
88c83f238c5cfe7c71293793d54149e5e6aaf9db92dce9f0f1c9ac2e5e35be3c
77f498f59e80623dd325f6297dcc1c0b068c0fc0b373ca5c137d49052f71276f
Deleted Networks:
default
docker_default
Deleted Volumes:
171304f87cde0dbe4142c80e10e30076acfdae1c9d1ac0ed73125e8938bd13af
65e26f00da5308b81afe3d870d63243716df4935445b25648c5c69392151fefe
a016235f662b38c657f5e04283fc54d779d18c6e9d778c04e2a5fc264fec428b
a20375ceb893d7ae95c2b5ffd10c8557b49f02896a456c22a9015d17f34bd490
untagged: nginx:stable
untagged: nginx@sha256:74fb4c9d7e4fe6a8ab699d66fb5ffbf3daf1025bbb6f65a3217dde6e8f4d6e56
deleted: sha256:50fe74b50e0d0258922495297efbb9ebc3cbd5742103df1ca54dc21c07d24575
deleted: sha256:5c89b8cf56a58aa2a96ab1ed19ffd8e0630355776b1db7082fd897f8a5d285d4
deleted: sha256:e45a683cc5d56e842fc90c7ad0535abb1e909f733c2c0c29f4cf43f7247f8438
deleted: sha256:7ffdf2d40e75d1028ecbdba3cd5c548dc7a2b6c6b6598c2ff0af1f864df662e8
deleted: sha256:43828a7cbba35611955d78d1849ba6e48f176c96795ea881a7a9adcf5eb23bfa
deleted: sha256:e6ffc9b8132b8380efc5dd578d3e369890abaa492863968a5c41bdf9a8e5070e
deleted: sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f
untagged: php-fpm:latest
deleted: sha256:cac496cb3198354a8bf68188c5cec929ba149e4f8f331c32f38e45ecc0bd0e67
deleted: sha256:21c4defd66f2e9e64c7b331a7580466403d4e2008d12864f2a29790ff1473a76
deleted: sha256:90f506af9c6530b6cc3c27ad661a9f4c4bfe64a57f313bad65ab67064ca7a880
deleted: sha256:45e703bc20b6aa77dd834ae2c81d1889be7a8b025d7570aa6034569210f25612
deleted: sha256:0f9ac9b1acec55805e6a2cb53b85406b39b07c5154bea03dc575f632e860cff9
deleted: sha256:5e1a9584d37f2f438eb4f9719591b72d9113d0b93e9fd336ee61e9653faaf156
deleted: sha256:bf23cc62c0e983ea1ed5b3b38bd78a86d26ab85de691802a81a800475a1a4e75
deleted: sha256:adf7df76ecb09fcd0fb8c283c8ac1aada505ed57bfa733461cc555d8ca23a816
deleted: sha256:2e09cf02796f006bde367ee89fcfd0053abbf080ef240e715343d6ead0b44851
deleted: sha256:c41477d2876d165d26869efd878a6e3b2fee7fafa10e51c5246909b6622d3b2c
deleted: sha256:9f0f98eb9fa7bd5d06653241253eda67fd08326b2634e903bb66dea0e2fb5139
deleted: sha256:4442cb52388be2f9a3ba0e6d6682e87d4586677d94c31af9064fc9315d0370cc
deleted: sha256:7ea425a7c077487583d85343140c2200a35bf98839a7228a789c74d4419c708f
deleted: sha256:cf3704308d18d0e52028613a7795a39658b02f345c647cf6aa0d82ec6dd51908
deleted: sha256:d943dbca5ecfa509906e2644be6e918c1c5961914271a320b895923c5324014f
deleted: sha256:ffc6430b96530f2b7d3f53e1cc64ec24852d9a1a826f687d87e0f6e4eec54869
deleted: sha256:8e32d40714a5cca10289b3fc0ded459b05320abc120bee3525f17c696c4bdb2e
deleted: sha256:3c4d7d6769cd7accbd1ccf61175010a1dfabbe435dab26ec2d771daba9de6f86
deleted: sha256:49143d13ba872d32b27bb2765beb496ac60d6b85414cd371a518c9946ec90b25
deleted: sha256:4883d13c15029dd0eab0e9fb7b3e00d8b0139e0d643e4c6e4bc144228e9e7e8f
deleted: sha256:2004464b54089dd15804882cb4803381532e0589d38f47f9729f7fb6ef169c34
deleted: sha256:c71714a613ec902f20bf8dce9866f62702302994af53bdd104331c19c7339da4
deleted: sha256:b1783cc83184509d3fffd30ba119ea1f11ec8602fdc50ba2c3e062e02df56e80
deleted: sha256:3e84bd99827c4963eab48a3e54bd088f7a206adb3aacd45361027327d5ca8443
deleted: sha256:d10560a7f2e4534ce146753b0748f1e73ce1b50f458f1e12385e19222b221b69
deleted: sha256:9c84657b917192c0490faf836824a113e6c397146db7a73fc2dc47755224c026
deleted: sha256:c13bd6861c9c7576cb27df56517347b5b7b28e68ce93e69a6ff25d8f1b4b4f6e
deleted: sha256:ced7cbb4abb893d33743c81fcbe3caf9c64da09a6fd9fa2f75efdfa0fd6efd6b
deleted: sha256:32f19a4eb0921d3b110352c4bdcdc7b64bd47092e1e15fe918e94cf6039037d8
deleted: sha256:054e2126fd90e29711637456090b61fc9b883eeb95ccf94430026ab7d5d14541
deleted: sha256:e8f41b5970d0e2b904babde28c490135b83b0a0be9ff7101171c203cc23af5fb
deleted: sha256:e022aa4b2c5f34b58acd5050d77cc23c087395010ab525ae9802ddc0ea52559c
deleted: sha256:ebdafce0fbc3adbde2ec9308930be55d3df801a2f62b31bd5b0b1162a54fea7e
deleted: sha256:c3744e7ff118e96f517ff1b4f97ee8ee62695d7cf97aec267b9bd73df77581ee
deleted: sha256:3b56d7cccfcf2579595d9d21f0788129276743ea2957f05cd9e49317fefd852f
deleted: sha256:d204f4d10e96af88215de15a6b47de64668572bfe9f143bc17f0adf0285c02bd
deleted: sha256:8c5518abda1bc707b21cc845ea17ebf5dcb4d05f8b5b5164d863255ea59390d4
deleted: sha256:9321ff862abbe8e1532076e5fdc932371eff562334ac86984a836d77dfb717f5
Total reclaimed space: 1.813GB

Все контейнеры и образы были удалены с сервера.

Базовая настройка завершена.

Приступаем к написанию нашего yml-файла.

ВНИМАНИЕ! Важное уточнение: так как это файл формата yml, в нем очень строго необходимо следить за пробелами и отступами и никогда не использовать TAB. В противном случае вы можете получить синтаксическую ошибку - например, лишний пробел где-нибудь в 80-ой строке, на поиск которого у вас может уйти не один час =).

Итак, открываем docker-compose.yml.

Пункт 1. Указание версии.

Для начала указываем, какую версию docker-compose будем использовать. В нашем случае мы используем версию 2.4 - её нам будет вполне достаточно. 

Для ознакомления со всеми версиями, и для чего они нужны, можете перейти на официальный мануал по этому поводу: version.

Добавляем:

version: '2.4'

Пункт 2. Объявляем сервисы.

Добавляем:

services:

Мы объявляем, что далее будут идти наши контейнеры.

Пункт 3. Объявляем наши контейнеры.

Не забываем про формат yml, поэтому делаем два пробела и добавляем:

nginx:
php-fpm8.1:
mysql:

Выглядит это так:

version: '2.4'
services:
  nginx:
  php-fpm8.1:
  mysql:

Пункт 4: Локальная сеть контейнеров.

Давайте заранее обьявим нашу сеть, чтобы больше к ней не возвращаться. За сеть у нас отвечает ключ networks.

Добавляем такие строки: 

networks:
  default:
    driver: bridge
    ipam:
      config:
        - subnet: 172.16.1.0/24
  1. default - название нашей сети. Можете использовать любое название.

  2. driver - драйвер нашей сети. 

  3. ipam - конфигурация сети. В данном случае мы указываем нашу локальную подсеть 172.16.1.0/24

Получаем:

version: '2.4'
services:
	nginx:
	php-fpm8.1:
  mysql:

networks:
	default:
  	driver: bridge
    ipam:
    	config:
      	- subnet: 172.16.1.0/24

Пункт 4.5. Основные конфигурации и ключи нашего файла docker-compose.

  1. container_name: - название контейнера;

  2. hostname: - hostname в контейнере;

  3. build: - загружаем файл Dockerfile, в котором будут хранится все команды для сборки образа;

  4. extra_hosts: - пункт, в котором мы указываем, какая запись будет в hosts на нашем сервере;

  5. ports: - порты, которые мы хотим прокинуть в контейнер;

  6. volumes: - директории, которые мы хотим прокинуть в контейнер.

    Для чего необходимо пробрасывать директории в контейнер? Каждый раз, когда мы будем пересобирать контейнер, у нас будут удаляться все внутренние директории. Для того, чтобы это не происходило, мы пробрасываем директорию в контейнер. После чего все файлы будут храниться на хост-машине, и после того, как будет пересобран контейнер, файлы будут в целости и сохранности.

    Например: У нас имеется mysql в контейнере. Если мы не пробросим директорию с БД, то все наши БД буду удалены после того, как мы пересоберем контейнер. Поэтому для всех сервисов лучше всего пробрасывать все нужные директории. Это важно!

  7. networks: - ip адрес который мы присвоим нашему контейнеру;

  8. links: - приоритет загрузки контейнеров;

  9. restart: - частота перезагрузка контейнера в случае ошибки.

Пункт 5. Пишем nginx.

Переходим к строчке nginx и делаем отступ 4 пробела. Формат yml (да, не устану это повторять:)).

Указываем название контейнера container_name:

container_name: DOMAIN_NAME-nginx

Указываем hostname:

hostname: DOMAIN_NAME-nginx

Указываем местонахождение нашего Dockerfile для сборки build:

build: ./volumes/build/nginx

Указываем директории, которые необходимо прокинуть в контейнер с помощью volumes. Обязательно необходимо прокинуть:

  1. Файлы площадки. Для работы со статикой.

  2. Конфигурацию nginx. Для быстрого управление в случае необходимости.

  3. Конфигурационные файлы площадки. Для работы площадки.

  4. Директорию с сертификатами ssl. Для быстрого подключения работы по https.

  5. Директорию с log-файлом nginx. Для удобства анализа в дальнейшем.

Указываем volumes и прокидываем директории через дефис:

    volumes:
      - ./var/log/nginx:/var/log/nginx #log файлы.
      - ./volumes/etc/nginx/nginx.conf:/etc/nginx/nginx.conf:ro #Конфигурация nginx.
      - ./volumes/etc/nginx/sites-enabled:/etc/nginx/sites-enabled:ro #Конфигурация площадок.
      - ./volumes/etc/nginx/ssl:/etc/nginx/ssl:ro #сертификаты
      - /var/www/DOMAIN_NAME:/var/www/DOMAIN_NAME #Домашняя директория

Ключ :ro означает read only. Он добавлен для безопасности, чтобы внутри контейнера нельзя было изменить конфигурационные файлы.

Указываем порты ports:

Открываем порты 80 и 443 на хосте и пробрасываем их в контейнер.

    ports:
      - "80:80"
      - "443:443"

Указываем приоритет загрузки links:

    links:
      - php-fpm

Контейнер nginx  не будет загружен быстрее чем контейнер с php-fpm. Делается для того, чтоб пользователя не видели 502 код ответа, в случае перегрузки контейнеров.

Указываем как часто можно перезагружаться контейнеру в случае ошибки:

    restart:
      always

Присваиваем ip адрес контейнеру с помощью networks:

     networks:
       default:
         ipv4_address: 172.16.1.4

В итоге получается у так:

 nginx:
    container_name: DOMAIN_NAME-nginx
    hostname: DOMAIN_NAME-nginx
    build: ./volumes/build/nginx
    volumes:
      - ./var/log/nginx:/var/log/nginx #log файлы.
      - ./volumes/etc/nginx/nginx.conf:/etc/nginx/nginx.conf:ro #Конфигурация nginx.
      - ./volumes/etc/nginx/sites-enabled:/etc/nginx/sites-enabled:ro #Конфигурация площадок.
      - ./volumes/etc/nginx/ssl:/etc/nginx/ssl:ro #сертификаты
      - /var/www/DOMAIN_NAME:/var/www/DOMAIN_NAME #Домашняя директория
    ports:
      - "80:80"
      - "443:443"
    links:
      - php-fpm
    restart:
      always
    networks:
      default:
        ipv4_address: 172.16.1.4

 Анализируем:

У нас имеется контейнер nginx:

  • С названием  DOMAIN_NAME-nginx

  • hostname в контейнере DOMAIN_NAME-nginx

  • Собирающийся из нашего Dockerfile по адресу ./volumes/build/nginx

  • С прокинутыми директориями и файлами ./var/log/nginx, ./volumes/etc/nginx/nginx.conf, ./volumes/etc/nginx/sites-enabled/, ./volumes/etc/nginx/ssl/, /var/www/DOMAIN_NAME/

  • Работающий на 80 и 443 портах хост машины

  • Запускающийся только после контейнера php-fpm

  • Часто перезагружаемый в случае ошибки и с ip адресом 172.16.1.4.

Пункт 6. Пишем php-fpm.

Переходим к строке php-fpm.

Название:

    container_name: DOMAIN_NAME-php-fpm

Hostname:

   hostname: DOMAIN_NAME-php-fpm

Расположение Dockerfile:

    build: ./volumes/php-fpm/build

Приоритет загрузки links: указывать не нужно.

Порты:

   ports:
      - "9000:9010"

Директории, которые нужно прокинуть:

  1. Директория площадки.

  2. php.ini php-fpm для быстрого изменения конфигурации (в случае необходимости).

  3. Конфигурационный файл площадки.

  4. log файл php.

Прокидываем:

    volumes:
      - ./volumes/etc/php/fpm.pool.d/DOMAIN_NAME.conf:/usr/local/etc/php-fpm.d/DOMAIN_NAME.conf:ro #Конфигурация площадки
      - ./volumes/etc/php/nxs-std.ini:/usr/local/etc/php/conf.d/nxs-std.ini:ro #Конфигурация php для php-fpm
      - /var/log/php:/var/log/php #log файлы
      - /var/www/DOMAIN_NAME:/var/www/DOMAIN_NAME #Домашняя директория

IP адрес:

    networks:
      default:
        ipv4_address: 172.16.1.5

Добавляем права на все изменения в докере php:

    cap_add:
      - SYS_NICE
      - DAC_READ_SEARCH

Для чего это нужно? Например php-fpm необходимо будет сменить приоритет процесса. Если данная строка будет отсутствовать, то получим ошибку:

mbind: Operation not permitted

Или, например, площадка у нас работает от пользователя DOMAIN_NAME. Для того, чтобы площадка работала в контейнере, php-fpm необходимо добавить пользователя в систему. Если строки не будет, то будет выдаваться аналогичная ошибка.

Перезагрузка контейнера:

    restart: always

Итог:

  php-fpm:
    container_name: DOMAIN_NAME-php-fpm
    hostname: DOMAIN_NAME-php-fpm
    build: ./volumes/php-fpm/build
    ports:
      - "9000:9010"
    volumes:
      - ./volumes/etc/php/fpm.pool.d/DOMAIN_NAME.conf:/usr/local/etc/php-fpm.d/DOMAIN_NAME.conf:ro #Конфигурация площадки
      - ./volumes/etc/php/php.ini:/usr/local/etc/php/conf.d/nxs-std.ini:ro #Конфигурация php для php-fpm
      - /var/log/php:/var/log/php #log файлы
      - /var/www/DOMAIN_NAME:/var/www/DOMAIN_NAME #Домашняя директория
    cap_add:
      - SYS_NICE
      - DAC_READ_SEARCH
    restart: always
    networks:
      default:
        ipv4_address: 172.16.1.5

У нас имеется контейнер php-fpm:

  • С названием  DOMAIN_NAME-php-fpm;

  • hostname в контейнере DOMAIN_NAME-php-fpm;

  • Собирающийся из нашего Dockerfile по адресу ./volumes/php-fpm/build. С прокинутыми директориями и файлами ./volumes/etc/php/fpm.pool.d/DOMAIN_NAME.conf, ./volumes/etc/php/php.ini, /var/log/php,  /var/www/DOMAIN_NAME/;

  • Работающий на 9000 порте хост машины;

  • Часто перезагружаемый в случае ошибки и с ip адресом 172.16.1.5.

Пункт 7. Пишем mysql.

Переходим к строке mysql.

Название:

   container_name: DOMAIN_NAME-mysql

Hostname:

     hostname: DOMAIN_NAME-mysql

Расположение Dockerfile:

    build: ./volumes/mysql/build

Приоритет загрузки links: указывать не нужно.

Порты:

    ports:
      - "3310:3310"

Директории, которые нужно прокинуть:

  1. Директория для хранения БД.

  2. Конфигурационный файл mysql.

  3. log файл mysql.

Прокидываем:

    volumes:
      - /var/lib/mysql:/var/lib/mysql #Директория БД.
      - /var/log/mysql:/var/log/mysql #log файл
      - ./volumes/mysql/conf.d:/etc/mysql/conf.d:ro #Конфигурация mysql.

IP адрес:

    networks:
      default:
        ipv4_address: 172.16.1.6

Перезагрузка контейнера:

    restart: always

Итог:

  mysql:
    container_name: DOMAIN_NAME-mysql
    hostname: DOMAIN_NAME-mysql
    build: ./volumes/mysql/build
    ports:
      - "3310:3310"
    volumes:
      - /var/lib/mysql:/var/lib/mysql #Директория БД.
      - /var/log/mysql:/var/log/mysql #log файл
      - ./volumes/mysql/conf.d:/etc/mysql/conf.d:ro #Конфигурация mysql.
    networks:
      default:
        ipv4_address: 172.16.1.6

У нас имеется контейнер mysql:

  • С названием  DOMAIN_NAME-mysql;

  • hostname в контейнере DOMAIN_NAME-mysql;

  • Собирающийся из нашего Dockerfile по адресу ./volumes/mysql/build;

  • С прокинутыми директориями и файлами /var/lib/mysql, /var/log/mysql:/var/log/mysql, ./volumes/mysql/conf.d;

  • Работающий на 3010 порте хост машины;

  • Часто перезагружаемый в случае ошибки и ip адресом 172.16.1.6.

Пункт 8. Общий итог нашего docker-compose.yml:

version: '2.4'
services:
  nginx:
    container_name: DOMAIN_NAME-nginx
    hostname: DOMAIN_NAME-nginx
    build: ./volumes/build/nginx
    volumes:
      - ./var/log/nginx:/var/log/nginx #log файлы.
      - ./volumes/etc/nginx/nginx.conf:/etc/nginx/nginx.conf:ro #Конфигурация nginx.
      - ./volumes/etc/nginx/sites-enabled:/etc/nginx/sites-enabled:ro #Конфигурация площадок.
      - ./volumes/etc/nginx/ssl:/etc/nginx/ssl:ro #сертификаты
      - /var/www/DOMAIN_NAME:/var/www/DOMAIN_NAME #Домашняя директория
    ports:
      - "80:80"
      - "443:443"
    links:
      - php-fpm
    restart:
      always
    networks:
      default:
        ipv4_address: 172.16.1.4

  php-fpm:
    container_name: DOMAIN_NAME-php-fpm
    hostname: DOMAIN_NAME-php-fpm
    build: ./volumes/php-fpm/build
    ports:
      - "9000:9010"
    volumes:
      - ./volumes/etc/php/fpm.pool.d/DOMAIN_NAME.conf:/usr/local/etc/php-fpm.d/DOMAIN_NAME.conf:ro #Конфигурация площадки
      - ./volumes/etc/php/nxs-std.ini:/usr/local/etc/php/conf.d/nxs-std.ini:ro #Конфигурация php для php-fpm
      - /var/log/php:/var/log/php #log файлы
      - /var/www/DOMAIN_NAME:/var/www/DOMAIN_NAME #Домашняя директория
    cap_add:
      - SYS_NICE
      - DAC_READ_SEARCH
    restart: always
    networks:
      default:
        ipv4_address: 172.16.1.5

  mysql:
    container_name: DOMAIN_NAME-mysql
    hostname: DOMAIN_NAME-mysql
    build: ./volumes/mysql/build
    ports:
      - "3310:3310"
    volumes:
      - /var/lib/mysql:/var/lib/mysql #Директория БД.
      - /var/log/mysql:/var/log/mysql #log файл
      - ./volumes/mysql/conf.d:/etc/mysql/conf.d:ro #Конфигурация mysql.
    networks:
      default:
        ipv4_address: 172.16.1.6

networks:
  default:
    driver: bridge
    ipam:
      config:
        - subnet: 172.16.1.0/24

Итак, мы разобрали базовые ключи и команды для написание docker-compose. Теперь вы можете самостоятельно писать yml, а самое главное понимать, что именно вы написали! Но перед запуском необходимо написать Dockerfile, и в следующей статье мы с вами разберем, что это такое, для чего Dockerfile нужен, и как его красиво писать. После чего запустим наш docker-compose, накатим WordPress и проверим его работу.

Спасибо за уделенное нам время. Надеемся, статья была для вас познавательной. Если остались вопросы - задавайте в комментариях, мы с радостью на них ответим. Всем удачного администрирования и чтоб ваш PROD никогда не падал!

P.S.: Еще больше полезной информации - в телеграм-канале DevOps FM, присоединяйтесь.

Комментарии (7)


  1. nikweter
    25.04.2022 15:47
    +2

    Еще бы осветить настройку проксирования с фронта на бэк. Когда на на фронте не голый nginx, а что-то вроде react-vue-etc, то возникают некоторые неочевидные тонкости.


  1. sswwssww
    25.04.2022 23:12
    +2

    При описании nginx docker-compose файла, у блока network неправильный уровень вложенности(хотя в конечно варианте все ок), подправьте.


    1. thisprogame Автор
      26.04.2022 04:41
      +1

      Спасибо, исправил!))


  1. stralex7
    26.04.2022 10:17
    +2

    Не совсем разобрался зачем присваиваются статические адреса контейнерам?


    1. thisprogame Автор
      27.04.2022 07:40

      Привет!

      Если у контейнера не статический ip. То:
      Когда контейнер пересобирается (Например: необходимо открыть новые порты) ip адрес может измениться, после чего необходимо будет заново настраивать проксирование в nginx, либо указывать новый ip адрес в коде площадки. Все это время площадка будет возвращать ошибку, пока не будет указан новый ip адрес. Также, при переносе на другой сервер ip адреса будут всегда разные и из-за этого необходимо будет всегда править конфигурационные файлы и вписывать правильный ip адрес. Для того, чтоб контейнеры, сервисы могли между собой общаться.
      Этого всего можно избежать, просто указав статический ip адрес. После чего у контейнера всегда будет один и тот же ip даже если перенести его на другой сервер. Это очень удобно!


      1. stralex7
        27.04.2022 10:28
        +1

        Мне кажется вы можете обращаться внутри по имени контейнера. Внешнее подключение от него на зависит, так как у вас проброс портов во внешнюю сеть через NAT -ports:

        В ситуации в которой вам надо поменять подсеть в случае пересечения по тем или иным причинам, то придётся только сменить определение сети


        1. thisprogame Автор
          28.04.2022 07:24

          Да, все верно можно так делать.

          Но, по нашему опыту обучения стажеров. Лучше на первых этапах обучения работать именно с ip адресами. Для того, чтоб понять весь смысл работы docker.