QPANC - Parte 20 - Docker - Traefik e Publicação
Tags: quasar, postgres, aspnetcore, docker
Published: 2020-04-19 23:39:33

> **QPANC** são as iniciais de **Q**uasar **P**ostgreSQL **A**SP **N**ET **C**ore.

  * [Source](https://github.com/TobyMosque/qpanc)
  * [Introdução](https://dev.to/quasar-pt-br/arquiteturando-uma-aplicacao-com-quasar-postgresql-asp-net-core-e-docker-introducao-o7o)
  * [Parte I - ASP.NET - Inicializando os Projetos](https://dev.to/quasar-pt-br/qpanc-parte-1-asp-net-inicializando-os-projetos-lkm)
  * [Parte 2 - PostgreSQL](https://dev.to/quasar-pt-br/qpanc-parte-2-postgresql-51pb)
  * [Parte 3 - ASP.NET - Registrando Serviços e Lendo Variáveis de Ambiente](https://dev.to/quasar-pt-br/qpanc-parte-3-asp-net-registrando-servicos-e-lendo-variaveis-de-ambiente-3do2)
  * [Parte 4 - ASP.NET - Entity Framework e ASP.NET Core Identity](https://dev.to/quasar-pt-br/qpanc-parte-4-asp-net-entity-framework-e-asp-net-core-identity-40f9)
  * [Parte 5 - ASP.NET - Documentação Interativa com Swagger](https://dev.to/quasar-pt-br/qpanc-parte-5-asp-net-documentacao-interativa-com-swagger-4n0o)
  * [Parte 6 - ASP.NET - Regionalização](https://dev.to/quasar-pt-br/qpanc-parte-6-asp-net-regionalizacao-13p5)
  * [Parte 7 - ASP.NET - Autenticação e Autorização](https://dev.to/quasar-pt-br/qpanc-parte-7-asp-net-autenticacao-e-autorizacao-bpd)
  * [Parte 8 - ASP.NET - CORS](https://dev.to/quasar-pt-br/qpanc-parte-8-asp-net-cors-52dn)
  * [Parte 9 - Quasar - Criação e Configuração do Projeto](https://dev.to/quasar-pt-br/qpanc-parte-9-quasar-criacao-e-configuracao-do-projeto-5hbi)
  * [Parte 10 - Quasar - Configurações e Customizações](https://dev.to/quasar-pt-br/qpanc-parte-10-quasar-configuracoes-e-customizacoes-2i86)
  * [Parte 11 - Quasar - Componentes - Diferença entre SPA e SSR](https://dev.to/quasar-pt-br/qpanc-parte-11-quasar-componentes-diferenca-entre-spa-e-ssr-1a3c)
  * [Parte 12 - Quasar - Serviços](https://dev.to/quasar-pt-br/qpanc-parte-12-quasar-servicos-4e61)
  * [Parte 13 - Quasar - Regionalização e Stores](https://dev.to/quasar-pt-br/qpanc-parte-13-quasar-regionalizacao-e-stores-1kep)
  * [Parte 14 - Quasar - Consumindo a API](https://dev.to/quasar-pt-br/qpanc-parte-14-quasar-consumindo-a-api-fn6)
  * [Parte 15 - Quasar - Login](https://dev.to/quasar-pt-br/qpanc-parte-15-quasar-login-jc6)
  * [Parte 16 - Quasar - Áreas Protegidas](https://dev.to/quasar-pt-br/qpanc-parte-16-quasar-areas-protegidas-3jkn)
  * [Parte 17 - Quasar - Registro](https://dev.to/quasar-pt-br/qpanc-parte-17-quasar-registro-3b8c)
  * [Parte 18 - Docker - Maquina Virtual Linux](https://dev.to/quasar-pt-br/qpanc-parte-18-docker-maquina-virtual-linux-g5c)
  * [Parte 19 - Docker - Registro e Build](https://dev.to/quasar-pt-br/qpanc-parte-19-docker-registro-e-build-31i4)
  * [Parte 20 - Docker - Traefik e Publicação](https://dev.to/quasar-pt-br/qpanc-parte-20-docker-traefik-e-publicacao-3g3d)
  * [Demo Online](https://qpanc.tobiasmesquita.dev)

##40 Configurando os serviços na VM

Para orquestrar as requisições na VM, iremos utilizar o `traefik`, porém iremos utilizar autenticação `basic` para proteger o seu painel, desta forma, precisamos primeiro codificar uma senha, para tal, execute o seguinte comando na terminal `SSH` conectado a `VM`.

```
sudo apt-get install apache2-utils
echo $(htpasswd -nb ${user} ${password}) | sed -e s/\\$/\\$\\$/g
```

por exemplo, para o usuario `qpanc` e a senha `exposed`:
```
echo $(htpasswd -nb qpanc exposed) | sed -e s/\\$/\\$\\$/g

qpanc:$$apr1$$U0UpF78N$$3AxgB876rR09fJ5OuylKk/
```

Agora, podemos montar o `compose.yml` que será utilizado na `VM`:

```yml
version: '3.4'

services:
  qpanc.api:
    restart: always
    container_name: qpanc_api
    depends_on:
      - qpanc.database
    image: qpanc.azurecr.io/api:latest
    ports:
      - "34512:80"
    volumes:
      - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
      - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
    networks:
      qpanc.network:
      qpanc.internal:
        ipv4_address: "172.18.18.3"
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
      - ASPNETCORE_URLS=http://+:80
      - DEFAULT_CONNECTION=Server=qpanc.database;Port=5432;Database=postgres;User Id=postgres;Password=keepitsupersecret;
      - JWTBEARER_VALIDISSUER=https://api.your_domain.com/
      - JWTBEARER_VALIDAUDIENCE=https://api.your_domain.com/
      - JWTBEARER_ISSUERSIGNINGKEY=itUXC7iVRsofSDWNeg/aLYpc4bMzHAsMPzeItE1PQi2tMK2f4t0InRgTE5B/4IAjhAX5LQSIGL1CaUHSSzED8A==
      - JWTBEARER_TOKENDECRYPTIONKEY=7hfboHG0d4GnXjVng0ukMo+IgrKKrPLUMtOvnt4S514=
      - CORS_HOSTS__0=your_domain.com
    labels:
      - "traefik.enable=true"
      - "traefik.http.services.qpanc_api.loadbalancer.server.port=80"
      - "traefik.http.routers.qpanc_api.rule=Host(`api.your_domain.com`)"
      - "traefik.http.routers.qpanc_api.entrypoints=web"
      - "traefik.http.routers.qpanc_api.service=qpanc_api"
      - "traefik.http.routers.qpanc_api-secure.rule=Host(`api.your_domain.com`)"
      - "traefik.http.routers.qpanc_api-secure.tls=true"
      - "traefik.http.routers.qpanc_api-secure.tls.certresolver=le"
      - "traefik.http.routers.qpanc_api-secure.entrypoints=websecure"
      - "traefik.http.routers.qpanc_api-secure.service=qpanc_api"
      - "traefik.docker.network=external_network"

  qpanc.app:
    restart: always
    container_name: qpanc_app
    image: qpanc.azurecr.io/app:latest
    ports:
      - "34515:3000"
    volumes:
      - webapp:/app
    networks:
      qpanc.network:
      qpanc.internal:
        ipv4_address: "172.18.18.6"
    labels:
      - "traefik.enable=true"
      - "traefik.http.services.qpanc_app.loadbalancer.server.port=3000"
      - "traefik.http.routers.qpanc_app.rule=Host(`your_domain.com`)"
      - "traefik.http.routers.qpanc_app.entrypoints=web"
      - "traefik.http.routers.qpanc_app.service=qpanc_app"
      - "traefik.http.routers.qpanc_app-secure.rule=Host(`your_domain.com`)"
      - "traefik.http.routers.qpanc_app-secure.tls=true"
      - "traefik.http.routers.qpanc_app-secure.tls.certresolver=le"
      - "traefik.http.routers.qpanc_app-secure.entrypoints=websecure"
      - "traefik.http.routers.qpanc_app-secure.service=qpanc_app"
      - "traefik.docker.network=external_network"

  qpanc.database:
    restart: always
    image: postgres:latest
    ports:
      - "34514:5432"
    volumes:
      - database:/var/lib/postgresql/database
    networks:
      qpanc.network:
      qpanc.internal:
        ipv4_address: "172.18.18.9"
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: keepitsupersecret
      POSTGRES_DB: postgres

  traefik:
    container_name: traefik
    image: traefik:latest
    depends_on:
      - qpanc.app
      - qpanc.api
    networks:
      qpanc.network:
      qpanc.internal:
        ipv4_address: "172.18.18.12"
    command:
      - "--api=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.traefik.address=:8080"
      - "--certificatesResolvers.le.acme.email=your_email@provider.com"
      - "--certificatesResolvers.le.acme.storage=acme.json"
      - "--certificatesResolvers.le.acme.tlsChallenge=true"
      - "--certificatesResolvers.le.acme.httpChallenge=true"
      - "--certificatesResolvers.le.acme.httpChallenge.entryPoint=web"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data/acme.json:/acme.json
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.rule=Host(`traefik.your_domain.com`)"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.middlewares=admin"
      - "traefik.http.routers.traefik.tls.certresolver=le"
      - "traefik.http.routers.traefik.entrypoints=websecure"
      - "traefik.http.middlewares.admin.basicauth.users=qpanc:$$apr1$$U0UpF78N$$3AxgB876rR09fJ5OuylKk/"

volumes:
  webapp:
  database:

networks:
  qpanc.internal:
    internal: true
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.18.18.0/24
  qpanc.network:
```

Não esqueça de atualizar o label `traefik.http.middlewares.admin.basicauth.users`, afinal, você não vai querer usar a senha `exposed`

Ele é basicamente a combinação do `QPANC/docker-compose.yml` e do `QPANC/docker-compose.production.yml`, porém sem a parte do `build`.

A outra diferença, é que agora estamos a configurar o `traefik`, é ele que irá receber todas as requisições e transferir para o serviço apropriado.

Por exemplo, as requisições feitas para o host `traefik.your_domain.com` serão redirecionadas para o painel do traefik. as feitas ao host `api.your_domain.com` irão para à `API` e por fim, as feitas para `qpanc.your_domain.com` para o app feito usando o Quasar.

Outro ponto importante, é que `traefik` é responsavel por configurar o `SSL`, gerenciando a integração com o `Let's Encrypt`. porém, precisamos de um domínio valido para isto.

Dado estas informações, conecte à `VM` usando o `SSH`, crie o arquivo `data/acme.json`, e modifique o seu nível de acesso para 600:

```
mkdir data
cd data
> acme.json
touch acme.json
chmod 600 acme.json
cd ..
```

Agora, vamos criar o aquivo `docker-compose.yml`:

```
sensible-editor docker-compose.yml
```

Caso pergunte qual é o editor da sua preferencia, na duvida escolha o nano.
Então, copie o conteúdo do `docker-compose` acima, apenas lembre-se de alterar o `your_mail@provider.com` para o seu email e `your_domain.com` para o endereço da aplicação.

Após salvar o `docker-compose.yml`, precisamos garantir que o `docker-compose up` será executado sempre que a `VM` for inicializada:

```
sudo systemctl enable docker
```

E antes de podemos levantar os nossos serviços, precisamos logar no `docker` usando uma conta que possa baixar as imagens:

```
docker login -u ${username} -p ${password} ${login_server}
```

no meu caso:

```
docker login -u qpanc -p ************************ qpanc.azurecr.io
```

E agora levante os serviços

```
sudo docker-compose up -d
```

Caso precise atualizar os serviços, podemos executar um script como o seguinte:

```sh
sudo docker-compose down
sudo docker pull qpanc.azurecr.io/api:latest
sudo docker pull qpanc.azurecr.io/app:latest
sudo docker-compose up -d
```