Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
552 views
in Technique[技术] by (71.8m points)

apache - How to set up SSL in Docker container

Resume

I have an Apache server running two applications in production. I want to implement other application made in Django that is served by Nginx inside a Docker container. The architecture is as follows:

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

enter image description here

What I want

I want to implement SSL certbot certificate, but I don't know how it should be set up communication between host(Apache) and container(Nginx) with HTTPS.

  1. I must install the Certbot certificate for Apache and this same certificate I can use for Nginx?
  2. how should be the HTTPS redirections between Apache in the host and Nginx in the container?.

I Take as reference this article where a similar architecture is implemented with the difference that Apache is installed in both the host and the Docker container, and which uses the same certificate created by Certbot for both servers but I don't know if this same logic applies between different servers like Apache and Nginx.

What I have

Apache host server config file

<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>

docker-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 config inside Docker container

I'm not sure how to configure HTTPS connection in Nginx inside Docker container to receive https requests from Apache and then redirect to the DJango app.

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;
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Try to keep your container as stateless as possible, so don't use certbot inside the container. Instead use certbot for Apache or whatever web server you have outside of your application container.

It's okay to have Apache talk to your application container in plain HTTP since your container is not exposed to the public web (make sure it only accepts localhost connections). Many people take an even easier route and use Cloudflare for SSL, this means the switch from http to https happens even closer to the end user.

Note: This method of having a reverse proxy handle SSL instead of your application is called "SSL Termination".


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...