tech-tips/Программное обеспечение/LEMP-стек/Установка WordPress с помощью Docker Compose DigitalOcean.md

920 lines
71 KiB
Markdown
Raw Normal View History

---
source: https://www.digitalocean.com/community/tutorials/how-to-install-wordpress-with-docker-compose-ru
---
![[intro-to-cloud.d49bc5f7.jpeg]]
## Введение
[WordPress](https://wordpress.org/) — бесплатная [система управления контентом (CMS)](https://www.digitalocean.com/community/tutorials/digitalocean-community-glossary#content-management-system) с открытым исходным кодом, которая опирается на базу данных [MySQL](https://www.mysql.com/) и обрабатывает запросы с помощью [PHP](https://www.php.net/). Благодаря огромному количеству плагинов и системе шаблонов, а также тому факту, что большая часть административных функций может производиться через веб-интерфейс, #WordPress завоевала популярность среди создателей самых разных сайтов, от блогов и страниц с описанием продукта и до сайтов электронной торговли.
Для запуска WordPress, как правило, требуется установка стека [LAMP](https://www.digitalocean.com/community/tutorials/digitalocean-community-glossary#lamp) ( #Linux, #Apache, #MySQL и #PHP) или [LEMP](https://www.digitalocean.com/community/tutorials/digitalocean-community-glossary#lemp) (Linux, #Nginx, MySQL и PHP), что может занять много времени. С помощью таких инструментов, как [Docker](https://www.docker.com/) и [Docker Compose](https://docs.docker.com/compose/), вы можете упростить процесс настройки предпочитаемого стека и установки WordPress. Вместо установки отдельных компонентов вручную, вы можете использовать _образы_, которые обладают такими стандартными элементами, как библиотеки, файлы конфигурации и переменные среды, и запускать эти образы в онтейнерах_, т. е. изолированных процессах, запущенных в общей операционной системе. Кроме того, используя Compose, вы можете координировать действия нескольких контейнеров, например приложения и базы данных, которые будут коммуницировать друг с другом.
В этом обучающем руководстве вы будете выполнять установку WordPress с несколькими контейнерами. Ваши контейнеры будут включать базу данных MySQL, веб-сервер Nginx и непосредственно WordPress. Также вы должны будете обеспечить защиту установки, получая с помощью [Lets Encrypt](https://letsencrypt.org/) сертификаты TLS/SSL для доменов, которые вы хотите привязать к вашему сайту. Наконец, вы настроите задание [`cron`](https://www.digitalocean.com/community/tutorials/how-to-schedule-routine-tasks-with-cron-and-anacron-on-a-vps) для обновления ваших сертификатов, чтобы ваш домен оставался защищенным.
## Предварительные требования
Для данного обучающего руководства вам потребуется следующее:
- Сервер на базе #Ubuntu 18.04, а также пользователь без прав root с привилегиями `sudo` и активный брандмауэр. Дополнительную информацию о настройке этих параметров см. в [руководстве по первоначальной настройке сервера](https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-18-04).
- Система #Docker, установленная на сервере в соответствии с шагами 1 и 2 руководства [Установка и использование Docker в Ubuntu 18.04](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-18-04).
- #docker-compose, установленный на сервере, в соответствии с шагом 1 руководства [Установка Docker Compose в Ubuntu 18.04](https://www.digitalocean.com/community/tutorials/how-to-install-docker-compose-on-ubuntu-18-04).
- Зарегистрированное доменное имя. В этом обучающем руководстве мы будем использовать example.com. Вы можете получить бесплатный домен на [Freenom](http://www.freenom.com/en/index.html) или зарегистрировать доменное имя по вашему выбору.
- На вашем сервере должны быть настроены обе нижеследующие записи DNS. Вы можете воспользоваться [введением в работу с DigitalOcean DNS](https://www.digitalocean.com/community/tutorials/an-introduction-to-digitalocean-dns), чтобы получить подробную информацию о добавлении доменов в учетную запись DigitalOcean, если вы используете этот способ:
- Запись `A`, где `example.com` указывает на публичный IP-адрес вашего сервера.
- Запись `A`, где `www.example.com` указывает на публичный IP-адрес вашего сервера.
## Шаг 1 — Настройка конфигурации веб-сервера
Перед запуском контейнеров прежде всего необходимо настроить конфигурацию нашего веб-сервера Nginx. Наш файл конфигурации будет включать несколько специфических для Wordpress блоков расположения наряду с блоками расположения, которые будут направлять передаваемые Lets Encrypt запросы верификации клиенту Certbot для автоматизированного обновления сертификатов.
Во-первых, создайте директорию проекта для настройки WordPress с именем `wordpress` и перейдите в эту директорию:
```shell
mkdir wordpress && cd wordpress
```
Затем создайте директорию для файла конфигурации:
```shell
mkdir nginx-conf
```
Откройте файл с помощью `nano` или своего любимого редактора:
```shell
nano nginx-conf/nginx.conf
```
В этом файле мы добавим серверный блок с директивами для имени нашего сервера и корневой директории документов, а также блок расположения для направления запросов сертификатов от клиента 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;
}
}
```
Наш серверный блок содержит следующую информацию:
**Директивы:**
- `listen`: данный элемент просит Nginx прослушивать порт `80`, что позволит нам использовать плагин [webroot](https://certbot.eff.org/docs/using.html#webroot) #Certbot для наших запросов сертификатов. Обратите внимание, что мы пока е_ будем включать порт `443`, мы обновим нашу конфигурацию и добавим SSL после успешного получения наших сертификатов.
- `server_name`: этот элемент определяет имя вашего сервера и серверный блок, которые должны использоваться для запросов к вашему серверу. Обязательно замените `example.com` в этой строке на ваше собственное доменное имя.
- `index`: директива `index` определяет файлы, которые будут использоваться в качестве индексов при обработке запросов к вашему серверу. Здесь мы изменили порядок приоритета по умолчанию, поставив `index.php` перед `index.html`, в результате чего Nginx будет давать приоритет файлам с именем `index.php` при наличии возможности.
- `root`: наша директива `root` назначает имя корневой директории для запросов к нашему серверу. Эта директория, `/var/www/html`, [создается в качестве точки монтирования](https://github.com/docker-library/wordpress/blob/07958d19ed465fb7fe50626be740d88a2c2260a7/php7.2/fpm-alpine/Dockerfile#L53) в момент сборки с помощью инструкций в [Dockerfile WordPress](https://github.com/docker-library/wordpress/blob/07958d19ed465fb7fe50626be740d88a2c2260a7/php7.2/fpm-alpine/Dockerfile). Эти инструкции Dockerfile также гарантируют, что файлы релиза WordPress монтируются в этот том.
**Блоки расположения:**
- `location ~ /.well-known/acme-challenge`: этот блок расположения будет обрабатывать запросы в директории `.well-known`, где Certbot будет размещать временный файл для подтверждения того, что DNS для нашего домена будет работать с нашим сервером. Настроив данную конфигурацию, мы сможем использовать плагин webroot Certbot для получения сертификатов для нашего домена.
- `location /`: в этом блоке расположения мы будем использовать директиву `try_files` для проверки файлов, соответствующих отдельным запросам URI. Вместо того, чтобы возвращать по умолчанию статус 404 `не найдено`, мы будем передавать контроль файлу `index.php` Wordpress с аргументами запроса.
- `location ~\.php$`: этот блок расположения будет обрабатывать PHP-запросы и проксировать эти запросы в наш контейнер `wordpress`. Поскольку наш образ WordPress Docker будет опираться на образ [`php:fpm`](https://github.com/docker-library/php/blob/e63194a0006848edb13b7eff5a7f9d790d679428/7.2/alpine3.9/fpm/Dockerfile), мы также добавим параметры конфигурации, принадлежащие [протоколу FastCGI](https://en.wikipedia.org/wiki/FastCGI), в этот блок. Nginx требует наличия независимого процессора PHP для запросов PHP: в нашем случае эти запросы будут обрабатываться процессором `php-fpm`, который будет включать образ `php:fpm`. Кроме того, этот блок расположения содержит директивы FastCGI, переменные и опции, которые будут проксировать запросы для приложения WordPress, запущенного в нашем контейнере `wordpress`, задавать предпочитаемый индекс захваченного URI запроса, а также выполнять парсинг URI-запросов.
- `location ~ /\.ht`: этот блок будет обрабатывать файлы `.htaccess`, поскольку Nginx не будет обслуживать их. Директива `deny_all` гарантирует, что файлы `.htaccess` никогда не будут отображаться для пользователей.
- `location = /favicon.ico`, `location = /robots.txt`: эти блоки гарантируют, что запросы для `/favicon.ico` и `/robots.txt` не будут регистрироваться.
- `location ~*\ (css|gif|ico|jpeg|jpg|js|png)$`: этот блок отключает запись в журнал для запросов статичных активов и гарантирует, что эти активы будут иметь высокую кэшируемость, поскольку обычно их трудно обслуживать.
Дополнительную информацию о проксировании #FastCGI см. в статье [Понимание и реализация проксирования FastCGI в Nginx](https://www.digitalocean.com/community/tutorials/understanding-and-implementing-fastcgi-proxying-in-nginx). Информацию о серверных блоках и блоках расположения см. в статье [Знакомство с сервером Nginx и алгоритмы выбора блоков расположения](https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms).
Сохраните и закройте файл после завершения редактирования. Если вы используете `nano`, нажмите `CTRL`+`X`, `Y`, затем `ENTER`.
После настройки конфигурации Nginx вы можете перейти к созданию переменных среды для передачи в контейнеры приложения и базы данных во время исполнения.
## Шаг 2 — Настройка переменных среды
Контейнеры базы данных и приложения WordPress должны получить доступ к определенным переменным среды в момент выполнения для сохранения данных приложения и предоставления доступа к этим данным для вашего приложения. Эти переменные включают чувствительные и нечувствительные данные: к чувствительным данным относятся **root**-пароль MySQL и пароль и пользователь базы данных приложения, а к нечувствительным данным относится информация об имени и хосте базы данных приложения.
Вместо того, чтобы задавать эти значения в нашем файле Docker Compose, основном файле, который содержит информацию о том, как наши контейнеры будут работать, мы можем задать чувствительные значения в файле `.env` и ограничить его распространение. Это не позволит скопировать эти значения в репозиторий нашего проекта и открыть их для общего доступа.
В главной директории проекта `~/wordpress`, откройте файл с именем `.env`:
```shell
nano .env
```
Конфиденциальные значения, которые мы зададим в этом файле, включают пароль для нашего **root**-пользователя MySQL, имя пользователя и пароль, которые WordPress будет использовать для доступа к базе данных.
Добавьте в файл следующие имена и значения переменных: Обязательно предоставьте здесь **ваши собственные значения** для каждой переменной:
```env
MYSQL_ROOT_PASSWORD=your_root_password
MYSQL_USER=your_wordpress_database_user
MYSQL_PASSWORD=your_wordpress_database_password
```
Мы включили пароль для административной учетной записи **root**, а также предпочитаемые имя пользователя и пароль для нашей базы данных приложения.
Сохраните и закройте файл после завершения редактирования.
Поскольку ваш файл `.env` содержит чувствительную информацию, вы можете убедиться, что в файлы `.gitignore` и `.dockerignore` вашего проекта включены инструкции, указывающие [Git](https://www.digitalocean.com/community/tutorials/how-to-use-git-a-reference-guide) и **Docker**, какие файлы не копировать в ваши репозитории Git и образы Docker.
Если вы планируете использовать #git для контроля версий, [инициализируйте текущую рабочую директорию в качестве репозитория](https://www.digitalocean.com/community/tutorials/how-to-use-git-a-reference-guide#set-up-and-initialization) с помощью `git init`:
```shell
git init
```
Затем откройте файл `.gitignore`:
```shell
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](https://certbot.eff.org/), чтобы получить сертификаты для нашего веб-сервера.
Откройте файл `docker-compose.yml`:
```shell
nano docker-compose.yml
```
Добавьте следующий код для определения версии файла Compose и базы данных `db`:
```yaml
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` включает следующие параметры:
- `image`: данный элемент указывает Compose, какой образ будет загружаться для создания контейнера. Мы закрепим здесь [образ](https://github.com/docker-library/mysql/blob/130bd8e46a3da1adfc1732a08c70673e20aa5977/8.0/Dockerfile) [`mysql:8.0`](https://github.com/docker-library/mysql/blob/130bd8e46a3da1adfc1732a08c70673e20aa5977/8.0/Dockerfile), чтобы избежать будущих конфликтов, так как образ `mysql:latest` продолжит обновляться. Дополнительную информацию о закреплении версии и предотвращении конфликтов зависимостей см. в документации Docker в разделе [Рекомендации по работе с Dockerfile](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/).
- `container_name`: данный элемент указывает имя контейнера.
- `restart`: данный параметр определяет политику перезапуска контейнера. По умолчанию установлено значение `no`, но мы задали значение, согласно которому контейнер будет перезапускаться, пока не будет остановлен вручную.
- `env_file`: этот параметр указывает Compose, что мы хотим добавить переменные среды из файла с именем `.env`, расположенного в контексте сборки. В этом случае в качестве контекста сборки используется наша текущая директория.
- `environment`: этот параметр позволяет добавить дополнительные переменные среды, не определенные в файле `.env`. Мы настроим переменную `MYSQL_DATABASE` со значением `wordpress`, которая будет предоставлять имя нашей базы данных приложения. Поскольку эта информация не является чувствительной, мы можем включить ее напрямую в файл `docker-compose.yml`.
- `volumes`: здесь мы монтируем именованный [том](https://docs.docker.com/storage/volumes/) с названием `dbdata` в директорию `/var/lib/mysql` в контейнере. Это стандартная директория данных в большинстве дистрибутивов.
- `command`: данный параметр указывает команду, которая будет переопределять используемое по умолчанию значение [инструкции CMD](https://docs.docker.com/engine/reference/builder/#cmd) для образа. В нашем случае мы добавим параметр для стандартной [команды](https://dev.mysql.com/doc/refman/8.0/en/mysqld.html) [`mysqld`](https://dev.mysql.com/doc/refman/8.0/en/mysqld.html) образа Docker, которая запускает сервер MySQL в контейнере. Эта опция `-default-authentication-plugin=mysql_native_password` устанавливает для системной переменной `-default-authentication-plugin` значение `mysql_native_password`, которое указывает, какой механизм аутентификации должен управлять новыми запросами аутентификации для сервера. Поскольку PHP и наш образ WordPress [не будут поддерживать](https://github.com/docker-library/wordpress/issues/313) [новое значение аутентификации MySQL по умолчанию](https://mysqlserverteam.com/upgrading-to-mysql-8-0-default-authentication-plugin-considerations/), мы должны внести изменения, чтобы выполнить аутентификацию пользователя базы данных приложения.
- `networks`: данный параметр указывает, что служба приложения будет подключаться к сети `app-network`, которую мы определим внизу файла.
Затем под определением службы `db` добавьте определение для вашей службы приложения `wordpress`:
```yaml
...
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`. Также мы добавляем в этот контейнер ряд параметров:
- `depends_on`: этот параметр гарантирует, что наши контейнеры будут запускаться в порядке зависимости, и контейнер `wordpress` запускается после контейнера `db`. Наше приложение WordPress зависит от наличия базы данных приложения и пользователя, поэтому установка такого порядка зависимостей позволит выполнять запуск приложения корректно.
- `image`: для этой настройки мы будем использовать [образ Wordpress](https://github.com/docker-library/wordpress/blob/07958d19ed465fb7fe50626be740d88a2c2260a7/php7.2/fpm-alpine/Dockerfile) [`5.11-fpm-alpine`](https://github.com/docker-library/wordpress/blob/07958d19ed465fb7fe50626be740d88a2c2260a7/php7.2/fpm-alpine/Dockerfile). Как было показано в [шаге 1](https://www.digitalocean.com/community/tutorials/how-to-install-wordpress-with-docker-compose#step-1-%E2%80%94-defining-the-web-server-configuration), использование этого образа гарантирует, что наше приложение будет иметь процессор `php-fpm`, который требуется Nginx для обработки PHP. Это еще и образ `alpine`, полученный из [проекта Alpine Linux](https://alpinelinux.org/), который поможет снизить общий размер образа. Дополнительную информацию о преимуществах и недостатках использования образов `alpine`, а также о том, имеет ли это смысл в случае вашего приложения, см. в полном описании в разделе **Варианты образа** на [странице образа WordPress на Docker Hub](https://hub.docker.com/_/wordpress).
- `env_file`: и снова мы укажем, что хотим загрузить значения из файла `.env`, поскольку там мы определили пользователя базы данных приложения и пароль.
- `environment`: здесь мы будем использовать значения, определенные в файле `.env`, но мы привяжем их к именам переменных, которые требуются для образа WordPress: `WORDPRESS_DB_USER` и `WORDPRESS_DB_PASSWORD`. Также мы определяем значение `WORDPRESS_DB_HOST`, которое будет указывать сервер MySQL, который будет работать в контейнере `db`, доступный на используемом по умолчанию порту MySQL `3306`. Наше значение `WORDPRESS_DB_NAME` будет тем же, которое мы указали при определении службы MySQL для `MYSQL_DATABASE`: `wordpress`.
- `volumes`: мы монтируем том с именем `wordpress` на точку монтирования `/var/www/html`, [созданную образом WordPress](https://github.com/docker-library/wordpress/blob/07958d19ed465fb7fe50626be740d88a2c2260a7/php7.2/fpm-alpine/Dockerfile#L53). Использование тома с именем таким образом позволит разделить наш код приложения с другими контейнерами.
- `networks`: мы добавляем контейнер `wordpress` в сеть `app-network`.
Далее под определением службы приложения `wordpress` добавьте следующее определение для службы Nginx `webserver`:
```yaml
...
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` — [образ Nginx](https://github.com/nginxinc/docker-nginx/blob/e5123eea0d29c8d13df17d782f15679458ff899e/mainline/stretch/Dockerfile) [`1.15.12-alpine`](https://github.com/nginxinc/docker-nginx/blob/e5123eea0d29c8d13df17d782f15679458ff899e/mainline/stretch/Dockerfile).
Это определение службы также включает следующие параметры:
- `ports`: этот параметр открывает порт `80`, чтобы активировать параметры конфигурации, определенные нами в файле `nginx.conf` в шаге 1.
- `volumes`: здесь мы определяем комбинацию названных томов и [связанных монтируемых образов](https://docs.docker.com/storage/bind-mounts/):
- `wordpress:/var/www/html`: этот параметр будет монтировать код нашего приложения WordPress в директорию `/var/www/html`, директорию, которую мы задали в качестве `root`директории в нашем серверном блоке Nginx.
- `./nginx-conf:/etc/nginx/conf.d`: этот элемент будет монтировать директорию конфигурации Nginx на хост в соответствующую директорию в контейнере, гарантируя, что любые изменения, которые мы вносим в файлы на хосте, будут отражены в контейнере.
- `certbot-etc:/etc/letsencrypt`: этот элемент будет монтировать соответствующие сертификаты и ключи Lets Encrypt для нашего домена в соответствующую директорию контейнера.
Здесь мы снова добавили этот контейнер в сеть `app-network`.
Наконец, под определением `webserver` добавьте последнее определение для службы `certbot`. Обязательно замените адрес электронной почты и доменные имена, перечисленные здесь, на ваши собственные:
```yaml
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 sammy@example.com --agree-tos --no-eff-email --staging -d example.com -d www.example.com
```
Это определение попросит Compose извлекать [образ](https://hub.docker.com/r/certbot/certbot/) [`certbot/certbot`](https://hub.docker.com/r/certbot/certbot/) из Docker Hub. Также оно использует имена томов для обмена ресурсами с контейнером Nginx, включая доменные сертификаты и ключ в `certbot-etc` и код приложения в `wordpress`.
Мы использовали `depends_on`, чтобы указать, что контейнер `certbot` следует запускать только после запуска службы `webserver`.
Также мы включили параметр `command`, указывающий субкоманду для запуска с используемой контейнером по умолчанию командой `certbot`. [Субкоманда](https://certbot.eff.org/docs/using.html#certbot-command-line-options) [`certonly`](https://certbot.eff.org/docs/using.html#certbot-command-line-options) будет получать сертификат со следующими параметрами:
- `-webroot`: данный элемент говорит Certbot о необходимости использования плагина webroot для размещения файлов в папке webroot для аутентификации. Работа плагина основана на [методе валидации HTTP-01](https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.2), который использует запрос HTTP, чтобы доказать, что Certbot может получить доступ к ресурсам с сервера, который отвечает на заданное доменное имя.
- `-webroot-path`: данный элемент указывает путь директории webroot.
- `-email`: предпочитаемый адрес электронной почты для регистрации и восстановления.
- `-agree-tos`: данный элемент указывает, что вы принимаете [Соглашение о подписке ACME](https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf).
- `-no-eff-email`: данный элемент указывает Certbot, что вы не хотите делиться адресом электронной почты с [Electronic Frontier Foundation](https://www.eff.org/) (EFF). Вы можете пропустить этот элемент.
- `-staging`: данный элемент говорит Certbot, что вы хотите использовать промежуточную среду Lets Encrypt для получения тестовых сертификатов. При использовании этого параметра вы можете протестировать параметры конфигурации и избежать возможных пределов для запросов домена. Дополнительную информацию об этих предельных значениях см. в [документации по ограничениям скорости](https://letsencrypt.org/docs/rate-limits/) Lets Encrypt.
- `d`: данный элемент позволяет указать доменные имена, которые вы хотите использовать для вашего запроса. В нашем случае мы включили `example.com` и `www.example.com`. Обязательно замените эти данные на имя вашего домена.
Под определением службы `certbot` добавьте определения сети и тома:
```yaml
...
volumes:
certbot-etc:
wordpress:
dbdata:
networks:
app-network:
driver: bridge
```
Наш ключ верхнего уровня `volumes` определяет тома `certbot-etc`, `wordpress` и `dbdata`. Когда Docker создает тома, содержимое тома сохраняется в директории файловой системы хоста, `/var/lib/docker/volumes/`, а данным процессом управляет Docker. После этого содержимое каждого тома монтируется из этой директории в любой контейнер, использующий том. Таким образом мы можем делиться кодом и данными между контейнерами.
Создаваемая пользователем мостовая система `app-network` позволяет организовать коммуникацию между нашими контейнерами, поскольку они находятся на одном хосте демона Docker. Это позволяет организовать трафик и коммуникации внутри приложения, поскольку она открывает все порты между контейнерами в одной мостовой сети, скрывая все порты от внешнего мира. Таким образом, наши контейнеры `db`, `wordpress` и `webserver` могут взаимодействовать друг с другом, и нам нужно будет только открыть порт `80` для внешнего доступа к приложению.
Итоговый файл `docker-compose.yml` будет выглядеть примерно так:
```yaml
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 sammy@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`](https://docs.docker.com/compose/reference/up/), которая будет создавать и запускать наши контейнеры и службы в указанном нами порядке. Если наши запросы доменов будут выполнены успешно, мы увидим корректный статус выхода в нашем выводе и нужные сертификаты, установленные в папке `/etc/letsencrypt/live` на контейнере `webserver`.
Создайте контейнеры с помощью команды [`docker-compose up`](https://docs.docker.com/compose/reference/up/) и флага `-d`, которые будут запускать контейнеры `db`, `wordpress` и `webserver` в фоновом режиме:
```shell
docker-compose up -d
```
Вы увидите вывод, подтверждающий, что ваши службы были успешно созданы:
```
Creating db ... done
Creating wordpress ... done
Creating webserver ... done
Creating certbot ... done
```
Если все будет выполнено успешно, ваши службы `db`, `wordpress` и `webserver` должны иметь статус `Up`, а работа контейнера `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
```
Если вы увидите любое значение, кроме `Up` в столбце `State` для служб `db`, `wordpress` и `webserver`, или любое сообщение о статусе выхода, отличающееся от `0`, для контейнера `certbot`, проверьте журналы службы с помощью команды [`docker-compose logs`](https://docs.docker.com/compose/reference/logs/):
Теперь вы можете убедиться, что ваши сертификаты были смонтированы в контейнер `webserver` с помощью команды [`docker-compose exec`](https://docs.docker.com/compose/reference/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`:
```shell
nano docker-compose.yml
```
Найдите раздел файла с определением службы `certbot` и замените флаг `--staging` в параметрах `command` на флаг `--force-renewal`, который будет указывать Certbot, что вы хотите запросить новый сертификат с теми же доменами, что и в уже существующем сертификате. Определение службы `certbot` должно будет выглядеть следующим образом:
```yaml
...
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 sammy@example.com --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com
...
```
Теперь вы можете запустить команду `docker-compose up` для воссоздания контейнера `certbot`. Также мы будем использовать параметр `--no-deps`, чтобы сообщить Compose о том, что можно пропустить запуск службы `webserver`, поскольку она уже запущена:
```shell
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.
## Шаг 5 — Изменение конфигурации веб-сервера и определения службы
Активация SSL в нашей конфигурации Nginx будет включать организацию перенаправления HTTP на HTTPS, указание расположения сертификата и ключей SSL и добавление параметров безопасности и заголовков.
Поскольку вы будете воссоздавать службу `webserver` для включения этих нововведений, сейчас вы можете остановить ее работу:
```shell
docker-compose stop webserver
```
Прежде чем мы самостоятельно изменим файл конфигурации, нам нужно предварительно получить [рекомендуемые параметры безопасности Nginx](https://github.com/certbot/certbot/blob/master/certbot-nginx/certbot_nginx/tls_configs/options-ssl-nginx.conf) от Certbot с помощью `curl`:
```shell
curl -sSLo nginx-conf/options-ssl-nginx.conf https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf
```
Данная команда будет сохранять эти параметры в файле с именем `options-ssl-nginx.conf`, расположенном в директории `nginx-conf`.
Затем удалите ранее созданный файл конфигурации Nginx:
```shell
rm nginx-conf/nginx.conf
```
Откройте другую версию файла:
```shell
nano nginx-conf/nginx.conf
```
Добавьте следующий код в файл для перенаправления HTTP на HTTPS и добавления учетных данных, протоколов и заголовков безопасности SSL. Обязательно замените `example.com` на ваше доменное имя:
```
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
index index.php index.html index.htm;
root /var/www/html;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/nginx/conf.d/options-ssl-nginx.conf;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# enable strict transport security only if you understand the implications
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;
}
}
```
Блок сервера HTTP указывает webroot для запросов обновления Certbot в директории `.well-known/acme-challenge`. Также он содержит [директиву перезаписи](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite), которая перенаправляет запросы HTTP в корневую директорию HTTPS.
Блок сервера HTTPS активирует `ssl` и `http2`. Дополнительную информацию о том, как выполняется итерация HTTP/2 в протоколах HTTP и какие преимущества это может дать для повышения производительности веб-сайта, см. во вводной части [руководства по настройке Nginx с поддержкой HTTP/2 в Ubuntu 18.04](https://www.digitalocean.com/community/tutorials/how-to-set-up-nginx-with-http-2-support-on-ubuntu-18-04).
Этот блок также включает расположение наших сертификата SSL и ключа, а также рекомендованные параметры безопасности Certbot, которые мы сохранили в `nginx-conf/options-ssl-nginx.conf`.
Кроме того, мы включили ряд заголовков безопасности, которые позволят нам получить оценки **A** на сайтах серверных тестов [SSL Labs](https://www.ssllabs.com/ssltest/) и [Security Headers](https://securityheaders.com/). Эти заголовки включают [`X-Frame-Options`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options), [`X-Content-Type-Options`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options), [`Referrer Policy`](https://scotthelme.co.uk/a-new-security-header-referrer-policy/), [`Content-Security-Policy`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) и [`X-XSS-Protection`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection). Заголовок [HTTP](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) [`Strict Transport Security (Строгая безопасность передачи информации по протоколу HTTP)`](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) закомментирован, активируйте этот элемент, только если вы понимаете возможные последствия и оценили его [«предварительно загруженный» функционал](https://hstspreload.org/).
Наши директивы `root` и `index` также расположены в этом блоке, равно как и остальные блоки расположения WordPress, описанные в [шаге 1](https://www.digitalocean.com/community/tutorials/how-to-install-wordpress-with-docker-compose#step-1-%E2%80%94-defining-the-web-server-configuration).
После завершения редактирования сохраните и закройте файл.
Перед повторным созданием службы `webserver` вам потребуется добавить распределение порта `443` в определение службы `webserver`.
Откройте ваш файл `docker-compose.yml`:
В определении службы `webserver` добавьте следующее распределение порта:
```yaml
...
webserver:
depends_on:
- wordpress
image: nginx:1.15.12-alpine
container_name: webserver
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- wordpress:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
networks:
- app-network
```
Файл `docker-compose.yml` будет выглядеть следующим образом после завершения настройки:
```yaml
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"
- "443:443"
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 sammy@example.com --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com
volumes:
certbot-etc:
wordpress:
dbdata:
networks:
app-network:
driver: bridge
```
Сохраните и закройте файл после завершения редактирования.
Повторно создайте службу `webserver`:
```shell
docker-compose up -d --force-recreate --no-deps webserver
```
Проверьте ваши службы с помощью команды `docker-compose ps`:
Вы должны получить результат, указывающий, что ваши службы `db`, `wordpress` и `webserver` запущены:
```
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:443->443/tcp, 0.0.0.0:80->80/tcp
wordpress docker-entrypoint.sh php-fpm Up 9000/tcp
```
После запуска ваших контейнеров вы можете завершить процесс установки WordPress через веб-интерфейс.
## Шаг 6 — Завершение установки через веб-интерфейс
После запуска контейнеров мы можем завершить установку через веб-интерфейс WordPress.
В браузере перейдите на домен вашего сервера. Не забудьте заменить здесь `example.com` на ваше доменное имя:
```
https://example.com
```
Выберите язык, который вы хотите использовать:
![[wp_language_select.png]]
После нажатия **Continue** (Продолжить) вы перейдете на главную страницу настройки, где вам нужно будет выбрать имя вашего сайта и пользователя. Рекомендуется выбрать запоминающееся имя пользователя (не просто «admin») и надежный пароль. Вы можете использовать пароль, который генерирует WordPress автоматически, или задать собственный пароль.
Наконец, вам нужно будет ввести ваш адрес электронной почты и указать, хотите ли вы, чтобы движки поисковых систем могли индексировать ваш сайт:
![[wp_main_setup.png]]
После нажатия **Install WordPress** (Установить Wordpress) внизу страницы на экране появится запрос выполнения входа:
![[wp_login.png]]
После входа вы получите доступ к панели управления WordPress:
![[wp_main_dash.png]]
После завершения установки WordPress вы можете выполнить определенные действия, необходимые для гарантии того, что ваши сертификаты SSL будут обновляться автоматически.
## Шаг 7 — Обновление сертификатов
Сертификаты Lets Encrypt действительны в течение 90 дней, поэтому вам нужно будет настроить автоматический процесс обновления, чтобы гарантировать, что сертификаты не окажутся просроченными. Один из способов — создание задания с помощью утилиты планирования `cron`. В нашем случае мы настроим задание для `cron` с помощью скрипта, который будет обновлять наши сертификаты и перезагружать конфигурацию Nginx.
Откройте скрипт под названием `ssl_renew.sh`:
Добавьте следующий код в скрипт, чтобы обновить ваши сертификаты и перезагрузить конфигурацию веб-сервера. Не забудьте заменить приведенное в качестве примера имя пользователя своим именем пользователя без прав root:
```shell
#!/bin/bash
COMPOSE="/usr/local/bin/docker-compose --no-ansi"
DOCKER="/usr/bin/docker"
cd /home/sammy/wordpress/
$COMPOSE run certbot renew --dry-run && $COMPOSE kill -s SIGHUP webserver
$DOCKER system prune -af
```
Данный скрипт привязывает двоичный код `docker-compose` для переменной `COMPOSE` и задает параметр `--no-ansi`, который запускает команды `docker-compose` без [управляющих символов ANSI](https://vt100.net/docs/vt510-rm/chapter4.html). Затем он делает то же самое с двоичным файлом `docker`. В заключение он меняет директорию проекта на `~/wordpress` и запускает следующие команды `docker-compose`:
- `docker-compose run`: данный параметр запускает контейнер `certbot` и переопределяет параметр `command`, указанный в определении службы `certbot`. Вместо использования субкоманды `certonly` мы используем здесь субкоманду `renew`, которая будет обновлять сертификаты, срок действия которых близок к окончанию. Мы включили параметр `-dry-run`, чтобы протестировать наш скрипт.
- [`docker-compose kill`](https://docs.docker.com/compose/reference/kill/): данный параметр отправляет сигнал [`SIGHUP`](https://en.wikipedia.org/wiki/SIGHUP) контейнеру `webserver` для перезагрузки конфигурации Nginx. Дополнительную информацию об использовании этого процесса для перезагрузки конфигурации Nginx см. в этой [публикации блога Docker, посвященной развертыванию официального образа Nginx с помощью Docker](https://blog.docker.com/2015/04/tips-for-deploying-nginx-official-image-with-docker/).
После этого он выполняет команду [`docker system prune`](https://docs.docker.com/engine/reference/commandline/system_prune/) для удаления всех неиспользуемых контейнеров и образов.
Закройте файл после завершения редактирования. Сделайте его исполняемым:
```shell
chmod +x ssl_renew.sh
```
Далее откройте **root**-файл `crontab` для запуска скрипта обновления с заданным интервалом:
Если вы в первый раз редактируете этот файл, вам будет предложено выбрать редактор:
```
no crontab for root - using an empty one
Select an editor. To change later, run 'select-editor'.
1. /bin/nano <---- easiest
2. /usr/bin/vim.basic
3. /usr/bin/vim.tiny
4. /bin/ed
Choose 1-4 [1]:
...
```
Добавьте внизу файла следующую строку:
```cron
...
*/5 * * * * /home/sammy/wordpress/ssl_renew.sh >> /var/log/cron.log 2>&1
```
В результате будет установлен интервал в 5 минут для выполнения работы, и вы можете проверить, работает ли запрос обновления так, как предполагается. Также мы создали файл журнала, `cron.log`, чтобы записывать соответствующий вывод выполнения задания.
Через 5 минут проверьте `cron.log`, чтобы убедиться, что запрос обновления выполнен успешно:
```shell
tail -f /var/log/cron.log
```
Вы должны увидеть вывод, подтверждающий успешное обновление:
```
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates below have not been saved.)
Congratulations, all renewals succeeded. The following certs have been renewed:
/etc/letsencrypt/live/example.com/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
```
Теперь вы можете изменить файл `crontab` для настройки ежедневного интервала. Чтобы запускать скрипт каждый день в полдень, например, вы должны изменить последнюю строку файла, которая должна выглядеть следующим образом:
```cron
...
0 12 * * * /home/sammy/wordpress/ssl_renew.sh >> /var/log/cron.log 2>&1
```
Также вы можете изменить параметр `--dry-run` из скрипта `ssl_renew.sh`:
```shell
#!/bin/bash
COMPOSE="/usr/local/bin/docker-compose --no-ansi"
DOCKER="/usr/bin/docker"
cd /home/sammy/wordpress/
$COMPOSE run certbot renew && $COMPOSE kill -s SIGHUP webserver
$DOCKER system prune -af
```
Ваше задание `cron` гарантирует, что ваши сертификаты Lets Encrypt не окажутся устаревшими, обновляя их в случае истечения срока действия. Также вы можете [настроить замену журнала с помощью утилиты Logrotate](https://www.digitalocean.com/community/tutorials/how-to-manage-logfiles-with-logrotate-on-ubuntu-16-04), которая будет выполнять ротацию и сжатие файлов журнала.
## Заключение
В этом руководстве вы использовали Docker Compose для создания установки WordPress с веб-сервером Nginx. В рамках этого рабочего процесса вы получили сертификаты TLS/SSL для домена, который вы хотите подключить к вашему сайту WordPress. Кроме того, вы создали задание `cron` для обновления этих сертификатов при необходимости.
В качестве дополнительных мер по повышению производительности сайта и создания запаса мощности, вы можете ознакомиться со следующими статьями, посвященными передаче и поддержке активов WordPress:
- [Ускорение предоставления актива WordPress с помощью DigitalOcean Spaces CDN](https://www.digitalocean.com/community/tutorials/how-to-speed-up-wordpress-asset-delivery-using-digitalocean-spaces-cdn).
Если вы заинтересованы в изучении контейнеризированного рабочего процесса с помощью Kubernetes, вы также можете ознакомиться со следующими материалами:
- [Настройка WordPress с MySQL с использованием Kubernetes и Helm](https://www.digitalocean.com/community/tutorials/how-to-set-up-wordpress-with-mysql-on-kubernetes-using-helm).