Skip to content

This article is available in Russian. An English version is on the way.Open the Russian page

Nginx перед контейнерами: домены и HTTPS

Отдавать несколько приложений из Docker на своих доменах с сертификатами: Nginx на хосте или Caddy в контейнере.

Level
Intermediate
Reading time
3 min read
Updated
Tested on
Ubuntu 22.04, Ubuntu 24.04, Debian 12
Contents
  1. Вариант 1: Nginx на хосте
  2. Вариант 2: Caddy в контейнере
  3. DNS и фаервол
  4. Проверьте результат
  5. Частые ошибки

Надёжная схема для сервера с контейнерами: приложения слушают только 127.0.0.1 или внутреннюю сеть Docker, а наружу смотрит один обратный прокси на портах 80 и 443. Он принимает HTTPS, выбирает сервис по домену и передаёт запрос дальше.

Вариант 1: Nginx на хосте

Подходит, если Nginx уже стоит или вы привыкли к Certbot. Контейнер публикует порт только на локальном адресе:

compose.yaml
services:  app:    image: ghcr.io/example/myapp:1.4.2    restart: unless-stopped    ports:      - "127.0.0.1:3000:3000"
/etc/nginx/sites-available/app.example.com
server {    listen 80;    server_name app.example.com;    location / {        proxy_pass http://127.0.0.1:3000;        proxy_set_header Host $host;        proxy_set_header X-Real-IP $remote_addr;        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        proxy_set_header X-Forwarded-Proto $scheme;        proxy_http_version 1.1;        proxy_set_header Upgrade $http_upgrade;        proxy_set_header Connection "upgrade";    }}
bash
$ ln -s /etc/nginx/sites-available/app.example.com /etc/nginx/sites-enabled/$ nginx -t && systemctl reload nginx$ certbot --nginx -d app.example.com

Вариант 2: Caddy в контейнере

Caddy сам получает и продлевает сертификаты Let’s Encrypt. Прокси и приложения живут в одной сети Compose, поэтому порты приложений вообще не публикуются.

compose.yaml
services:  caddy:    image: caddy:2    restart: unless-stopped    ports:      - "80:80"      - "443:443"    volumes:      - ./Caddyfile:/etc/caddy/Caddyfile:ro      - caddy-data:/data      - caddy-config:/config  app:    image: ghcr.io/example/myapp:1.4.2    restart: unless-stoppedvolumes:  caddy-data:  caddy-config:
Caddyfile
app.example.com {    reverse_proxy app:3000}

Каждый новый сервис — ещё один блок с доменом в Caddyfile. После правки перечитайте конфигурацию: docker compose exec caddy caddy reload --config /etc/caddy/Caddyfile.

DNS и фаервол

Перед выпуском сертификата A-запись домена должна указывать на IP сервера, а порты 80 и 443 — быть открыты:

bash
$ ufw allow 80/tcp$ ufw allow 443/tcp$ dig +short app.example.com

Проверьте результат

bash
$ curl -I https://app.example.com$ ss -tlnp | grep -E ":(80|443|3000) "

По HTTPS должен прийти ответ приложения; порт 3000 — только на 127.0.0.1 или не опубликован вовсе.

Частые ошибки

  • 502 Bad Gateway — приложение не запущено или слушает другой порт. Проверьте docker compose ps и логи.
  • Приложение видит IP прокси вместо IP клиента — включите в нём доверие к заголовку X-Forwarded-For от адреса прокси.
  • Caddy не получает сертификат — DNS ещё не обновился или порт 80 закрыт. Смотрите docker compose logs caddy.

Read to the end and the article counts toward your learning progress.

  • nginx
  • caddy
  • обратный прокси
  • docker
  • https

Was this article helpful?