404 Not Found

404 Not Found


nginx

Implantação com Contêineres Docker

Docker é uma revolução na implantação — construa uma vez, execute em qualquer lugar e diga adeus à desculpa "funciona na minha máquina".

1. O Que Você Vai Aprender


2. Uma História Real de um Engenheiro de Operações

(1) Dor: Ambiente Inconsistente

Depois que Bob terminou de depurar o OrderFlow localmente e o implantou em produção, o serviço falhou ao iniciar devido a versões incompatíveis do driver MySQL, versões inconsistentes do JDK e configurações de fuso horário diferentes. Cada implantação exigia meio dia para solucionar discrepâncias de ambiente, e "Funciona na minha máquina" tornou-se o lema da equipe. Para piorar, os três servidores exigiam três implantações manuais separadas, e configurações eram frequentemente esquecidas.

(2) A Solução Docker

O Docker empacota a aplicação e todas as suas dependências em uma única imagem:

DOCKERFILE
FROM eclipse-temurin:17-jre-alpine
COPY target/orderflow-service.jar /app/app.jar
ENTRYPOINT ["java", "-jar", "/app/app.jar"]

Implante com um único comando, garantindo um ambiente completamente consistente.

(3) Resultado

Depois que Bob começou a usar Docker, a imagem era construída uma vez localmente, e todos os três servidores faziam pull e executavam a partir da mesma fonte, eliminando inconsistências de ambiente. Um único comando do Docker Compose inicia o ambiente completo — OrderFlow, MySQL e Redis — e novos funcionários podem executá-lo localmente em apenas cinco minutos.


3. Dockerfile Multi-stage

(1) Processo de Build Multi-stage

100%
graph TD
    A["Estágio 1: Builder<br/>Maven + JDK 17<br/>Compilar + Empacotar"] --> B["orderflow-service.jar"]
    B --> C["Estágio 2: Runtime<br/>JRE 17 Alpine<br/>Copiar apenas o JAR"]
    C --> D["Imagem Final<br/>~150MB"]

(1) ▶ Exemplo: Dockerfile Multi-stage

DOCKERFILE
# Estágio 1: Build
FROM maven:3.9-eclipse-temurin-17 AS builder
WORKDIR /build

# Copiar pom.xml primeiro para cache de dependências
COPY pom.xml .
RUN mvn dependency:go-offline -B

# Copiar código-fonte e construir
COPY src ./src
RUN mvn package -DskipTests -B

# Estágio 2: Runtime
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app

# Criar usuário não-root
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

# Copiar JAR do builder
COPY --from=builder /build/target/*.jar app.jar

# Definir propriedade
RUN chown -R appuser:appgroup /app
USER appuser

# Expor porta
EXPOSE 8080

# Health check
HEALTHCHECK --interval=30s --timeout=3s \
  CMD wget -qO- http://localhost:8080/actuator/health || exit 1

# Executar aplicação
ENTRYPOINT ["java", \
  "-XX:+UseG1GC", \
  "-XX:MaxRAMPercentage=75.0", \
  "-jar", "app.jar"]

Saída:

TEXT
// Execução bem-sucedida
Imagem Base Tamanho Segurança Casos de Uso
eclipse-temurin:17 ~450MB Média Desenvolvimento/Testes
eclipse-temurin:17-jre-alpine ~170MB Média-Alta Recomendada para Produção
gcr.io/distroless/java17-debian12 ~100MB Máxima Segurança Extrema

(2) ▶ Exemplo: Imagem Distroless

DOCKERFILE
# Estágio 1: Build
FROM maven:3.9-eclipse-temurin-17 AS builder
WORKDIR /build
COPY pom.xml .
RUN mvn dependency:go-offline -B
COPY src ./src
RUN mvn package -DskipTests -B

# Estágio 2: Runtime Distroless
FROM gcr.io/distroless/java17-debian12
COPY --from=builder /build/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

Saída:

TEXT
// Execução bem-sucedida
💡 Dica: Imagens Distroless não possuem shell (sem sh/bash), então você não pode usar docker exec -it para entrar no modo de depuração. Elas são recomendadas para produção, mas use a imagem Alpine para depuração.


4. .dockerignore e Otimização de Imagem

(1) ▶ Exemplo: .dockerignore

TEXT
# .dockerignore
.git
.github
.idea
*.md
target/
!target/*.jar
node_modules/
*.log
.env
docker-compose*.yml
Dockerfile*
Estratégia de Otimização Efeito Descrição
.dockerignore Excluir arquivos desnecessários Reduz o contexto de build Não enviar .git, .idea, etc.
Primeiro, COPY pom.xml Cachear dependências Pular download se dependências não mudaram
Build multi-stage Reduz o tamanho final da imagem Não inclui Maven ou código-fonte
JRE em vez de JDK Economiza ~200MB Não requer ferramentas de compilação em runtime
Imagem Base Alpine Reduzido em ~280MB Um sistema Linux mínimo usando musl libc

5. Orquestração Multi-Serviço com Docker Compose

(1) ▶ Exemplo: OrderFlow + MySQL + Redis

YAML
# docker-compose.yml
version: "3.9"

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    environment:
      SPRING_PROFILES_ACTIVE: prod
      DB_HOST: mysql
      DB_USERNAME: orderflow
      DB_PASSWORD: ${DB_PASSWORD:-orderflow123}
      REDIS_HOST: redis
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:8080/actuator/health"]
      interval: 30s
      timeout: 3s
      retries: 5
    restart: unless-stopped

  mysql:
    image: mysql:8.0
    ports:
      - "3306:3306"
    environment:
      MYSQL_DATABASE: orderflow
      MYSQL_USER: orderflow
      MYSQL_PASSWORD: ${DB_PASSWORD:-orderflow123}
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-root123}
    volumes:
      - mysql-data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 10

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 5

volumes:
  mysql-data:
  redis-data:

Saída:

TEXT
CONTAINER ID   IMAGE          STATUS         PORTS
abc123         nginx:latest   Up 2 hours     0.0.0.0:80->80/tcp

(2) ▶ Exemplo: Inicialização e Verificação

BASH
# Construir e iniciar todos os serviços
docker compose up -d --build

# Verificar status dos serviços
docker compose ps

# Visualizar logs da aplicação
docker compose logs -f app

# Testar API
curl http://localhost:8080/actuator/health

# Parar todos os serviços
docker compose down -v

Saída:

TEXT
CONTAINER ID   IMAGE     STATUS    
abc123         latest    Up 2 hours
Comando Descrição
docker compose up -d Iniciar em segundo plano
docker compose down Parar e remover contêineres
docker compose logs -f app Visualizar logs da aplicação
docker compose ps Verificar status dos serviços
docker compose build Apenas construir a imagem

6. Injeção de Variáveis de Ambiente

(1) ▶ Exemplo: Externalizando Configuração

YAML
# application-prod.yml (na imagem Docker)
spring:
  datasource:
    url: jdbc:mysql://${DB_HOST:localhost}:3306/orderflow
    username: ${DB_USERNAME:orderflow}
    password: ${DB_PASSWORD:defaultpass}
  data:
    redis:
      host: ${REDIS_HOST:localhost}
      port: ${REDIS_PORT:6379}
Método de Configuração Prioridade Cenários Aplicáveis
Docker Compose environment Alta Implantação Simplificada
Arquivo .env Média Desenvolvimento Local
K8s ConfigMap / Secret Alta Produção
TEXT
# arquivo .env
DB_PASSWORD=secure_password_here
DB_ROOT_PASSWORD=root_secure_here
REDIS_PASSWORD=redis_secure_here

7. Exemplo Completo: Dockerização Completa do OrderFlow

DOCKERFILE
# Dockerfile
FROM maven:3.9-eclipse-temurin-17 AS builder
WORKDIR /build
COPY pom.xml .
RUN mvn dependency:go-offline -B
COPY src ./src
RUN mvn package -DskipTests -B

FROM eclipse-temurin:17-jre-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY --from=builder /build/target/*.jar app.jar
RUN chown -R appuser:appgroup /app
USER appuser
EXPOSE 8080 8081
HEALTHCHECK --interval=30s --timeout=3s \
  CMD wget -qO- http://localhost:8080/actuator/health || exit 1
ENTRYPOINT ["java", "-XX:+UseG1GC", "-XX:MaxRAMPercentage=75.0", "-jar", "app.jar"]
YAML
# docker-compose.yml
version: "3.9"
services:
  app:
    build: .
    ports:
      - "8080:8080"
      - "8081:8081"
    environment:
      SPRING_PROFILES_ACTIVE: prod
      DB_HOST: mysql
      DB_USERNAME: orderflow
      DB_PASSWORD: ${DB_PASSWORD:-orderflow123}
      REDIS_HOST: redis
      MANAGEMENT_SERVER_PORT: "8081"
    depends_on:
      mysql: { condition: service_healthy }
      redis: { condition: service_healthy }
    restart: unless-stopped

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_DATABASE: orderflow
      MYSQL_USER: orderflow
      MYSQL_PASSWORD: ${DB_PASSWORD:-orderflow123}
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-root123}
    volumes: [mysql-data:/var/lib/mysql]
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s; timeout: 5s; retries: 10

  redis:
    image: redis:7-alpine
    volumes: [redis-data:/data]
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s; timeout: 3s; retries: 5

volumes:
  mysql-data:
  redis-data:

❓ Perguntas Frequentes

P Por que as imagens Docker são tão grandes?
R Por padrão, a imagem completa do JDK é usada (~450MB). Métodos de otimização: 1) Usar JRE em vez de JDK (~170MB); 2) Usar a imagem base Alpine; 3) Usar Distroless (~100MB); 4) Usar a imagem nativa GraalVM (~50MB).
P Como depurar uma aplicação em um contêiner Docker?
R 1) docker compose logs -f app para visualizar logs; 2) docker compose exec app sh para entrar no contêiner (imagem Alpine); 3) Depuração remota: ENTRYPOINT ["java", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005", "-jar", "app.jar"].
P Qual a relação entre depends_on e healthcheck?
R depends_on apenas garante a ordem de inicialização dos contêineres; não garante que o serviço esteja pronto. Quando usado em conjunto com condition: service_healthy, o Docker Compose aguardará o health check passar antes de iniciar o serviço dependente.
P Como posso reduzir o tempo de build da imagem?
R 1) Primeiro, copie o pom.xml e execute mvn dependency:go-offline para aproveitar o cache de camadas do Docker; 2) Use .dockerignore para excluir arquivos irrelevantes; 3) Use montagem de cache do BuildKit.
P O Docker Compose pode ser usado em produção?
R O Docker Compose é adequado para desenvolvimento local e implantações simples. Para ambientes de produção, recomendamos Docker Swarm ou Kubernetes, que oferecem recursos como auto-scaling, rolling updates e self-healing.
P Quais são as armadilhas da imagem Alpine?
R 1) Ela usa musl libc em vez de glibc, então algumas bibliotecas nativas podem ser incompatíveis; 2) Dados de fuso horário requerem instalação adicional; 3) Resolução DNS tem um bug sob alta concorrência (problema ndots). Alpine é recomendada para cenários com apenas JRE.

📖 Resumo


📝 Exercícios

  1. Exercício Básico (Dificuldade ⭐): Escreva um Dockerfile para o OrderFlow, construa a imagem, execute localmente e verifique que /actuator/health retorna "UP."

  2. Exercício Avançado (Dificuldade: ⭐⭐): Escreva um arquivo docker-compose.yml para orquestrar os três serviços — OrderFlow, MySQL e Redis — e configure healthcheck e depends_on para garantir que os serviços iniciem na ordem correta.

  3. Desafio (Dificuldade: ⭐⭐⭐): Otimize a imagem para menos de 150 MB, use a imagem base Distroless, configure os parâmetros de memória da JVM (MaxRAMPercentage) e adicione um usuário não-root e configurações relacionadas à segurança.

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%