Docker-compose для создания nginx entrypoint

Обновлено Обновлено: Опубликовано Опубликовано:

На одном сервере с docker-контейнерами может размещаться несколько веб-приложений, которые необходимо публиковать по http и https. Самый оптимальный способ это сделать в среде Docker — использовать отдельный контейнер с http-прокси, который будет переводить веб-запросы на нужные контейнеры, ориентируясь по доменным именам.

Рассмотрим пример файла docker-compose для проксирования запросов на другие контейнеры и возможностью получения сертификатов от Let's Encrypt.

Подготовка

Выполним предварительные действия. Предполагается, что мы будем хранить наш файл docker-compose в каталоге /opt/nginx.

Создаем каталог:

mkdir /opt/nginx

Перейдем в него:

cd /opt/nginx

Создаем файл docker-compose.yml:

vi docker-compose.yml

Мы готовы к написанию сценария.

Docker-compose

Пример нашего файла compose:

  1. services:
  2.   nginx-entrypoint:
  3.     image: nginx
  4.     hostname: nginx-entrypoint
  5.     container_name: nginx-entrypoint
  6.     restart: unless-stopped
  7.     environment:
  8.       TZ: "Europe/Moscow"
  9.     ports:
  10.       - 80:80
  11.       - 443:443
  12.     volumes:
  13.       - ./conf/conf.d:/etc/nginx/conf.d
  14.       - ./conf/ssl:/etc/nginx/ssl
  15.       - ./well-known:/usr/share/nginx/html
  16.       - /opt/letsencrypt:/etc/letsencrypt
  17.     networks:
  18.       dnet:
  19.  
  20. networks:
  21.   dnet:
  22.     name: dnet
  23.     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:

Страница приветствия в 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:

  1. Заменяем значение listen с 80 на 443 ssl.
  2. Добавляем опции ssl_certificate и ssl_certificate_key в качестве значений который, соответственно, прописываем открытый и закрытый ключи.
  3. Дописываем блок с 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"

# DevOps # Linux # Интернет # Серверы
Дмитрий Моск — частный мастер
Был ли вам полезен этот скрипт?

Да            Нет