Skip to main content

Padrão de DevOps: Docker & GitLab CI/CD

Status: Aprovado Área: Arquitetura / DevOps Domínio Relacionado: (N/A)


1. Visão Geral

Este documento define o padrão para empacotamento, publicação e implantação da documentação do CRM utilizando Docker, Docker Compose e pipelines automatizados do GitLab CI/CD.

A arquitetura do deploy baseia-se em build de dois estágios (multi-stage) e na disponibilização de um servidor web otimizado (Nginx) para servir o conteúdo estático produzido pelo Docusaurus.


2. Dockerfile (Build Multi-Stage)

O processo de compilação da imagem Docker isola as dependências de build e runtime.

# Stage 1: Build estático com Node.js
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: Servidor estático com Nginx
FROM nginx:1.25-alpine AS runner
COPY --from=builder /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80

Regras do Dockerfile:

  1. Segurança: Utilização de imagens base alpine leves e com superfície de ataque reduzida.
  2. Performance: A instalação de dependências utiliza npm ci para garantir reprodutibilidade baseando-se estritamente no package-lock.json.
  3. Isolamento: Nenhum código-fonte ou ferramenta de compilação (como compiladores Node e TypeScript) é exposto na imagem final de runtime, que contém apenas o binário do Nginx e os arquivos estáticos compilados.

3. Configuração do Servidor Web (Nginx)

O arquivo nginx.conf é injetado no container de runtime e deve respeitar as seguintes diretrizes de performance e segurança:

  • Compressão Gzip: Ativada para reduzir o consumo de banda de rede de arquivos texto, JS e CSS.
  • Cache-Control: Headers de cache longo (30 dias) aplicados dinamicamente para arquivos estáticos (.js, .css, imagens, fontes).
  • SPA/Docusaurus routing: Fallback com try_files para garantir roteamento limpo de páginas.
  • Segurança (Headers HTTP): Injeção obrigatória dos cabeçalhos:
    • X-Frame-Options: SAMEORIGIN (prevenção contra clickjacking)
    • X-Content-Type-Options: nosniff (prevenção contra sniffing de mime-types)
    • X-XSS-Protection: 1; mode=block (bloqueio de scripts cross-site)

4. Pipeline do GitLab CI/CD

A pipeline de CI/CD está documentada no arquivo .gitlab-ci.yml na raiz do projeto e segue as seguintes políticas de governança:

Estágios da Pipeline

  • build-and-publish: Job único responsável por realizar o build e fazer o push das imagens de forma otimizada.

Políticas de Tagging (Publicação de Imagens)

O sistema publica tags no GitLab Container Registry baseado na branch de origem:

  1. Branch Padrão (Produção): Commits na branch principal geram duas tags no registry:
    • :latest (aponta para a versão estável de produção mais recente).
    • :sha-$CI_COMMIT_SHORT_SHA (identificador único imutável do commit de build).
  2. Outras Branches (Desenvolvimento): Commits em branches paralelas publicam tags com o padrão:
    • :branch-$CI_COMMIT_REF_SLUG (ex: :branch-feature-dashboard).
    • :sha-$CI_COMMIT_SHORT_SHA.

Mecanismo de Cache

O pipeline puxa a imagem :latest existente antes do build (docker pull ... || true) e a utiliza como parâmetro --cache-from no Docker build, acelerando a pipeline ao evitar reinstalação de dependências do Node que não sofreram alterações.


5. Docker Compose (Integração com Traefik Proxy)

Para subir o serviço na VPS junto com o proxy reverso e gerenciador de SSL (Traefik), utiliza-se a seguinte estrutura no docker-compose.yml:

services:
# Serviço do Traefik: Proxy Reverso e SSL Automático
traefik:
image: traefik:latest
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
environment:
- DOCKER_API_VERSION=1.40
command:
- "--global.checknewversion=false"
- "--global.sendanonymoususage=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
- "--certificatesresolvers.letsencrypt.acme.email=admin@guardiansystem.com.br"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./letsencrypt:/letsencrypt"
networks:
- traefik_proxy

# Serviço da Documentação do CRM
crm-docs:
image: "vulcano.guardiansystem.com.br/guardian-system/crm:latest"
container_name: crm-portal-docs
restart: unless-stopped
expose:
- "80"

networks:
- traefik_proxy

labels:
- "traefik.enable=true"
- "traefik.http.routers.crm-docs.rule=Host(`crm.oryon.api.br`)"
- "traefik.http.routers.crm-docs.entrypoints=websecure"
- "traefik.http.routers.crm-docs.tls=true"
- "traefik.http.routers.crm-docs.tls.certresolver=letsencrypt"
- "traefik.http.services.crm-docs.loadbalancer.server.port=80"

deploy:
resources:
limits:
cpus: '0.50'
memory: 256M
reservations:
cpus: '0.10'
memory: 64M
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

networks:
traefik_proxy:
external: true

Diretrizes do Compose:

  • Segurança de Rede: O container não publica portas diretamente na interface do host (ports: ... omitido). A comunicação é feita exclusivamente via rede privada Docker virtual traefik_proxy.
  • Orquestração e Descoberta: O Traefik faz a autodescoberta do container e mapeia o tráfego da porta 80 interna do container para a rota HTTPS baseada nos labels injetados.
  • Limites de Recursos: Impõe limites rígidos de CPU (50% de um núcleo) e Memória (256MB) para garantir resiliência de infraestrutura em ambientes compartilhados.
  • Rotação de Logs: Configuração obrigatória de limites de tamanho (max-size: 10m e max-file: 3) para evitar o esgotamento de espaço em disco no servidor.

Para garantir que a documentação possa ser lida e pesquisada em ambientes de VPS privados, redes locais ou VPNs sem depender de indexadores externos baseados na nuvem (como Algolia DocSearch), o projeto utiliza a busca local offline via plugin @easyops-cn/docusaurus-search-local.

Características da Configuração:

  • Indexação Estática: O índice de palavras-chave é gerado de forma totalmente estática e otimizada durante a compilação do projeto (npm run build).
  • Suporte a Idiomas: Configurado para indexar e realizar pesquisas eficientes em Português (pt) e Inglês (en).
  • UX (User Experience): Habilita destaque visual de termos buscados ao abrir a página correspondente (highlightSearchTermsOnTargetPage: true) e adiciona a trilha hierárquica nos resultados da pesquisa (explicitSearchResultPath: true).