Автор выбрал фонд Организации Объединенных Наций для получения пожертвования в рамках программы Write for DOnations.
Оригинальная версия WordPress этого обучающего руководства была написана Кэйтлин Джуэлл (Kathleen Juell).
Drupal — это система управления контентом (CMS), написанная на PHP и распространяемая по универсальной общественной лицензии GNU с открытым исходным кодом. Люди и организации по всему миру используют Drupal для управления правительственными сайтами, ведения личных блогов, бизнеса и не только. Уникальные отличия Drupal от других структур CMS: растущее сообщество и набор функций, которые включают безопасные процессы, надежную работу и адаптивность.
Для Drupal необходимо установить стек LAMP (Linux, Apache, MySQL и PHP) или LEMP (Linux, Nginx, MySQL и PHP), но установка компонентов по отдельности занимает много времени. Для упрощения процесса установки Drupal мы можем использовать такие инструменты, как Docker и Docker Compose. В этом обучающем руководстве будут использованы образы Docker для установки отдельных компонентов в Docker-контейнерах. С помощью Docker Compose мы можем определять и управлять несколькими контейнерами для базы данных, приложения, а также взаимодействием/коммуникацией между ними.
В этом обучающем руководстве мы установим Drupal с помощью Docker Compose для возможности контейнеризации и развертывания нашего веб-сайта Drupal на серверах. Мы запустим контейнеры для базы данных MySQL, веб-сервера Nginx и системы Drupal. Также мы защитим нашу установку, получив сертификаты TLS/SSL с Let’s Encrypt для домена, который мы хотим ассоциировать с нашим сайтом. Наконец, мы настроим задание cron для обновления ваших сертификатов, чтобы домен оставался защищенным.
Для данного обучающего руководства нам потребуется следующее:
sudo
и активный брандмауэр. Дополнительную информацию о настройке этих параметров см. в руководстве по первоначальной настройке сервера.your_domain
. Вы можете получить бесплатный домен на Freenom или зарегистрировать доменное имя по вашему выбору.your_domain
указывает на публичный IP-адрес вашего сервера.www.your_domain
указывает на публичный IP-адрес вашего сервера.Перед запуском контейнеров нам нужно определить конфигурацию для нашего веб-сервера Nginx. Наш файл конфигурации будет включать несколько специфических для Drupal блоков расположения наряду с блоками расположения, которые будут направлять передаваемые запросы верификации Let’s Encrypt клиенту Certbot для автоматизированного обновления сертификатов.
Вначале создадим директорию проекта для нашей настройки Drupal с именем drupal
:
- mkdir drupal
Перейдите в недавно созданную директорию:
- cd drupal
Теперь мы можем создать директорию для нашего файла конфигурации:
- mkdir nginx-conf
Откройте файл с помощью nano или своего любимого редактора:
- nano nginx-conf/nginx.conf
В этом файле мы добавим серверный блок с директивами для имени нашего сервера и корневой директории документов, а также блок расположения для направления запросов сертификатов от клиента Certbot, обработки PHP и запросов статичных активов.
Добавьте в этот файл следующий код. Обязательно замените your_domain
на ваше доменное имя:
server {
listen 80;
listen [::]:80;
server_name your_domain www.your_domain;
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;
}
rewrite ^/core/authorize.php/core/authorize.php(.*)$ /core/authorize.php$1;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass drupal: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 Certbot для наших запросов сертификатов. Обратите внимание, что мы пока не будем включать порт 443
, мы обновим нашу конфигурацию и добавим SSL после успешного получения наших сертификатов.
server_name
: этот элемент определяет имя нашего сервера и серверный блок, которые должны использоваться для запросов к нашему серверу. Обязательно замените your_domain
в этой строке на ваше собственное доменное имя.
index
: директива index определяет файлы, которые будут использоваться в качестве индексов при обработке запросов к нашему серверу. Здесь мы изменили порядок приоритета по умолчанию, поставив index.php
перед index.html
, в результате чего Nginx будет давать приоритет файлам с именем index.php
при наличии возможности.
root
: наша директива root назначает имя корневой директории для запросов к нашему серверу. Эта директория, /var/www/html
, создается в качестве точки монтирования в момент сборки с помощью инструкций в файле Dockerfile Drupal. Эти инструкции Dockerfile также гарантируют, что файлы релиза Drupal монтируются в этот том.
rewrite
: если указанное регулярное выражение (^/core/authorize.php/core/authorize.php(.*)$
) соответствует запросу URI, URI меняется согласно указаниям в строке замены (/core/authorize.php$1
).
Блоки расположения:
location ~ /.well-known/acme-challenge
: этот блок расположения будет обрабатывать запросы в директории .well-known
, где Certbot будет размещать временный файл для подтверждения того, что DNS для нашего домена будет работать с нашим сервером. Настроив данную конфигурацию, мы сможем использовать плагин webroot Certbot для получения сертификатов для нашего домена.
location /
: в этом блоке расположения мы будем использовать директиву try_files
для проверки файлов, соответствующих отдельным запросам URI. Вместо того чтобы возвращать по умолчанию статус 404 Not Found
, мы будем передавать контроль файлу index.php
Drupal с аргументами запроса.
location ~\.php$
: этот блок расположения будет обрабатывать PHP-запросы и проксировать эти запросы в наш контейнер drupal. Поскольку наш образ Drupal Docker будет опираться на образ php:fpm
, мы также добавим параметры конфигурации, принадлежащие протоколу FastCGI, в этот блок. Nginx требует наличия независимого процессора PHP для запросов PHP: в нашем случае эти запросы будут обрабатываться процессором php-fpm
, который будет включать образ php:fpm
. Кроме того, этот блок расположения содержит директивы FastCGI, переменные и параметры, которые будут проксировать запросы для приложения Drupal, запущенного в нашем контейнере Drupal, задавать предпочитаемый индекс захваченного 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. Информацию о серверных блоках и блоках расположения см. в статье Знакомство с сервером Nginx и алгоритмы выбора блоков расположения.
Сохраните и закройте файл после завершения редактирования.
После настройки конфигурации Nginx вы можете перейти к созданию переменных среды для передачи в контейнеры приложения и базы данных во время исполнения.
Для сохранения информации, связанной с сайтом, нашему приложению Drupal требуется база данных (MySQL, PostgresSQL и др.). Контейнеру Drupal потребуется доступ к определенным переменным среды во время исполнения, чтобы получить доступ к контейнеру базы данных (MySQL). Эти переменные содержат конфиденциальную информацию, например учетные данные базы данных, поэтому мы не можем раскрыть ее непосредственно в файле Docker Compose — главном файле, содержащем информацию о том, как будут работать наши контейнеры.
Рекомендуется всегда помещать конфиденциальные значения в файл .env
и ограничить их использование до внутреннего. Это не позволит скопировать эти значения в репозиторий нашего проекта и открыть их для общего доступа.
В главной директории проекта ~/drupal
, создайте и откройте файл .env
:
- nano .env
Добавьте в файл .env
следующие переменные, заменив выделенные части на учетные данные, которые вы хотите использовать:
MYSQL_ROOT_PASSWORD=root_password
MYSQL_DATABASE=drupal
MYSQL_USER=drupal_database_user
MYSQL_PASSWORD=drupal_database_password
Теперь мы добавили пароль для административной учетной записи root MySQL, а также предпочитаемые имя пользователя и пароль для нашей базы данных приложения.
Наш файл .env
содержит конфиденциальную информацию, поэтому его всегда рекомендуется включать в файлы проекта .gitignore
и .dockerignore
, чтобы ее нельзя было добавить в наши репозитории Git и образы Docker.
Если вы планируете использовать Git для контроля версий, инициализируйте текущую рабочую директорию в качестве репозитория с помощью git init
:
- git init
Откройте файл .gitignore
:
- nano .gitignore
Добавьте следующее:
.env
Сохраните и закройте файл.
Подобным образом откройте файл .dockerignore
:
- nano .dockerignore
Затем добавьте следующее:
.env
.git
Сохраните и закройте файл.
Теперь, когда мы приняли меры для защиты наших учетных данных как переменных среды, перейдем к следующему шагу определения наших служб в файле docker-compose.yml
.
Docker Compose — это инструмент для определения и запуска многоконтейнерных приложений. Мы определяем файл YAML
для настройки служб нашего приложения. Служба Docker Compose — это запущенный контейнер, и Compose позволяет нам связывать эти службы с общими томами и сетями.
Мы создадим разные контейнеры для нашего приложения, базы данных и веб-сервера Drupal. Также мы создадим контейнер для запуска Certbot, чтобы получить сертификаты для нашего веб-сервера.
Создайте файл docker-compose.yml
:
- nano docker-compose.yml
Добавьте следующий код для определения версии файла Compose и службы базы данных mysql
:
version: "3"
services:
mysql:
image: mysql:8.0
container_name: mysql
command: --default-authentication-plugin=mysql_native_password
restart: unless-stopped
env_file: .env
volumes:
- db-data:/var/lib/mysql
networks:
- internal
Давайте пройдемся по ним отдельно со всеми параметрами настройки службы mysql
:
image
: указывает образ, который будет использоваться/извлекаться для создания контейнера. Чтобы избежать конфликтов в будущем, рекомендуется всегда использовать образ с соответствующей версией тега, кроме тега latest
. Подробнее об оптимальных методах использования Dockerfile узнайте в документации Docker.
container_name
: определяет имя контейнера.
command
: используется для отмены команды по умолчанию (инструкции CMD) в образе. MySQL поддерживает разные плагины аутентификации, но mysql_native_password
— это традиционный способ аутентификации. Поскольку PHP и, следовательно, Drupal не будут поддерживать более новую аутентификацию MySQL, необходимо установить --default-authentication-plugin=mysql_native_password
в качестве механизма аутентификации по умолчанию.
restart
: используется для определения политики контейнера. Политика unless-stopped
повторно запускает контейнер, пока он не будет остановлен вручную.
env_file
: добавляет переменные среды из файла. В нашем случае он будет считывать переменные среды из файла .env
, определенные в предыдущем шаге.
volumes
: монтирует пути к хосту или томам с именем, указанным как подпараметры службы. Мы монтируем том с именем db-data
в директорию /var/lib/mysql
в контейнере, куда MySQL по умолчанию будет записывать свои файлы данных.
networks
: определяет сеть internal
, к которой подключится наша служба приложения. Мы определим сети в конце файла.
Мы дали определение нашей службы mysql
, а теперь добавим определение службы приложения drupal
в конец файла:
...
drupal:
image: drupal:8.7.8-fpm-alpine
container_name: drupal
depends_on:
- mysql
restart: unless-stopped
networks:
- internal
- external
volumes:
- drupal-data:/var/www/html
В этом определении службы мы называем наш контейнер и определяем политику перезапуска, как уже делали это для службы mysql
. Также мы добавляем в этот контейнер ряд параметров:
image
: здесь мы используем образ Drupal 8.7.8-fpm-alpine
. Этот образ содержит процессор php-fpm
, для которого наш веб-сервер Nginx должен выполнять обработку PHP. Кроме того, мы используем образ alpine
, полученный из проекта Alpine Linux, который уменьшит размер всего образа и рекомендуется в оптимальных методах использования Dockerfile. Drupal имеет несколько версий и образов, ознакомьтесь с ними в Dockerhub.
depends_on
: используется для выражения зависимости между службами. Определение службы mysql
как зависимости к нашему контейнеру drupal
обеспечит создание контейнера drupal
после контейнера mysql
и поможет успешно запустить наше приложение.
networks
: здесь мы добавили этот контейнер в сеть external
вместе с сетью internal
. Таким образом доступ к службе mysql
будет возможен только из контейнера drupal
по сети internal
, но при этом доступ других контейнеров по сети external
к этому контейнеру будет сохранен.
volumes
: мы монтируем том с именем drupal-data
на точку монтирования /var/www/html
, созданную образом Drupal. Использование тома с именем таким образом позволит разделить наш код приложения с другими контейнерами.
Далее добавим определение службы Nginx после определения службы drupal
:
...
webserver:
image: nginx:1.17.4-alpine
container_name: webserver
depends_on:
- drupal
restart: unless-stopped
ports:
- 80:80
volumes:
- drupal-data:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
networks:
- external
Мы снова присвоим имя нашему контейнеру и сделаем его зависимым от контейнера Drupal в отношении порядка запуска. Также мы используем образ alpine — образ Nginx 1.17.4-alpine
.
Это определение службы также включает следующие параметры:
ports
: этот параметр открывает порт 80
, чтобы активировать параметры конфигурации, определенные нами в файле nginx.conf
в шаге 1.
volumes
: здесь мы определяем том с именем и путь хоста:
drupal-data:/var/www/html
: этот параметр будет монтировать код нашего приложения Drupal в директорию /var/www/html
, директорию, которую мы задали в качестве корневой директории в нашем серверном блоке Nginx.
./nginx-conf:/etc/nginx/conf.d
: этот элемент будет монтировать директорию конфигурации Nginx на хост в соответствующую директорию в контейнере, гарантируя, что любые изменения, которые мы вносим в файлы на хосте, будут отражены в контейнере.
certbot-etc:/etc/letsencrypt
: этот элемент будет монтировать соответствующие сертификаты и ключи Let’s Encrypt для нашего домена в соответствующую директорию контейнера.
networks
: мы определили сеть external
только для того, чтобы этот контейнер мог обмениваться данными с контейнером drupal
, а не с контейнером mysql
.
Наконец, мы добавим наше последнее определение для службы certbot
. Обязательно замените sammy@your_domain
и your_domain
на свой адрес эл. почты и доменное имя:
...
certbot:
depends_on:
- webserver
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- drupal-data:/var/www/html
command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --staging -d your_domain -d www.your_domain
Это определение попросит Compose извлекать образ certbot/certbot
из Docker Hub. Также оно использует тома с именем для обмена ресурсами с контейнером Nginx, включая доменные сертификаты и ключ в certbot-etc
и код приложения в drupal-data
.
Мы также использовали depends_on
, чтобы убедиться, что контейнер certbot
будет запущен после запуска службы webserver
.
Мы не указали здесь networks
, поскольку этот контейнер не будет обмениваться данными с какими-либо службами по сети. Это просто добавление доменных сертификатов и ключа, которые мы монтировали с помощью томов с именем.
Также мы включили параметр command
, указывающий субкоманду для запуска с используемой контейнером по умолчанию командой certbot
. Клиент Certbot поддерживает плагины для получения и установки сертификатов. Мы используем плагин webroot
для получения сертификата путем включения certonly
и --webroot
в командную строку. Подробнее о плагине и дополнительных командах читайте в официальной документации Certbot.
Под определением службы certbot
добавьте определения сети и тома:
...
networks:
external:
driver: bridge
internal:
driver: bridge
volumes:
drupal-data:
db-data:
certbot-etc:
Ключ верхнего уровня networks
позволяет нам указывать, какие сети необходимо создать. networks
обеспечивает коммуникацию между службами/контейнерами во всех портах, так как они находятся на одном и том же хосте демона Docker. Мы определили две сети, internal
и external
, для защиты коммуникации между службами webserver
, drupal
и mysql
.
Ключ volumes
используется для определения томов с именем drupal-data
, db-data
и certbot-etc
. Когда Docker создает тома, содержимое тома сохраняется в директории файловой системы хоста, /var/lib/docker/volumes/
, а данным процессом управляет Docker. После этого содержимое каждого тома монтируется из этой директории в любой контейнер, использующий том. Таким образом мы можем делиться кодом и данными между контейнерами.
Итоговый файл docker-compose.yml
будет выглядеть примерно так:
version: "3"
services:
mysql:
image: mysql:8.0
container_name: mysql
command: --default-authentication-plugin=mysql_native_password
restart: unless-stopped
env_file: .env
volumes:
- db-data:/var/lib/mysql
networks:
- internal
drupal:
image: drupal:8.7.8-fpm-alpine
container_name: drupal
depends_on:
- mysql
restart: unless-stopped
networks:
- internal
- external
volumes:
- drupal-data:/var/www/html
webserver:
image: nginx:1.17.4-alpine
container_name: webserver
depends_on:
- drupal
restart: unless-stopped
ports:
- 80:80
volumes:
- drupal-data:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
networks:
- external
certbot:
depends_on:
- webserver
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- drupal-data:/var/www/html
command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --staging -d your_domain -d www.your_domain
networks:
external:
driver: bridge
internal:
driver: bridge
volumes:
drupal-data:
db-data:
certbot-etc:
Мы завершили определение наших служб. Далее запустим контейнер и протестируем наши запросы сертификата.
Мы можем запустить наши контейнеры с помощью команды docker-compose up
, которая будет создавать и запускать наши контейнеры и службы в указанном нами порядке. Если наши запросы доменов будут выполнены успешно, мы увидим корректный статус выхода в нашем выводе и нужные сертификаты, установленные в папке /etc/letsencrypt/live
на контейнере веб-сервера.
Чтобы запустить контейнеры в фоновом режиме, используйте команду docker-compose up
с флагом -d
:
- docker-compose up -d
Вы увидите аналогичный вывод, подтверждающий, что ваши службы были успешно созданы:
Output...
Creating mysql ... done
Creating drupal ... done
Creating webserver ... done
Creating certbot ... done
Проверьте статус служб с помощью команды docker-compose ps
:
- docker-compose ps
Мы увидим службы mysql
, drupal
и webserver
с State
в значении Up
, а выход из certbot
будет выполнен с сообщением о статусе 0
:
Output Name Command State Ports
--------------------------------------------------------------------------
certbot certbot certonly --webroot ... Exit 0
drupal docker-php-entrypoint php-fpm Up 9000/tcp
mysql docker-entrypoint.sh --def ... Up 3306/tcp, 33060/tcp
webserver nginx -g daemon off; Up 0.0.0.0:80->80/tcp
Если вы увидите любое значение, кроме Up
в столбце State
для служб mysql
, drupal
или webserver
, или любое сообщение о статусе выхода, отличающееся от 0
, для контейнера certbot
, проверьте журналы службы с помощью команды docker-compose logs
:
- docker-compose logs service_name
Теперь мы можем проверить, что наши сертификаты установлены на контейнере webserver
, с помощью команды docker-compose exec
:
- docker-compose exec webserver ls -la /etc/letsencrypt/live
Результат будет выглядеть следующим образом:
Outputtotal 16
drwx------ 3 root root 4096 Oct 5 09:15 .
drwxr-xr-x 9 root root 4096 Oct 5 09:15 ..
-rw-r--r-- 1 root root 740 Oct 5 09:15 README
drwxr-xr-x 2 root root 4096 Oct 5 09:15 your_domain
Теперь, когда все работает успешно, мы можем изменить определение службы certbot
, чтобы удалить флаг --staging
.
Откройте файл docker-compose.yml
, найдите определение службы certbot
и замените флаг --staging
в параметрах команды на флаг --force-renewal
, который будет указывать Certbot, что вы хотите запросить новый сертификат с теми же доменами, что и в уже существующем сертификате. Обновленное определение certbot
будет выглядеть примерно следующим образом:
...
certbot:
depends_on:
- webserver
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- drupal-data:/var/www/html
command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --force-renewal -d your_domain -d www.your_domain
...
Нам необходимо снова запустить docker-compose up
для воссоздания контейнера certbot
. Также мы будем использовать параметр --no-deps
, чтобы сообщить Compose о том, что можно пропустить запуск службы webserver
, поскольку она уже запущена:
- docker-compose up --force-recreate --no-deps certbot
Мы увидим вывод, указывающий, что запрос сертификата выполнен успешно:
OutputRecreating 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 your_domain
certbot | http-01 challenge for www.your_domain
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/your_domain/fullchain.pem
certbot | Your key file has been saved at:
certbot | /etc/letsencrypt/live/your_domain/privkey.pem
certbot | Your cert will expire on 2020-01-03. 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.
После установки сертификатов SSL в Nginx нам нужно будет перенаправить все запросы HTTP в HTTPS. Также необходимо указать наш сертификат SSL и места расположения ключей, а также добавить параметры безопасности и заголовки.
Поскольку вы будете воссоздавать службу webserver
для включения этих нововведений, сейчас вы можете остановить ее работу:
- docker-compose stop webserver
Результат будет выглядеть следующим образом:
OutputStopping webserver ... done
Затем удалим ранее созданный файл конфигурации Nginx:
- rm nginx-conf/nginx.conf
Откройте другую версию файла:
- nano nginx-conf/nginx.conf
Добавьте следующий код в файл для перенаправления HTTP на HTTPS и добавления учетных данных, протоколов и заголовков безопасности SSL. Не забудьте заменить your_domain
на свой собственный домен:
server {
listen 80;
listen [::]:80;
server_name your_domain www.your_domain;
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name your_domain www.your_domain;
index index.php index.html index.htm;
root /var/www/html;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem;
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;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
rewrite ^/core/authorize.php/core/authorize.php(.*)$ /core/authorize.php$1;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass drupal: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 в корневую директорию HTTPS.
Блок сервера HTTPS активирует ssl
и http2
. Дополнительную информацию о том, как выполняется итерация HTTP/2 в протоколах HTTP и какие преимущества это может дать для повышения производительности веб-сайта, см. во вводной части руководства по настройке Nginx с поддержкой HTTP/2 в Ubuntu 18.04.
Эти блоки активируют SSL, поскольку мы включили наш сертификат SSL и места расположения ключей, а также рекомендуемые заголовки. Эти заголовки позволят нам получить рейтинг А на SSL Labs и сайтах тестирования сервера Security Headers.
Наши директивы root
и index
также расположены в этом блоке, равно как и остальные блоки расположения Drupal, описанные в шаге 1.
Сохраните и закройте обновленный файл конфигурации Nginx.
Прежде чем воссоздать контейнер webserver
, необходимо добавить сопоставление порта 443
в наше определение службы webserver
, поскольку мы активировали сертификаты SSL.
Откройте файл docker-compose.yml
:
- nano docker-compose.yml
Сделайте следующие изменения в определении службы webserver
:
...
webserver:
image: nginx:1.17.4-alpine
container_name: webserver
depends_on:
- drupal
restart: unless-stopped
ports:
- 80:80
- 443:443
volumes:
- drupal-data:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
networks:
- external
...
После активации сертификатов SSL наш файл docker-compose.yml
будет выглядеть следующим образом:
version: "3"
services:
mysql:
image: mysql:8.0
container_name: mysql
command: --default-authentication-plugin=mysql_native_password
restart: unless-stopped
env_file: .env
volumes:
- db-data:/var/lib/mysql
networks:
- internal
drupal:
image: drupal:8.7.8-fpm-alpine
container_name: drupal
depends_on:
- mysql
restart: unless-stopped
networks:
- internal
- external
volumes:
- drupal-data:/var/www/html
webserver:
image: nginx:1.17.4-alpine
container_name: webserver
depends_on:
- drupal
restart: unless-stopped
ports:
- 80:80
- 443:443
volumes:
- drupal-data:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
networks:
- external
certbot:
depends_on:
- webserver
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- drupal-data:/var/www/html
command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --force-renewal -d your_domain -d www.your_domain
networks:
external:
driver: bridge
internal:
driver: bridge
volumes:
drupal-data:
db-data:
certbot-etc:
Сохраните и закройте файл. Давайте воссоздадим службу webserver
с нашей обновленной конфигурацией:
- docker-compose up -d --force-recreate --no-deps webserver
Результат будет выглядеть следующим образом:
OutputRecreating webserver ... done
Проверьте службы с помощью команды docker-compose ps
:
- docker-compose ps
Мы увидим службы mysql
, drupal
и webserver
со значением Up
, а выход из certbot
будет выполнен с сообщением о статусе 0
:
Output Name Command State Ports
--------------------------------------------------------------------------
certbot certbot certonly --webroot ... Exit 0
drupal docker-php-entrypoint php-fpm Up 9000/tcp
mysql 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
Теперь все наши службы запущены, и мы можем продолжить установку Drupal через веб-интерфейс.
Давайте выполним установку через веб-интерфейс Drupal.
В браузере перейдите к домену сервера. Не забудьте заменить здесь your_domain
на ваше доменное имя:
https://your_domain
Выберите язык:
Нажмите Сохранить и продолжить. Мы перейдем на страницу Профиль установки. Drupal имеет несколько профилей, поэтому выберите стандартный профиль и нажмите Сохранить и продолжить.
После выбора профиля мы перейдем к странице Конфигурация базы данных. Выберите тип базы данных MySQL, MySQL, MariaDB, Percona Server или аналогичная и введите значения для Имя базы данных, имя пользователя и пароль из значений, соответствующих MYSQL_DATABASE
, MYSQL_USER
и MYSQL_PASSWORD
, определенных соответственно в файле .env
в шаге 2. Нажмите Расширенные параметры и установите значение Хост, соответствующее контейнеру службы mysql
. Нажмите Сохранить и продолжить.
После настройки базы данных начнется установка модулей и тем Drupal по умолчанию:
После установки сайта мы перейдем к странице настройки сайта Drupal для настройки имени сайта, электронной почты, имени пользователя, пароля и региональных параметров. Заполните информацию и нажмите Сохранить и продолжить:
После нажатия Сохранить и продолжить мы увидим страницу Добро пожаловать в Drupal, которая показывает, что наш сайт Drupal готов и работает успешно.
Теперь после завершения установки Drupal необходимо убедиться, что наши сертификаты SSL будут обновляться автоматически.
Сертификаты Let’s Encrypt действительны в течение 90 дней, поэтому нам нужно будет настроить процесс автоматического обновления, чтобы гарантировать, что сертификаты не окажутся просроченными. Один из способов — создание задания с помощью утилиты планирования cron
. В нашем случае мы настроим задание для cron
с помощью скрипта, который будет обновлять наши сертификаты и перезагружать конфигурацию Nginx.
Давайте создадим файл ssl_renew.sh
для обновления наших сертификатов:
- nano ssl_renew.sh
Добавьте следующий код. Не забудьте заменить имя директории на своего собственного пользователя без прав root:
#!/bin/bash
cd /home/sammy/drupal/
/usr/local/bin/docker-compose -f docker-compose.yml run certbot renew --dry-run && \
/usr/local/bin/docker-compose -f docker-compose.yml kill -s SIGHUP webserver
Этот скрипт меняет директорию проекта ~/drupal
и запускает следующие команды docker-compose
.
docker-compose run
: данный параметр запускает контейнер certbot
и переопределяет параметр command
, указанный в определении службы certbot
. Вместо использования субкоманды certonly
мы используем здесь субкоманду renew
, которая будет обновлять сертификаты, срок действия которых близок к окончанию. Мы включили параметр --dry-run
, чтобы протестировать наш скрипт.
docker-compose kill
: данный параметр отправляет сигнал SIGHUP
контейнеру webserver
для перезагрузки конфигурации Nginx.
Закройте файл и настройте его исполняемость, запустив следующую команду:
- sudo chmod +x ssl_renew.sh
Далее откройте root
-файл crontab для запуска скрипта обновления с заданным интервалом:
- sudo crontab -e
Если вы впервые редактируете файл, вас попросят выбрать текстовый редактор, чтобы открыть файл с его помощью:
Outputno crontab for root - using an empty one
Select an editor. To change later, run 'select-editor'.
1. /bin/nano
2. /usr/bin/vim.basic
3. /usr/bin/vim.tiny
4. /bin/ed
Choose 1-4 [1]:
...
В конце файла добавьте следующую строку, заменив sammy
на ваше имя пользователя:
...
*/5 * * * * /home/sammy/drupal/ssl_renew.sh >> /var/log/cron.log 2>&1
В результате будет установлен интервал в пять минут для выполнения работы, и мы сможем проверить, работает ли запрос обновления в соответствии с ожиданиями. Также мы создали файл журнала, cron.log
, чтобы записывать соответствующий вывод выполнения задания.
Через пять минут воспользуйтесь командой tail
для проверки cron.log
, чтобы увидеть, выполнен ли запрос обновления:
- tail -f /var/log/cron.log
Вы увидите вывод, подтверждающий успешное обновление:
Output** 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/your_domain/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Нажмите CTRL+C
, чтобы завершить процесс tail
.
Теперь мы можем изменить файл crontab для запуска скрипта каждый 2-й день недели в 2:00. Измените последнюю строку crontab на следующее:
...
* 2 * * 2 /home/sammy/drupal/ssl_renew.sh >> /var/log/cron.log 2>&1
Закройте и сохраните файл.
Теперь удалим параметр --dry-run
из скрипта ssl_renew.sh
. Сначала откройте его:
- nano ssl_renew.sh
Затем измените содержимое на следующее:
#!/bin/bash
cd /home/sammy/drupal/
/usr/local/bin/docker-compose -f docker-compose.yml run certbot renew && \
/usr/local/bin/docker-compose -f docker-compose.yml kill -s SIGHUP webserver
Теперь наше задание cron
будет выполнять обновление сертификатов SSL.
В этом руководстве мы использовали Docker Compose для создания установки Drupal с веб-сервером Nginx. В рамках этого рабочего процесса мы получили сертификаты TLS/SSL для домена, который мы хотели ассоциировать с сайтом Drupal, и создали задание cron для обновления этих сертификатов при необходимости.
Для получения дополнительной информации посетите тематическую страницу Docker.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!