Как настроить SSL в контейнере Docker

Продолжить

У меня есть сервер Apache, на котором запущены два приложения. Я хочу реализовать другое приложение, созданное в Django, которое обслуживается Nginx внутри контейнера Docker. Архитектура выглядит следующим образом:

User request --> Apache --> Nginx inside Docker --> Gunicorn inside Docker --> Django app inside Docker

введите здесь описание изображения

Что я хочу

Я хочу реализовать SSL certbot certificate, но не знаю, как настроить связь между хостом (Apache) и контейнером (Nginx) с помощью HTTPS.

  1. Я должен установить сертификат Certbot для Apache и использовать этот же сертификат для Nginx?
  2. Каким должно быть перенаправление HTTPS между Apache на хосте и Nginx в контейнере?.

Я беру за основу эту статью, где реализована подобная архитектура с той разницей, что Apache установлен как на хосте, так и в контейнере Docker, и использует один и тот же сертификат, созданный Certbot для обоих серверов, но я не знаю, применяется ли эта же логика между разными серверами, такими как Apache и Nginx.

Что я имею

Конфигурационный файл хост-сервера Apache

<VirtualHost *:80>
        ServerName app.com.co
        ServerAdmin [email protected]

        ErrorLog /var/log/app_com_co/error.log
        CustomLog /var/log/app_com_co/access.log combined

        ProxyPreserveHost On
        ProxyPass        "/" "http://127.0.0.1:1300/"
        ProxyPassReverse "/" "http://127.0.0.1:1300/"
</VirtualHost>
 
# Apache SSL Relate things in host

<VirtualHost *:443>
       ServerName app.com.co
       ServerAdmin [email protected]

       ErrorLog /var/log/app_com_co/error.log
       CustomLog /var/log/app_com_co/access.log combined

       # Enable/Disable SSL for this virtual host.
       SSLEngine on

       # Activate SSL for proxy
       SSLProxyEngine On

       # Disable certificate verification in communication between host and container
       SSLProxyVerify none
       SSLProxyCheckPeerCN off
       SSLProxyCheckPeerName off
       SSLProxyCheckPeerExpire off

       # Defines that The host will pass the Host: line from the incoming request to
       # the container instead of the hostname specified in the ProxyPass line.
       ProxyPreserveHost On
       ProxyPass        "/" "https://127.0.0.1:14443/"
       ProxyPassReverse "/" "https://127.0.0.1:14443/"

       # Self signed SSL Certificate file
       SSLCertificateFile /etc/letsencrypt/live/app.com.co/fullchain.pem
       SSLCertificateKeyFile /etc/letsencrypt/live/app.com.co/privkey.pem
       Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>

докер-compose.yml

version: '3.8'

services:
  nginx:
    build: ./nginx
    ports:
      - 1300:80
      - 14443:443
    depends_on:
      - backend
    networks:
      - backend-tier

  backend:
    expose:
      - 8000
    build:
      context: .
      dockerfile: ./Dockerfile
    restart: unless-stopped
    networks:
      - backend-tier
    depends_on:
      - db
      - redis
    volumes:
      - ./app_com_co/:/app/app_com_co:Z
      - ./app_com_co/templates/:/app/app_com_co/templates:Z
      # shared volume between worker, beat and backend for media
      - app-media:/app/app_com_co/media
    env_file: common.env

  db:
    image: library/postgres:11.1-alpine
    ports:
      - 5439:5432
    restart: unless-stopped
    networks:
      - backend-tier
    volumes:
      - app-db:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=myuser
      - POSTGRES_PASSWORD=mypassword
      - POSTGRES_DB=mydb

  redis:
    image: library/redis:5.0-alpine
    ports:
      - 6379:6379
    restart: unless-stopped
    networks:
      - backend-tier
    volumes:
      - app-redis:/data

  worker:
    build:
      context: .
      dockerfile: ./Dockerfile
    command: celery -A config --app=config.celery_app:app worker --loglevel=info
    restart: unless-stopped
    networks:
      - backend-tier
    env_file: common.env
    depends_on:
      - redis
    volumes:
      - ./app_com_co/:/app/app_com_co:Z,cached
      - ./app_com_co/templates/:/app/app_com_co/templates:Z,cached
      # shared volume between worker, beat and backend for media
      - app-media:/app/app_com_co/media

  beat:
    build:
      context: .
      dockerfile: ./Dockerfile
    command: celery -A config --app=config.celery_app:app beat --loglevel=info
    restart: unless-stopped
    networks:
      - backend-tier
    env_file: common.env
    depends_on:
      - redis
    volumes:
      - ./app_com_co/:/app/app_com_co:Z,cached
      - ./app_com_co/templates/:/app/app_com_co/templates:Z,cached
      # shared volume between worker, beat and backend for media
      - app-media:/app/app_com_co/media

volumes:
  app-db:
    driver: local
  app-redis:
    driver: local
  app-media:

networks:
  backend-tier:
    driver: bridge

Конфигурация Nginx внутри контейнера Docker

Я не знаю, как настроить HTTPS-соединение в Nginx внутри контейнера Docker для получения https-запросов от Apache и последующего перенаправления в приложение DJango.

upstream django {
    server backend:8000;
}

server {
    listen 80;

    location / {
        proxy_pass http://django;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;
        client_max_body_size 4G;
    }
}

person Cristian Flórez    schedule 31.12.2020    source источник


Ответы (1)


Старайтесь, чтобы ваш контейнер был как можно более апатридным, поэтому не используйте certbot внутри контейнера. Вместо этого используйте certbot для Apache или любого другого веб-сервера, который у вас есть за пределами вашего контейнера приложений.

Это нормально, когда Apache общается с контейнером вашего приложения в простом HTTP, так как ваш контейнер не открыт для общедоступной сети (убедитесь, что он принимает только соединения с локальным хостом). Многие выбирают еще более простой путь и используют Cloudflare для SSL, это означает, что переход с http на https происходит еще ближе к конечному пользователю.

Примечание. Этот метод использования обратного прокси-сервера для обработки SSL вместо вашего приложения называется терминацией SSL.

person Hassan Selim    schedule 31.12.2020