Docker-compose для создания nginx entrypoint
На одном сервере с docker-контейнерами может размещаться несколько веб-приложений, которые необходимо публиковать по http и https. Самый оптимальный способ это сделать в среде Docker — использовать отдельный контейнер с http-прокси, который будет переводить веб-запросы на нужные контейнеры, ориентируясь по доменным именам.
Рассмотрим пример файла docker-compose для проксирования запросов на другие контейнеры и возможностью получения сертификатов от Let's Encrypt.
Подготовка системы
Пример файла docker-compose.yml
Описание compose-файла
Запуск контейнера
Пример настройки виртуального домена
Настройка сети в docker-compose для работы с entrypoint
Получение сертификата от Let's Encrypt
Подготовка
Выполним предварительные действия. Предполагается, что мы будем хранить наш файл docker-compose в каталоге /opt/nginx.
Создаем каталог:
mkdir /opt/nginx
Перейдем в него:
cd /opt/nginx
Создаем файл docker-compose.yml:
vi docker-compose.yml
Мы готовы к написанию сценария.
Docker-compose
Пример нашего файла compose:
- services:
- nginx-entrypoint:
- image: nginx
- hostname: nginx-entrypoint
- container_name: nginx-entrypoint
- restart: unless-stopped
- environment:
- TZ: "Europe/Moscow"
- ports:
- - 80:80
- - 443:443
- volumes:
- - ./conf/conf.d:/etc/nginx/conf.d
- - ./conf/ssl:/etc/nginx/ssl
- - ./well-known:/usr/share/nginx/html
- - /opt/letsencrypt:/etc/letsencrypt
- networks:
- dnet:
- networks:
- dnet:
- name: dnet
- driver: bridge
Описание сценария
Кратко опишем, что выполнит наш сценарий. Подробнее про работу с docker-compose можно прочитать в инструкции Шпаргалка по работе с docker-compose.
1 - 19 | Поднимаем контейнер с nginx прокси. |
13 | Дополнительные конфигурационные файлы, которые будут подгружаться к основному. В них мы будем хранить настройки для виртуальных доменов. |
14 | Хранение самоподписанных или платных сертификатов. |
15 | Каталог обмена контентом, который нужен для валидации домена. Используется при получении бесплатных сертификатов от Let's Encrypt. |
16 | Бесплатные сертификаты, полученные от Let's Encrypt. |
20 - 23 | Общая сеть. Ее мы будем добавлять к другим службам других контейнеров для обеспечения сетевой доступности между данным контейнерами и нашим entrypoint. |
Запуск
Продолжая находиться в каталоге с файлом docker-compose, выполним команду:
docker-compose up -d
При первом запуске система загрузит образ с nginx и запустит контейнер. Посмотреть его состояние можно командой:
docker-compose ps
Пример конфигурации виртуального домена
Рассмотрим простой пример создания конфигурационного файла для проксирования http запросов.
Убедимся, что мы находимся в рабочем каталоге:
cd /opt/nginx
Создаем конфигурационный файл:
vi conf/conf.d/test.domain.ru.conf
* обязательно, чтобы название файла заканчивалось на .conf.
server {
listen 80;
server_name test.domain.ru;
location / {
proxy_pass http://my_site_container;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
* nginx с данной конфигурацией будет переводить запросы на контейнер my_site_container для запросов к сайту test.domain.ru.
Чтобы наш конфигурационный файл работал, контейнер nginx-entrypoint должен видеть сервис my_site_container (из нашего примера). Создадим его для теста:
docker run --rm -d --name my_site_container --network dnet nginx
* наш контейнер будет с именем my_site_container, работать в сети dnet.
Теперь можно применить конфигурацию nginx, но для начала, проверим корректность конфига:
docker exec nginx-entrypoint nginx -t
Если видим:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
... перечитываем конфигурацию:
docker exec nginx-entrypoint nginx -s reload
Можно проверять — при обращении к нашему домену в браузере мы должны получить страницу приветствия nginx:
После завершения проверки можно удалить тестовый контейнер:
docker rm -f my_site_container
И уже работать со своими образами.
Настройка других docker-compose
Также рассмотрим небольшой пример куска сценария для других файлов docker-compose, где будут описаны сервисы, которые должны взаимодействовать с нашим nginx-entrypoint. Последний работает в созданной сети dnet — это значит, что для сервиса нужно указать такую настройку:
services:
service_name:
...
networks:
- default
- dnet
...
networks:
...
dnet:
name: dnet
external: true
* итого, чтобы все работало, среди перечня сетей должна быть перечислена та, в которой находится nginx-entrypoint (в нашем примере это dnet).
Получение сертификата (настройка HTTPS)
Ну и напоследок, рассмотрим процесс получения сертификата от Let's Encrypt. Подробнее процесс описан в инструкции Получение бесплатного SSL сертификата Let's Encrypt.
Для получения сертификата в docker мы будем использовать образ certbot/certbot
docker run -it --rm --name certbot -v "/opt/letsencrypt:/etc/letsencrypt" -v "/opt/nginx/well-known:/usr/share/nginx/html" certbot/certbot certonly --webroot --agree-tos --email postmaster@dmosk.ru --webroot-path /usr/share/nginx/html/ -d test.domain.ru -d www.test.domain.ru
* в данном примере мы задействуем пути, которые описали выше в сценарии — каталог /opt/letsencrypt, куда будут сохранены полученные сертификаты и /opt/nginx/well-known для размещения временных файлов, необходимых при проверке домена.
** Мы получим сертификаты для хостов test.domain.ru и www.test.domain.ru. Важно, чтобы данные имена вели на наш сервер с nginx.
Если все пройдет успешно, мы увидим:
...
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/test.domain.ru/fullchain.pem
Key is saved at: /etc/letsencrypt/live/test.domain.ru/privkey.pem
...
Теперь нужно вернуться к конфигурационному файлу для виртуального домена:
vi /opt/nginx/conf/conf.d/test.domain.ru.conf
И разрешить использование ssl:
- Заменяем значение listen с 80 на 443 ssl.
- Добавляем опции ssl_certificate и ssl_certificate_key в качестве значений который, соответственно, прописываем открытый и закрытый ключи.
- Дописываем блок с listen 80 для настройки автоматического редиректа с http на https.
Все изменения выделены желтым:
server {
listen 443 ssl;
server_name test.domain.ru;
location ~ /.well-known {
root /usr/share/nginx/html;
allow all;
}
ssl_certificate /etc/letsencrypt/live/test.domain.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/test.domain.ru/privkey.pem;
location / {
proxy_pass http://my_site_container;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 80;
server_name test.domain.ru;
return 301 https://$host$request_uri;
}
Проверяем конфигурацию и перечитываем ее:
docker exec nginx-entrypoint sh -c "nginx -t && nginx -s reload"
Снова открываем в браузере наш сайт — запрос должен быть переброшен на https.
Для продления сертификатов можно использовать команду:
docker run -it --rm --name certbot -v "/opt/letsencrypt:/etc/letsencrypt" -v "/opt/nginx/well-known:/usr/share/nginx/html" certbot/certbot renew
После продления необходимо перечитать конфигурацию nginx:
docker exec nginx-entrypoint nginx -s reload
Также мы можем настроить задание в cron, например:
crontab -e
0 0 * * 1,4 /usr/bin/docker run --rm --name certbot -v "/opt/letsencrypt:/etc/letsencrypt" -v "/opt/nginx/well-known:/usr/share/nginx/html" certbot/certbot renew && /usr/bin/docker exec nginx-entrypoint sh -c "nginx -t && nginx -s reload"