2
respostas

[Dúvida] Ansible + Docker (Ningx, Projeto Django, PostgreSQL) + Certificado HTTPS

Eu estou implementando um projeto que combina os conhecimentos que tenho em utilizar Docker com Ansible. Meu playbook roda tranquilo, e sobe todas as camadas do projeto perfeitamente, o que preciso agora é uma etapa adicionar para instalar o lets encrypt no container do Nginx que funciona como proxy da minha aplicação Django.

Minha arquitetura foi estruturada para utilizar containers para cada uma das camadas do projeto, atualmente meu arquivo docker-compose está assim:

version: "3.7"

networks:
  projeto_teste_network:
    name: projeto_teste_network

services:
  projeto_teste_database:
    container_name: projeto_teste_database
    image: postgres:16.1
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
    restart: always
    volumes:
      - projeto_teste-db:/var/lib/postgresql/data
    environment:
      - LC_ALL=C.UTF-8
      - POSTGRES_DB=projeto_teste_db
      - POSTGRES_USER=xyz
      - POSTGRES_PASSWORD=...
      - POSTGRES_HOST_AUTH_METHOD=md5
    networks:
      - projeto_teste_network
    ports:
      - "5437:5432"

  projeto_teste_django:
    container_name: projeto_teste_django
    image: projeto_teste:1.0
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
    environment:
      - DB_NAME=projeto_teste_db
      - DB_PASSWORD=...
      - DB_USER=xyz
      - DB_HOST=xyz_db
      - DB_PORT=5432
      - DEBUG=False
      - DB_ENGINE=django.db.backends.postgresql_psycopg2
      - SECRET_KEY=......
      - ALLOWED_HOSTS=.localhost,*
      - API_PATH=http://localhost:8080/api/
      - PYTHONDONTWRITEBYTECODE=1
      - PYTHONUNBUFFERED=1
    build:
      context: .
      dockerfile: ./Dockerfile
    entrypoint: /home/app/.../foo.sh
    networks:
      - projeto_teste_network
    volumes:
      - projeto_teste-media:/home/app/projeto_teste_django/media
      - projeto_teste-static:/home/app/projeto_teste_django/static
    depends_on:
      - projeto_teste_database

  gateway:
    image: nginx:1.19-alpine
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
    container_name: projeto_teste_gateway
    restart: unless-stopped
    networks:
      - projeto_teste_network
    expose:
      - 443
      - 82
    ports:
      - "8004:82"
    depends_on:
      - projeto_teste_django
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
      - projeto_teste-media:/home/app/projeto_teste_django/media
      - projeto_teste-static:/home/app/projeto_teste_django/static

volumes:
  projeto_teste-db:
  projeto_teste-media:
  projeto_teste-static:

Já o arquivo nginx.conf está assim:

upstream projet_teste {
  server projeto_teste_django:8004;
}

server {
    listen 82 ;
    client_max_body_size 2048M;
    charset utf-8;
    server_name _;

    # Frontend
    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect off;
        proxy_pass http://projet_teste/;
    }

    location /static/ {
        alias /home/app/projeto_teste_django/static/;
    }

    location /media/ {
        alias /home/app/projeto_teste_django/media/;
    }

    location = /favicon.ico
    {
        access_log off; log_not_found off;
    }
}

O que estou precisando fazer é instalar e configurar o nginx para rodar com https, utilizando o let's encrypt (https://letsencrypt.org/)

2 respostas

Oi, Afrânio! Tudo bem?

Você pode fazer isso usando o Certbot :)

Ele é uma ferramenta automatizada para obtenção e renovação de certificados SSL/TLS fornecidos pelo Let's Encrypt.

Primeiro, você precisa adicionar algumas linhas ao seu arquivo Dockerfile para o Nginx para instalar o Certbot. Aqui está um exemplo:

FROM nginx:1.19-alpine

RUN apk add --no-cache certbot

COPY ./nginx.conf /etc/nginx/conf.d/default.conf

CMD ["nginx", "-g", "daemon off;"]

Em seguida, você vai adicionar um novo serviço ao seu arquivo docker-compose.yml para executar o Certbot. Vou deixar um exemplo abaixo:

certbot:
  image: certbot/certbot
  volumes:
    - ./letsencrypt:/etc/letsencrypt
  entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done'"

Finalmente, você vai ter que modificar o seu arquivo nginx.conf para usar os certificados gerados pelo Certbot. Outro exemplo pra ficar mais prático:

server {
    listen 82 ;
    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/seudominioaqui/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/seudominioaqui/privkey.pem;

    ...
}

Lembre-se de substituir o seudominioaqui pelo seu domínio real.

Como não temos acesso à aplicação, é um pouco difícil dar uma solução mais cirúrgica. Mas espero que isso já te dê uma ajudinha.

Abraços!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.

Meu DockerFile já contem instruções para construir a imagem do projeto que estou tentando rodar, conforme abaixo:

FROM python:3.12.1-slim as builder

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV CRYPTOGRAPHY_DONT_BUILD_RUST=1

WORKDIR /app

RUN apt-get clean && apt-get update
RUN apt-get -y install sudo --no-install-recommends build-essential libpq-dev
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
COPY . /app
RUN pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/app/wheels -r requirements.txt

EXPOSE 8181

FROM python:3.12.1-slim

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV CRYPTOGRAPHY_DONT_BUILD_RUST=1

ENV HOME=/home/api
ENV APP_HOME=/home/api/*******

RUN mkdir -p $HOME
RUN mkdir $APP_HOME

WORKDIR $APP_HOME

COPY --from=builder /usr/src/app/wheels /wheels
COPY --from=builder /app .

RUN pip install -U setuptools pip
RUN pip install --no-cache /wheels/*

COPY requirements.txt .
RUN python -m pip install -r requirements.txt

RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser $APP_HOME
USER appuser

Como eu faria para adicionar a resposta sugerida neste contexto?