Site icon 8HOST.COM

Установка WordPress с помощью Docker Compose: сервисы и SSL-сертификаты

WordPress – это свободная и открытая система управления контентом (CMS), построенная на базе данных MySQL с обработкой PHP. Благодаря своей расширяемой архитектуре на основе плагинов и шаблонов, а также возможности управлять через веб-интерфейс, WordPress является популярным выбором при создании различных веб-сайтов – от блогов до посадочных страниц и eCommerce сайтов.

Запуск WordPress обычно включает в себя установку стека LAMP (Linux, Apache, MySQL и PHP) или LEMP (Linux, Nginx, MySQL и PHP), что может занять много времени. Однако с помощью таких инструментов, как Docker и Docker Compose, вы можете упростить процесс настройки стека и установки WordPress. Вместо ручной установки отдельных компонентов вы можете использовать образы, которые многое стандартизируют (библиотеки, конфигурационные файлы и переменные среды), и запускать эти образы в изолированных контейнерах, которые выполняются в общей операционной системе. Кроме того, с помощью Compose вы можете координировать работу нескольких контейнеров – например, приложения и базы данных – и связать их друг с другом.

В этом мануале мы создадим мультиконтейнерную установку WordPress, где будет контейнер базы данных MySQL, веб-сервера Nginx и самого WordPress. Также мы защитим установку, получив для домена, который вы хотите связать с вашим сайтом, сертификаты TLS/SSL от Let’s Encrypt. Также мы настроим cron для обновления ваших сертификатов, чтобы домен оставался зашифрованным.

Требования

1: Определение конфигурации веб-сервера

Прежде чем запускать какие-либо контейнеры, нужно определить конфигурации веб-сервера Nginx. Его конфигурационный файл будет включать в себя специальные блоки location для WordPress, а также блок location для направления запросов верификации Let’s Encrypt на клиент Certbot (для автоматического обновления сертификатов).

Сначала создайте каталог проекта для вашей установки WordPress под названием wordpress и перейдите в него:

mkdir wordpress && cd wordpress

Затем создайте каталог для конфигурационного файла:

mkdir nginx-conf

Откройте файл с помощью nano или другого редактора:

nano nginx-conf/nginx.conf

В этот файл мы поместим блок server с директивами server name и document root, а также блоки location для направления запроса клиента Certbot, обработки PHP и запросов статических активов.

Вставьте следующий код в файл. Обязательно замените example.com собственным доменным именем:

server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
index index.php index.html index.htm;
root /var/www/html;
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html;
}
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass wordpress:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location ~ /\.ht {
deny all;
}
location = /favicon.ico {
log_not_found off; access_log off;
}
location = /robots.txt {
log_not_found off; access_log off; allow all;
}
location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
expires max;
log_not_found off;
}
}

Давайте подробно разберем, какую информацию содержит блок server.

Директивы:

Блоки location:

Читайте также: Алгоритмы выбора блоков server и location в Nginx

Сохраните и закройте файл, когда закончите редактирование. Если вы использовали nano, нажмите Ctrl+X, Y, а затем Enter.

После конфигурации Nginx вы можете перейти к созданию переменных среды, которые будут передаваться в приложение и контейнеры базы данных во время выполнения.

2: Определение переменных среды

Ваша БД и контейнеры приложений WordPress нуждаются в доступе к определенным переменным среды во время выполнения, чтобы данные приложения сохранялись и были доступны. Эти переменные должны содержать имя базы данных приложения и хоста. Они в том числе включают в себя конфиденциальную информацию: root пароль MySQL, пароль пользователя и базы данных приложения.

Вместо того чтобы указывать все эти значения в файле Docker Compose – главном файле, который содержит информацию о том, как будут работать контейнеры, – мы можем установить конфиденциальные значения в файле .env и ограничить его использование. Таким образом можно предотвратить копирование конфиденциальных данных в репозитории проектов и, следовательно, их раскрытие.

В основном каталоге проекта ~/wordpress откройте файл .env:

nano .env

Конфиденциальные значения, которые нужно указать в этом файле, включают пароль root пользователя MySQL, а также имя и пароль, которые WordPress будет использовать для доступа к базе данных.

Добавьте следующие имена переменных и значения в файл. Не забудьте указать свои собственные значения для каждой переменной:

MYSQL_ROOT_PASSWORD=your_root_password
MYSQL_USER=your_wordpress_database_user
MYSQL_PASSWORD=your_wordpress_database_password

Итак, вы указали пароль учетной записи администратора root, а также имя пользователя и пароль для БД приложения.

Сохраните и закройте файл, когда закончите редактирование.

Поскольку файл .env содержит конфиденциальную информацию, нужно обязательно включить его в файлы .gitignore и .dockerignore этого проекта (они сообщают Git и Docker, какие файлы не следует копировать в репозитории Git и образы Docker соответственно).

Читайте также: Краткий справочник по Git

Если вам нужен контроль версий Git, инициализируйте текущий рабочий каталог как репозиторий:

git init

Откройте файл .gitignore:

nano .gitignore

Добавьте в него файл .env:

.env

Сохраните и закройте файл.

Еще одна хорошая мера предосторожности – добавить .env в файл .dockerignore, чтобы он не попадал в контейнеры, когда вы используете этот каталог в качестве контекста сборки.

Откройте файл:

nano .dockerignore

Добавьте .env:

.env

Ниже можно при желании добавить файлы и каталоги, связанные с разработкой вашего приложения:

.env
.git
docker-compose.yml
.dockerignore

Сохраните и закройте файл.

После этого вы можете перейти к определению своих сервисов в файле docker-compose.yml.

3: Определение сервисов с помощью Docker Compose

Ваш файл docker-compose.yml будет содержать определения сервисов вашей установки. В Compose сервис – это работающий контейнер, а определения сервисов указывают информацию о том, как будет работать каждый контейнер.

Используя Compose, вы можете определить различные сервисы для запуска мультиконтейнерных приложений, поскольку Compose позволяет связывать эти сервисы вместе с помощью общих сетей и томов. Это полезно для нашей текущей настройки, так как мы собираемся создать отдельные контейнеры для БД, приложения WordPress и веб-сервера. Мы также создадим контейнер для запуска клиента Certbot, чтобы получить сертификаты для веб-сервера.

Для начала откройте файл docker-compose.yml:

nano docker-compose.yml

Добавьте следующий код, чтобы определить версию файла Compose и сервис базы данных db:

version: '3'
services:
db:
image: mysql:8.0
container_name: db
restart: unless-stopped
env_file: .env
environment:
- MYSQL_DATABASE=wordpress
volumes:
- dbdata:/var/lib/mysql
command: '--default-authentication-plugin=mysql_native_password'
networks:
- app-network

Определение сервиса db содержит следующие параметры:

Под сервисом db укажите определение сервиса приложения wordpress.

...
wordpress:
depends_on:
- db
image: wordpress:5.1.1-fpm-alpine
container_name: wordpress
restart: unless-stopped
env_file: .env
environment:
- WORDPRESS_DB_HOST=db:3306
- WORDPRESS_DB_USER=$MYSQL_USER
- WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD
- WORDPRESS_DB_NAME=wordpress
volumes:
- wordpress:/var/www/html
networks:
- app-network

В этом определении мы называем контейнер и определяем политику перезапуска, как делали это в сервисе db. Мы также добавляем некоторые индивидуальные параметры для этого контейнера:

Далее, под определением сервиса wordpress добавьте следующее определение для сервиса веб-сервера Nginx:

...
webserver:
depends_on:
- wordpress
image: nginx:1.15.12-alpine
container_name: webserver
restart: unless-stopped
ports:
- "80:80"
volumes:
- wordpress:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
networks:
- app-network

Опять же, здесь мы называем контейнер и делаем его зависимым от контейнера WordPress в порядке запуска. Мы также используем образ alpine – 1.15.12-alpine.

Это определение сервиса также включает следующие опции:

Снова этот контейнер добавляется в сеть app-network.

Под определением webserver  добавьте последнее определение сервиса для certbot. Обязательно замените адрес электронной почты и указанные здесь доменные имена своей собственной информацией:

certbot:
depends_on:
- webserver
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- wordpress:/var/www/html
command: certonly --webroot --webroot-path=/var/www/html --email 8host@example.com --agree-tos --no-eff-email --staging -d example.com -d www.example.com

Это определение извлекает образ certbot/certbot из Docker Hub. Оно также привлекает именованные тома для совместного использования ресурсов с контейнером Nginx (сертификаты домена и ключ в certbot-etc и код приложения в wordpress).

Опять же, мы использовали depends_on, чтобы указать, что контейнер certbot должен запускаться только после запуска сервиса webserver.

Мы также включили параметр command, он задает подкоманду, которую нужно запустить с помощью команды certbot контейнера по умолчанию. Подкоманда certonly получит сертификат со следующими параметрами:

После сервиса certbot добавьте определение сети и тома:

...
volumes:
certbot-etc:
wordpress:
dbdata:
networks:
app-network:
driver: bridge

Ключ верхнего уровня volumes определяет тома certbot-etc, wordpress и dbdata. Когда Docker создает тома, содержимое тома сохраняется в каталоге в файловой системе хоста Docker, /var/lib/docker/volumes/. Содержимое каждого тома затем монтируется из этого каталога в любой контейнер, использующий соответствующий том. Таким образом можно обмениваться кодом и данными между контейнерами.

Пользовательская мостовая сеть app-network обеспечивает связь между контейнерами, поскольку они находятся на одном хосте Docker. Это оптимизирует трафик и обмен данными внутри приложения, поскольку оно открывает все порты между контейнерами в одной и той же мостовой сети, при этом не открывая никаких портов для внешнего мира. Контейнеры db, wordpress и webserver могут взаимодействовать друг с другом, нужно только предоставить порт 80 для внешнего доступа к приложению.

Готовый файл docker-compose.yml будет выглядеть так:

version: '3'
services:
db:
image: mysql:8.0
container_name: db
restart: unless-stopped
env_file: .env
environment:
- MYSQL_DATABASE=wordpress
volumes:
- dbdata:/var/lib/mysql
command: '--default-authentication-plugin=mysql_native_password'
networks:
- app-network
wordpress:
depends_on:
- db
image: wordpress:5.1.1-fpm-alpine
container_name: wordpress
restart: unless-stopped
env_file: .env
environment:
- WORDPRESS_DB_HOST=db:3306
- WORDPRESS_DB_USER=$MYSQL_USER
- WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD
- WORDPRESS_DB_NAME=wordpress
volumes:
- wordpress:/var/www/html
networks:
- app-network
webserver:
depends_on:
- wordpress
image: nginx:1.15.12-alpine
container_name: webserver
restart: unless-stopped
ports:
- "80:80"
volumes:
- wordpress:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
networks:
- app-network
certbot:
depends_on:
- webserver
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- wordpress:/var/www/html
command: certonly --webroot --webroot-path=/var/www/html --email 8host@example.com --agree-tos --no-eff-email --staging -d example.com -d www.example.com
volumes:
certbot-etc:
wordpress:
dbdata:
networks:
app-network:
driver: bridge

Сохраните и закройте файл.

4: Получение сертификатов SSL

Мы можем запустить контейнеры с помощью команды docker-compose up, которая создаст и запустит их в указанном нами порядке. Если запросы сертификата для домена будут выполнены успешно, мы увидим соответствующий статус в выходных данных и сами сертификаты, смонтированные в /etc/letsencrypt/live контейнера webserver.

Создайте контейнеры с помощью docker-compose up и флага -d, который запустит контейнеры db, wordpress и webserver в фоновом режиме:

docker-compose up -d

Вы увидите вывод, подтверждающий, что сервисы были созданы:

Creating db ... done
Creating wordpress ... done
Creating webserver ... done
Creating certbot   ... done

Используя docker-compose ps, проверьте статус сервисов:

docker-compose ps

Если все прошло успешно, сервисы db, wordpress и webserver будут активированы, и контейнер certbot завершит работу и выведет сообщение о статусе 0:

Name                 Command               State           Ports
-------------------------------------------------------------------------
certbot     certbot certonly --webroot ...   Exit 0
db          docker-entrypoint.sh --def ...   Up       3306/tcp, 33060/tcp
webserver   nginx -g daemon off;             Up       0.0.0.0:80->80/tcp
wordpress   docker-entrypoint.sh php-fpm     Up       9000/tcp

Если в столбце State сервисов db, wordpress или webserver вы видите не Up, а другое значение, или статус выхода контейнера certbot отличается от 0, обязательно проверьте логи сервисов с помощью команды docker-compose logs:

docker-compose logs service_name

Теперь можно убедиться, что сертификаты в контейнере webserver были смонтированы, с помощью docker-compose exec:

docker-compose exec webserver ls -la /etc/letsencrypt/live

Если ваши запросы на сертификат были обработаны успешно, вы увидите подобный вывод:

total 16
drwx------    3 root     root          4096 May 10 15:45 .
drwxr-xr-x    9 root     root          4096 May 10 15:45 ..
-rw-r--r--    1 root     root           740 May 10 15:45 README
drwxr-xr-x    2 root     root          4096 May 10 15:45 example.com

Теперь, когда вы знаете, что ваш запрос на сертификаты был принят, вы можете отредактировать определение сервиса certbot и убрать флаг –staging.

Откройте docker-compose.yml:

nano docker-compose.yml

Найдите раздел с определением сервиса certbot и замените флаг –staging в опции command на флаг –force-renewal. С его помощью Certbot сможет запросить новый сертификат для тех же доменов, что и действующий сертификат. Определение certbot теперь будет выглядеть так:

...
certbot:
depends_on:
- webserver
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
- wordpress:/var/www/html
command: certonly --webroot --webroot-path=/var/www/html --email 8host@example.com --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com
...

Теперь вы можете запустить docker-compose для воссоздания контейнера certbot. Мы также включим параметр –no-deps, чтобы Compose мог пропустить запуск сервиса webserver, поскольку он уже запущен:

docker-compose up --force-recreate --no-deps certbot

Вы увидите вывод, указывающий, что ваш запрос сертификата был успешно обработан:

Recreating certbot ... done
Attaching to certbot
certbot      | Saving debug log to /var/log/letsencrypt/letsencrypt.log
certbot      | Plugins selected: Authenticator webroot, Installer None
certbot      | Renewing an existing certificate
certbot      | Performing the following challenges:
certbot      | http-01 challenge for example.com
certbot      | http-01 challenge for www.example.com
certbot      | Using the webroot path /var/www/html for all unmatched domains.
certbot      | Waiting for verification...
certbot      | Cleaning up challenges
certbot      | IMPORTANT NOTES:
certbot      |  - Congratulations! Your certificate and chain have been saved at:
certbot      |    /etc/letsencrypt/live/example.com/fullchain.pem
certbot      |    Your key file has been saved at:
certbot      |    /etc/letsencrypt/live/example.com/privkey.pem
certbot      |    Your cert will expire on 2019-08-08. To obtain a new or tweaked
certbot      |    version of this certificate in the future, simply run certbot
certbot      |    again. To non-interactively renew *all* of your certificates, run
certbot      |    "certbot renew"
certbot      |  - Your account credentials have been saved in your Certbot
certbot      |    configuration directory at /etc/letsencrypt. You should make a
certbot      |    secure backup of this folder now. This configuration directory will
certbot      |    also contain certificates and private keys obtained by Certbot so
certbot      |    making regular backups of this folder is ideal.
certbot      |  - If you like Certbot, please consider supporting our work by:
certbot      |
certbot      |    Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
certbot      |    Donating to EFF:                    https://eff.org/donate-le
certbot      |
certbot exited with code 0

Получив необходимые сертификаты, вы можете перейти к отладке конфигурации Nginx для поддержки SSL. Об этом мы поговорим в следующей части этой серии мануалов.