QPANC - Parte 19 - Docker - Registro e Build
Tags: quasar, postgres, aspnetcore, docker
Published: 2020-04-19 23:39:31

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

##38 Criando um Container Registry no Azure.

para podemos continuar, iremos precisar de um `Container Registry`, novamente, você pode usar qual quer provedor, como por exemplo, o [Docker Hub](https://hub.docker.com) porém estarei criando um no azure.

Então comece o processo para adicionar um novo recurso, e busque por `Container Registry`:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/m13nctj9xx6eauasjgmd.png)

É interessante que o `Container Registry` use o mesmo grupo de recursos e esteja localizado na mesma região que a `VM`, assim como estaremos ativando o usuário `admin`, e como estamos criando este registro apenas para testes, use o `SKU` Basic.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/gts9mw9vcgggf3xp9ryp.png)

Agora à confirmação da criação do registro, precisamos esperar alguns instantes, até que o azure configure tudo.

Por fim, vá até a guia `Access Keys` e copie o nome do `Login server`, `username` e o `password`.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/xtr0ipaimxofh39r9djy.png)

Agora, temos um registro para onde podemos enviar as nossas imagens.

##39 Fazendo o Build para produção

Antes de realizamos o `build` para produção, precisamos desativar o redirecionamento `HTTPS` da `API`, pois este procedimento será feito por outro serviço, o traefik.

então, no `docker-compose.yml` remova qual quer referencia à porta `443`.

```
- "34513:443" => // remova completamente esta linha
- ASPNETCORE_URLS=http://+:443;http://+:80 => - ASPNETCORE_URLS=;http://+:80
```

E no QPANC.Api/Startup.cs, remova a seguinte linha:

```
app.UseHttpsRedirection();
```

Então, faça uma copia do `docker-compose.override.yml` e renomeie ela para `docker-compose.production.yml`.

**QPANC/docker-compose.production.yml**
```yml
version: '3.4'

services:
  qpanc.api:
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
      - ASPNETCORE_URLS=https://+:443;http://+:80
      - DEFAULT_CONNECTION=Server=qpanc.database;Port=5432;Database=postgres;User Id=postgres;Password=keepitsupersecret;
      - JWTBEARER_VALIDISSUER=https://api.qpanc.tobiasmesquita.dev/
      - JWTBEARER_VALIDAUDIENCE=https://api.qpanc.tobiasmesquita.dev/
      - JWTBEARER_ISSUERSIGNINGKEY=itUXC7iVRsofSDWNeg/aLYpc4bMzHAsMPzeItE1PQi2tMK2f4t0InRgTE5B/4IAjhAX5LQSIGL1CaUHSSzED8A==
      - JWTBEARER_TOKENDECRYPTIONKEY=7hfboHG0d4GnXjVng0ukMo+IgrKKrPLUMtOvnt4S514=
      - CORS_HOSTS__0=qpanc.tobiasmesquita.dev
    ports:
      - "34512:80"
      - "34513:443"
    volumes:
      - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
      - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro

  qpanc.app:
    container_name: qpanc_app_prod
    build:
      context: ./QPANC.App
      target: 'prod-stage'
      dockerfile: .docker/prod.Dockerfile
    volumes:
      - app:/app
    ports:
      - "34514:3000"

  qpanc.database:
    volumes:
      - database:/var/lib/postgresql/database
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: keepitsupersecret
      POSTGRES_DB: postgres

volumes:
  app:
  database:
```

No service `qpanc.api` nós alteramos o `environment`, adicionando algumas variáveis de ambiente e modificando outras: `ASPNETCORE_ENVIRONMENT`, `JWTBEARER_VALIDISSUER`, `JWTBEARER_VALIDAUDIENCE` e `CORS_HOSTS__0`.

No service `qpanc.app`, temos mais alterações, a primeira é o nome do contêiner em `container_name: qpanc_app_prod`, no caso do build, estamos usando um outro `Dockerfile`, nos `volumes`, `app` vai está apontando para um volume interno, na porta, estaremos usando a porta `3000` ao invés de `8080`, assim como, foi removido o `commands`.

Por fim, o `qpanc.database` teve alterações menos relevantes, como o `volumes` e o `container_name`.

O próximo passo, é preparar o `prod.Dockerfile`

**QPANC.App/.docker/prod.Dockerfile**
```docker
# develop stage
FROM node:12.16-alpine as develop-stage
WORKDIR /app/source
COPY package*.json ./
RUN npm i -g @quasar/cli@latest
COPY . .

# local-deps
FROM develop-stage as local-deps-stage
RUN ls
RUN rm -r -f .quasar
RUN rm -r -f dist
RUN rm -r -f node_moduless
RUN rm -f yarn.lock
RUN yarn

# build stage
FROM local-deps-stage as build-stage
ENV API_CLIENT_URL=https://api.qpanc.tobiasmesquita.dev/
ENV API_SERVER_URL=https://api.qpanc.tobiasmesquita.dev/
RUN quasar build -m ssr

# prod stage
FROM build-stage as prod-stage
WORKDIR /app/source/dist/ssr
RUN mv * ../../../
WORKDIR /app
RUN rm -r -f source
RUN yarn
CMD ["node", "index.js"]
```

Basicamente, estamos copiando o `source`, apagando `node_moduless`, `dist`, `locks`, e baixamos novamente, então é feito o build, copiamos os arquivos do build para a raiz, por fim apagamos o `source`

Agora, execute o seguinte comando.:

```
docker-compose -f docker-compose.yml -f docker-compose.production.yml build
docker image ls -a
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/lebk122zcd7ubhcztswt.png)

Vai levar alguns longos segundos, para que o build do app e da api seja realizado, então devemos anotar o ID das imagens, no meu caso `516a0d428a28`para a `api` e `eb3ec1b5548e` para o `app`.

Então, execute o seguinte comando para o `app` e para a `api`, para que consigamos criar as suas respectivas tags.

```
docker tag {image} {registry_name}/{container_name}:{tag_name}
```

no meu caso:

```
docker tag 516a0d428a28 qpanc.azurecr.io/api:latest
docker tag eb3ec1b5548e qpanc.azurecr.io/app:latest
docker image ls -a
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/l84dhj7zf3ymnopawc79.png)

Agora que criamos as nossas imagens e as suas respectivas tags, precisamos subir relas para o `container`, para que isto seja possível, teremos de logar no `docker` usando uma conta com permissão:

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

no meu caso

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

agora que efetuamos o login, podemos fazer o `push` das imagens, então execute o seguinte comando, tanto para o `app` como para a `api`.

```
docker push {registry_name}/{container_name}:{tag_name}
```

no meu caso

```
docker push qpanc.azurecr.io/api:latest
docker push qpanc.azurecr.io/app:latest
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/lc42x9kk8fqny34lbk40.png)

Feito isto, as imagens já estão disponíveis, já podemos ser acessadas a partir da `VM`

Caso tenha feito o upload para um Registro criado no portal do Azure, eles vão ser listados da seguinte forma:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/fgh13vemat4xxmn948im.png)

Note que `latest` é o valor `default` para as `tags`, porém é interessante, que a cada publicação seja criado uma nova `tag`, como por exemplo `1.0.0`, `1.0.1` ou `1.1.0`, e a `latest` deverá ser apenas um `alias` para a mais recente.

Por fim, deixo um script que fazer a limpeza dos containers/imagens, faz o build, cria as tags e realiza o upload. Porém que fique claro, que esta solução é um tanto quanto drástica.

```sh
docker container stop $(docker container ls -aq)
docker container rm $(docker container ls -aq)
docker image rm $(docker image ls -aq) -f
docker-compose -f docker-compose.yml -f docker-compose.production.yml build --no-cache --force-rm --compress
docker tag $(docker image ls -f=reference="qpancapi" -q) qpanc.azurecr.io/api:latest
docker tag $(docker image ls -f=reference="qpancapp" -q) qpanc.azurecr.io/app:latest
docker push qpanc.azurecr.io/api:latest
docker push qpanc.azurecr.io/app:latest
```