Теперь нам нужно подготовить прочную основу для дальнейшей раскатки всего и вся в контейнерах. В будущем нам понадобятся:
MySQL (развернули в ч. 5)PostgreSQL (развернули в ч. 6)PHPMyAdmin (развернули в ч. 7)PgAdmin (развернули в ч. 7)Nginx- PHP-FPM
В этой части развернём подготовим всё для запуска php-fpm, а вот запустим его и WordPress на его базе уже в следующей части.
Напоминаю, что сервер развёрнут и работает в timeweb.cloud, но вы можете использовать любой другой VPS.
Итак, последний компонент инфраструктуры, по факту тут мы просто создадим директорию и "подложим" настройки, "подложим" WordPress (исходные файлы), а уже в следующей части будем его устанавливать и настраивать. Итак, сегодняшняя цель - увидеть интерфейс установки WP на экране, пробросом через nginx к нашем PHP-FPM.
Подгружаем конфигурации php-fpm
Первым шагом переходим по ссылке:
Скачиваем директорию php-fpm и загружаем её на наш сервер в:
/home/docker-admin/infra/
В директории лежат несколько вариантов конфигурации php-fpm и ряд общих файлов, как и какие использовать - увидите дальше.
Готовим контейнер для WordPress
Теперь создаём раздел sites в /home/docker-admin:
mkdir -p /home/docker-admin/sites/wp_teach/sources
Туда загрузим исходники WordPress (скачать можно отсюда) - грузим архивом в sources. После переходим туда сами, используя команду:
cd /home/docker-admin/sites/wp_teach/sources
И выполняем команды:
unzip wordpress-6.8.1-ru_RU.zip
rm -rf wordpress-6.8.1-ru_RU.zip
mv wordpress/* ./
mv wordpress/.* ./
rmdir wordpress/
Первая - распаковывает архив
Вторая - удаляет его
Третья и четвёртая переносят все файлы из директории wordpress в sources
Пятая - удаляем директорию wordpress
После загрузки содержимое директории должно быть таким:
Теперь настало время собрать для нашего сайта docker-compose файл. Кроме того, тут мы впервые будем писать свой собственный Dockerfile, добавлять список игнорирования (чтобы не тянуло лишнего в контейнер) и собирать образ перед стартом в docker-swarm.
В /home/docker-admin/sites/wp_teach/ создаём файл .dockerignore (скрытый файл) и пишем в него одну единственную строку:
sources
После создаём Dockerfile со следующим содержимым:
FROM php:7.4-fpm
RUN apt update && apt upgrade -y && apt install -y libcurl4-openssl-dev zlib1g-dev libpng-dev libjpeg-dev libfreetype6-dev libxml2-dev libonig-dev libsnmp-dev libzip-dev libpq-dev libwebp-dev
RUN docker-php-ext-configure gd --with-jpeg -with-webp && docker-php-ext-install -j$(nproc) gd
RUN docker-php-ext-install curl mysqli pdo_mysql json opcache xml xmlrpc intl mbstring snmp soap zip
Что мы тут делаем:
- Наследуемся от Dockerfile php:7.4-fpm (базовая сборка)
- Запускаем команду, которая при сборке образа установит в ОС необходимые пакеты
- Двумя следующими пунктами ставим необходимые расширения
Последняя команда разбита на две для большей гибкости, например, если мы не захотим пересобирать весь образ, а нужно будет добавить какой-то пакет, то добавление его в 4ю команду (4й слой) поможет ускорить процесс сборки.
После того как докерфайл сохранён - сбилдим образ, для этого выполняем команду:
sudo docker build /home/docker-admin/sites/wp_teach/ --tag=prod_wp_teach_main:latest
Если всё задано правильно, начнётся сборка образа:
Что мы сделали:
- Команде docker build передали путь в Dockerfile на основе которого нужно собрать образ
- Передав параметр --tag= - указали, как должен называться собранный образ
При этом, если бы мы работали с docker-compose - там есть параметр build, который позволяет ребилдить образы при запуске, однако, swarm это классический оркестратор, его логика в том что он не должен брать на себя дополнительные задачи, а просто управляет запуском готовых контейнеров, но делает это хорошо)
Если сборка завершилась успешно - мы увидим примерно такие надписи:
Теперь заполним docker-compose.yml:
version: "3.9"
services:
wp_app_main:
image: prod_wp_teach_main:latest
deploy:
mode: replicated
replicas: 2
resources:
limits:
cpus: "0.5"
memory: 512M
reservations:
memory: 128M
restart_policy:
condition: on-failure
update_config:
parallelism: 2
delay: 10s
tty: true
volumes:
- type: bind
source: ./sources
target: /var/www/html/uprod/
- type: bind
source: /home/docker-admin/infra/php-fpm/zz-docker.conf
target: /usr/local/etc/php-fpm.d/zz-docker.conf
- type: bind
source: /home/docker-admin/infra/php-fpm/www.conf
target: /usr/local/etc/php-fpm.d/www.conf
- type: bind
source: /home/docker-admin/infra/php-fpm/php.ini
target: /usr/local/etc/php/php.ini
environment:
TZ: Russia/Moscow
networks:
- portainer_composite_nw
networks:
portainer_composite_nw:
external: true
Тут нет каких-то особых изменений, кроме одного. Мы впервые запускаем две реплики, т.е. у нас будет работать два экземпляра контейнера под оркестрацией. При этом какие-то донастройки на стороне nginx делать не требуется - все задачи маршрутизации берёт на себя встроенный в swarm функционал.
Пробуем запустить контейнер:
sudo docker stack deploy -c /home/docker-admin/sites/wp_teach/docker-compose.yml wp_teach
Если всё прошло успешно - в списке появится два новых контейнера:
Настраиваем проксирование nginx
Для того, чтобы всё "взлетело" нужно:
- Добавить точку монтирования с файлами WordPress в nginx
- Добавить маршрут в .conf файл (будем использовать тот же - infr.conf)
Добавление точки монтирования предельно простое, открываем файл:
/home/docker-admin/infra/nginx/docker-compose.yml
И прописываем туда (в раздел nginx, где мы монтируем остальные директории):
version: '3.9'
services:
webserver:
image: nginx:1.25
deploy:
replicas: 1
resources:
limits:
cpus: "1"
memory: 1G
reservations:
memory: 256M
restart_policy:
condition: on-failure
ports:
- target: 80
published: 80
mode: host
- target: 443
published: 443
mode: host
tty: true
volumes:
- type: bind
source: ./service_folders/nginx/conf
target: /etc/nginx/conf.d
- type: bind
source: ./service_folders/www/html/0_default
target: /var/www/html/0_default
- type: bind
source: /etc/letsencrypt/
target: /etc/letsencrypt/
- type: bind
source: ./service_folders/logs
target: /var/log/www
- type: bind
source: /home/docker-admin/sites/wp_teach/sources/
target: /var/www/html/uprod/
environment:
- APP_NAME=webserver_sites
- TZ=Russia/Moscow
networks:
- portainer_composite_nw
networks:
portainer_composite_nw:
external: true
После этого в /home/docker-admin/infra/nginx/service_folders/nginx/conf/infr.conf добавляем блоки (выделил крупным шрифтом):
server {
listen 80;
server_name teach.testarea.biz www.teach.testarea.biz;
return 301 https://teach.testarea.biz$request_uri;
}
# HTTPS www → HTTPS без www
server {
listen 443 ssl http2;
server_name www.teach.testarea.biz;
ssl_certificate /etc/letsencrypt/live/teach.testarea.biz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/teach.testarea.biz/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
return 301 https://teach.testarea.biz$request_uri;
}
# Основной HTTPS сервер
server {
listen 443 ssl http2;
server_name teach.testarea.biz;
ssl_certificate /etc/letsencrypt/live/teach.testarea.biz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/teach.testarea.biz/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
access_log /var/log/www/teach.access_log;
error_log /var/log/www/teach.error_log;
root /var/www;
gzip on;
gzip_types text/plain application/xml;
gzip_proxied no-cache no-store private expired auth;
gzip_min_length 1000;
index index.php;
client_max_body_size 32m;
location /pma/ {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Scheme $scheme;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://sqladmin_phpmyadmin:80/;
rewrite ^/pma(/.*)$ $1 break;
}
location /pga/ {
proxy_set_header X-Script-Name /pga;
proxy_set_header Host $host;
proxy_pass http://sqladmin_pgadmin:80/;
proxy_redirect off;
}
location / {
root /var/www/html/uprod;
try_files $uri $uri/ /index.php?$args;
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PICO_URL_REWRITING 1;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass wp_teach_wp_app_main:9000;
#fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_read_timeout 600;
}
}
Теперь у нас ведётся логирование обращений и ошибок, а также корень: teach.testarea.biz должен открывать страницу установки WordPress. Чтобы применить изменения - пересоздаём контейнер с nginx:
sudo docker stack rm nginx
sudo docker stack deploy -c /home/docker-admin/infra/nginx/docker-compose.yml nginx
Если всё сделали без ошибок, на выходе увидим WordPress, готовый к установке по адресу (для моего примера): https://teach.testarea.biz/wp-admin/setup-config.php