Skip to content

Commit

Permalink
Refactor (infra): Changes the strategy for deploying, removes traefik…
Browse files Browse the repository at this point in the history
… and uses nginx-proxy. The previous strategy had traefik and nginx (nginx just serving the static files).
  • Loading branch information
leandrodesouzadev committed Oct 19, 2023
1 parent 8e5489e commit d02180c
Show file tree
Hide file tree
Showing 12 changed files with 171 additions and 274 deletions.
58 changes: 54 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -811,23 +811,73 @@ Após alguns segundos você terá duas instâncias da aplicação Django rodando

## Deploy

Normalmente o deploy das aplicações são realizados em uma VPS, como a Amazon EC2. O Boilerplate já vem configurado com CI/CD para o ambiente de Staging, porém é simples copiar e criar um outro worfklow para o ambiente de produção.
Normalmente o deploy das aplicações são realizados em uma VPS, como a Amazon EC2. O Boilerplate já vem configurado com CI/CD para o ambiente de Staging e Produção. Porém o primeiro deploy é necessário a configuração pelo usuário.

> Apesar de apenas copiar e colar o workflow seja o suficiente para o ambiente de produção, perceba que o deploy atual possui downtime de cerca de 30 segundos.
> O formato de deploy atual possui downtime de cerca de 5 segundos.
Antes do primeiro deploy por CI/CD será necessário:
- Criar a máquina virtual;
- Atribuir um domínio para o endereço da máquina;
- Instalar as dependências (git, docker compose) na máquina;
- Configurar o acesso via SSH ao Github (quando criar sua chave SSH não coloque um passphrase, caso contrário o processo de CD irá falhar);
- Configurar as variáveis de ambiente;
- Subir a aplicação manualmente.
- [Subir a aplicação manualmente](#subir-a-aplicação-pela-primeira-vez).

Após estes passos, o fluxo de CI/CD fará deploys automaticamente, após a configuração das Secrets no Github (Dentro do repositório -> `Settings` -> `Secrets`).
Vá até o arquivo [deploy_to_staging.yml](./.github/workflows/deploy_to_staging.yml) e verifique as variáveis de ambiente necessárias. Elas provavelmente são:
Vá até o arquivo [deploy_to_staging.yml](./.github/workflows/deploy_to_staging.yml) e verifique as variáveis de ambiente necessárias. Elas são:

- `STAGING_SSH_PRIVATE_KEY`: Chave SSH Privada utilizada para conectar na máquina
- `STAGING_SSH_HOSTNAME`: Nome do HOST para acesso SSH
- `STAGING_USER_NAME`: Nome do usuário da máquina para acesso SSH

> Perceba que os valores das variáveis de ambiente são prefixados para o ambiente de deploy, caso esteja criando um novo arquivo de deploy para outro ambiente, garanta que as variáveis estarão prefixadas com o nome do ambiente. Exemplo: `PRODUCTION_SSH_PRIVATE_KEY`.
Para o ambiente de produção, o fluxo é praticamente o mesmo, porém as variáveis de ambiente são:
- `PRODUCTION_SSH_PRIVATE_KEY`: Chave SSH Privada utilizada para conectar na máquina
- `PRODUCTION_SSH_HOSTNAME`: Nome do HOST para acesso SSH
- `PRODUCTION_USER_NAME`: Nome do usuário da máquina para acesso SSH


### Subir a aplicação pela primeira vez

Para subir a aplicação pela primeira vez será necessário subir alguns serviços na máquina, porém já existem scripts que fazem a maior parte do trabalho.
Primeiro passo é rodar o script [start_nginx_acme.sh](./infra/server/start_nginx_acme.sh) a partir do root do repositório:
```sh
./infra/server/start_nginx_acme.sh
```
Esse comando irá iniciar dois containers: o [nginx-proxy](https://github.com/nginx-proxy/nginx-proxy) e [nginx-proxy-acme](https://github.com/nginx-proxy/acme-companion). Que tem como objetivo:
- nginx-proxy: Reverse-proxy que ficará na frente da aplicação Django e demais serviços;
- nginx-proxy-acme: Configura automaticamente HTTPs;

Após isso, será necessário subir a infraestrutura de serviços de terceiros, dependendo do ambiente.

Para o ambiente de staging, utilize o compose [infra/server/3rd_party/staging.yml](./infra/server/3rd_party/staging.yml), com o comando:
```sh
docker compose -f ./infra/server/3rd_party/staging.yml --env-file .env up -d
```

Para o ambiente de produção, utilize o compose [infra/server/3rd_party/production.yml](./infra/server/3rd_party/production.yml), com o comando:
```sh
docker compose -f ./infra/server/3rd_party/production.yml --env-file .env up -d
```

Após isso é possível subir o compose da aplicação de acordo com o ambiente.

Para o ambiente de staging, utilize o compose [staging.yml](./staging.yml), com o comando:
```sh
docker compose -f staging.yml --env-file .env build --no-cache
docker compose -f staging.yml --env-file .env up -d
```

Para o ambiente de produção, utilize o compose [production.yml](./production.yml), com o comando:
```sh
docker compose -f production.yml --env-file .env build --no-cache
docker compose -f production.yml --env-file .env up -d
```

Feito! A aplicação estará no ar. Após isso o processo de CI/CD irá fazer deploys automaticamente na máquina.


### Detalhes sobre os ambientes de staging/produção

Os arquivos estáticos são servidos pelo nginx em qualquer domínio! Não encontramos um jeito melhor de servir os arquivos estáticos sem ser configurando um fallback para quando não é possível se conectar com um container. Essa configuração está definida no arquivo [infra/nginx/conf.d/fallback_server.conf](./infra/nginx/conf.d/fallback_server.conf).
1 change: 1 addition & 0 deletions infra/nginx/conf.d/custom_proxy.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
client_max_body_size 100m;
8 changes: 8 additions & 0 deletions infra/nginx/conf.d/fallback_server.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
server {
listen 80 default_server;
root /usr/share/nginx/static;

location /static {
alias /usr/share/nginx/static;
}
}
51 changes: 0 additions & 51 deletions infra/nginx/nginx.conf.template

This file was deleted.

19 changes: 19 additions & 0 deletions infra/server/3rd_party/production.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
version: "3.3"

services:
redis:
image: "redis"
ports:
- "${REDIS_PORT}:${REDIS_PORT}"
command: redis-server --requirepass ${REDIS_PASSWORD} --replicaof no one --replica-read-only no
volumes:
- cache:/data
networks:
- shared

volumes:
cache:

networks:
shared:
external: true
34 changes: 34 additions & 0 deletions infra/server/3rd_party/staging.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
version: "3.3"

services:
redis:
image: "redis"
ports:
- "${REDIS_PORT}:${REDIS_PORT}"
command: redis-server --requirepass ${REDIS_PASSWORD} --replicaof no one --replica-read-only no
volumes:
- cache:/data
networks:
- shared

db:
image: postgres:16-alpine
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "${SQL_PORT}:${SQL_PORT}"
command: -p ${SQL_PORT}
environment:
POSTGRES_PASSWORD: ${SQL_PASSWORD}
POSTGRES_USER: ${SQL_USER}
POSTGRES_DB: ${SQL_DATABASE}
networks:
- shared

volumes:
cache:
postgres_data:

networks:
shared:
external: true
30 changes: 30 additions & 0 deletions infra/server/start_nginx_acme.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/sh
set -e

echo "Creating the shared network..."
docker network create shared

echo "Starting nginx-proxy..."
docker run --detach \
--name nginx-proxy \
--publish 80:80 \
--publish 443:443 \
--volume certs:/etc/nginx/certs \
--volume vhost:/etc/nginx/vhost.d \
--volume html:/usr/share/nginx/html \
--volume /var/run/docker.sock:/tmp/docker.sock:ro \
--volume ./infra/nginx/conf.d/custom_proxy.conf:/etc/nginx/conf.d/custom_proxy.conf \
--volume ./infra/nginx/conf.d/fallback_server.conf:/etc/nginx/conf.d/fallback_server.conf \
--volume staticfiles:/usr/share/nginx/static \
--network shared \
nginxproxy/nginx-proxy

echo "Starting nginx-proxy-acme..."
docker run --detach \
--name nginx-proxy-acme \
--volumes-from nginx-proxy \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
--volume acme:/etc/acme.sh \
--env "[email protected]" \
--network shared \
nginxproxy/acme-companion
3 changes: 0 additions & 3 deletions infra/traefik/traefik.Dockerfile

This file was deleted.

43 changes: 0 additions & 43 deletions infra/traefik/traefik.yml

This file was deleted.

3 changes: 1 addition & 2 deletions local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ services:

command: python3 manage.py runserver_plus 0.0.0.0:${DJANGO_HTTP_PORT:-8000}
depends_on:
db:
condition: service_started
redis:
condition: service_started
mailpit:
Expand Down Expand Up @@ -73,4 +71,5 @@ services:

volumes:
postgres_data:
mediafiles:
cache:
Loading

0 comments on commit d02180c

Please sign in to comment.