Post

Guia Completo para Docker Compose: Criação e Orquestração de Aplicações Multi-Containers

Guia Completo para Docker Compose: Criação e Orquestração de Aplicações Multi-Containers

Introdução Geral

O Docker Compose é uma ferramenta essencial para o desenvolvimento e a operação de aplicações multi-containers. Projetado para simplificar a orquestração e o gerenciamento de containers, o Docker Compose permite que você defina, configure e execute todos os serviços necessários para sua aplicação em um único arquivo docker-compose.yml. Esse recurso é especialmente valioso em ambientes de desenvolvimento e produção, onde diferentes componentes de uma aplicação — como servidores web, bancos de dados e sistemas de cache — precisam trabalhar em conjunto.

Este tutorial aborda o Docker Compose de forma completa e detalhada, desde a instalação e configuração inicial até práticas avançadas para escalonamento, persistência de dados e deploy em produção. Ao final, você terá o conhecimento necessário para configurar ambientes multi-containers robustos e seguros, seja para desenvolvimento, testes ou produção.


Sumário

  1. Introdução ao Docker Compose
  2. Instalação e Configuração do Docker Compose
  3. Estrutura do Arquivo docker-compose.yml
  4. Configurando Serviços e Containers
  5. Configurando Volumes para Persistência de Dados
  6. Configurando Redes e Comunicação entre Serviços
  7. Comandos Essenciais do Docker Compose
  8. Variáveis de Ambiente e .env no Docker Compose
  9. Build de Imagens Customizadas com Docker Compose
  10. Escalando Serviços com Docker Compose
  11. Saúde e Monitoramento de Containers com Healthchecks
  12. Usando Dependências de Inicialização e Ordem de Inicialização
  13. Práticas de Deploy em Produção com Docker Compose
  14. Executando Comandos em Containers com Docker Compose
  15. Troubleshooting e Solução de Problemas Comuns

1. Introdução ao Docker Compose

Objetivo

Apresentar o que é o Docker Compose, suas principais vantagens para orquestração de containers, e como ele se diferencia do Docker CLI.

Conteúdo

  • O que é o Docker Compose?
  • Benefícios do Docker Compose para aplicações multi-containers
  • Cenários ideais para uso do Docker Compose

O que é o Docker Compose?

O Docker Compose é uma ferramenta que permite definir e gerenciar ambientes com múltiplos containers Docker de forma declarativa. Com o Compose, você define os serviços, volumes, redes e outras configurações necessárias em um arquivo docker-compose.yml, permitindo que todos os containers de uma aplicação sejam iniciados com um único comando.

Em vez de criar e configurar containers individualmente, o Compose simplifica o processo, sendo uma excelente ferramenta para gerenciar aplicações multi-containers, como uma aplicação web com um banco de dados e um serviço de cache.

Diferença entre Docker CLI e Docker Compose

Docker CLI Docker Compose
Gerencia containers individualmente Orquestra múltiplos containers simultaneamente
Usado para comandos específicos (docker run, docker build) Usa um arquivo docker-compose.yml para definir toda a infraestrutura de containers
Focado em operações de um container por vez Ideal para arquiteturas com vários serviços integrados

Benefícios do Docker Compose para Aplicações Multi-Containers

  1. Configuração Centralizada: O Compose permite definir todos os aspectos da infraestrutura (serviços, volumes, redes) em um único arquivo docker-compose.yml, simplificando o gerenciamento e a versão do ambiente.
  2. Orquestração de Múltiplos Serviços: Ideal para arquiteturas baseadas em microsserviços, o Docker Compose facilita o desenvolvimento, teste e orquestração de vários serviços interdependentes.
  3. Automação e Consistência: O Compose assegura que o ambiente configurado seja o mesmo em diferentes estágios de desenvolvimento (ex. desenvolvimento, teste e produção), promovendo consistência e simplificando o processo de automação.
  4. Escalabilidade: Docker Compose permite escalar serviços horizontalmente com facilidade, tornando-o uma boa escolha para projetos que exigem aumento da capacidade de processamento com apenas alguns comandos.

Exemplos de Cenários Onde o Docker Compose é Ideal

  1. Desenvolvimento de Aplicações Web com Backend Completo: Com o Docker Compose, uma aplicação web pode ser desenvolvida junto a seus serviços necessários, como um banco de dados (MySQL, PostgreSQL), um serviço de cache (Redis) e uma API REST.

  2. Testes Automatizados de Sistemas Complexos: O Compose permite configurar ambientes complexos com bancos de dados e serviços externos, mantendo consistência em testes automatizados.

  3. Ambientes de Desenvolvimento Local Replicáveis: O Compose é amplamente usado para criar ambientes de desenvolvimento local que são uma réplica precisa dos ambientes de produção, o que ajuda a evitar problemas de configuração ao mover o código para produção.

  4. Orquestração de Aplicações Baseadas em Microsserviços: Para arquiteturas baseadas em microsserviços, o Compose facilita o gerenciamento de serviços interdependentes, garantindo que todos os containers estejam disponíveis e funcionando em conjunto.


2. Instalação e Configuração do Docker Compose

Objetivo

Ensinar como instalar e configurar o Docker Compose em diferentes sistemas operacionais, além de garantir que a versão esteja atualizada e pronta para uso em desenvolvimento e produção.

Conteúdo

  • Instalação do Docker Compose no Linux, Windows e Mac
  • Verificação da Instalação
  • Requisitos e Atualizações

Instalação do Docker Compose

O Docker Compose é uma ferramenta separada do Docker, mas frequentemente incluída no pacote de instalação principal do Docker Desktop para Windows e Mac. Para o Linux, pode ser necessário instalá-lo manualmente.

1. Instalação no Linux

No Linux, o Docker Compose pode ser instalado diretamente via linha de comando. Confira as instruções a seguir:

1
2
3
4
5
6
7
8
# Baixar a versão mais recente do Docker Compose (confirme a versão em https://github.com/docker/compose/releases)
sudo curl -L "https://github.com/docker/compose/releases/download/v2.10.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# Dar permissão de execução ao binário do Docker Compose
sudo chmod +x /usr/local/bin/docker-compose

# Verificar se a instalação foi bem-sucedida
docker-compose --version

Nota: Certifique-se de substituir v2.10.2 pela versão mais recente disponível.

2. Instalação no Windows e Mac

Para Windows e Mac, o Docker Compose é normalmente incluído no Docker Desktop. Siga os passos abaixo para garantir que o Docker Compose está disponível:

  1. Baixar Docker Desktop: Acesse o site oficial do Docker Desktop e faça o download para o seu sistema operacional.
  2. Instalação: Siga o assistente de instalação. Durante o processo, o Docker Desktop instalará automaticamente o Docker Compose.
  3. Verificação da Instalação: Após a instalação, abra um terminal e execute o comando:

    1
    
    docker-compose --version
    

Se o comando exibir a versão, o Docker Compose está pronto para uso.


Verificação da Instalação

Após instalar o Docker Compose, execute o seguinte comando para garantir que a instalação foi bem-sucedida:

1
docker-compose --version

A saída deve ser semelhante a:

1
Docker Compose version v2.10.2

Se a versão for exibida, significa que o Docker Compose está instalado corretamente e pronto para configurar e gerenciar aplicações multi-containers.


Requisitos e Atualizações

Requisitos de Sistema

  • Docker: O Docker Compose depende do Docker, então é necessário ter o Docker instalado e funcionando antes de usar o Compose.
  • Permissões de Administrador: Para instalar e configurar o Docker Compose no Linux, você precisará de permissões de superusuário.

Atualização do Docker Compose

Para garantir que você tenha a versão mais recente com os últimos recursos e correções de segurança, é importante atualizar o Docker Compose regularmente.

Passos para Atualização no Linux:

  1. Remova a versão antiga (opcional):
    1
    
    sudo rm /usr/local/bin/docker-compose
    
  2. Reinstale a versão mais recente, repetindo o processo de instalação acima.

Atualização no Docker Desktop (Windows e Mac): No Windows e Mac, o Docker Compose é atualizado automaticamente junto com o Docker Desktop. Para verificar se há atualizações, acesse o Docker Desktop, vá até as configurações e verifique a seção de atualizações.


Resumo

Sistema Operacional Comando de Instalação Verificação de Versão
Linux sudo curl -L "https://github.com/docker/compose/releases/download/v<versao>/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose docker-compose --version
Windows Incluído com Docker Desktop. Baixe e instale o Docker Desktop a partir do site oficial. docker-compose --version
Mac Incluído com Docker Desktop. Baixe e instale o Docker Desktop a partir do site oficial. docker-compose --version

Conclusão

Com o Docker Compose instalado e configurado, você está pronto para começar a definir e orquestrar ambientes multi-containers. No próximo capítulo, Estrutura do Arquivo docker-compose.yml, vamos explorar a estrutura e as principais diretivas do arquivo docker-compose.yml, que é a base para configurar serviços no Docker Compose.


3. Estrutura do Arquivo docker-compose.yml

Objetivo

Apresentar a estrutura e as principais diretivas do arquivo docker-compose.yml, que é o centro da configuração de aplicações multi-containers com Docker Compose.

Conteúdo

  • Introdução às Diretivas do Arquivo docker-compose.yml
    • version
    • services
    • volumes
    • networks
  • Estruturação e Organização do Arquivo YAML
  • Exemplo Simples de Configuração com Dois Serviços

Introdução às Diretivas do Arquivo docker-compose.yml

O arquivo docker-compose.yml define todos os serviços, redes, volumes e outras configurações necessárias para rodar a aplicação. Abaixo estão as principais diretivas que compõem esse arquivo.

1. version

A diretiva version especifica a versão do formato de arquivo Compose. É importante escolher uma versão compatível com os recursos que você pretende usar e com a versão do Docker Compose instalada.

Exemplo:

1
version: '3.8'

As versões mais comuns são 3, 3.8 e 2. A versão 3.8 é recomendada, pois oferece suporte aos recursos mais recentes e é ideal para a maioria das aplicações modernas.

2. services

A seção services é onde você define cada container que a aplicação precisa. Para cada serviço, você especifica a imagem, portas, variáveis de ambiente, comandos e outras configurações.

Exemplo:

1
2
3
4
5
6
7
8
9
10
services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
  db:
    image: postgres:13
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password

No exemplo acima:

  • O serviço web usa a imagem nginx:alpine e expõe a porta 80.
  • O serviço db usa a imagem postgres:13 e define variáveis de ambiente para configurar o banco de dados.

3. volumes

A diretiva volumes é usada para definir volumes persistentes que serão montados nos containers, permitindo o armazenamento de dados entre reinicializações.

Exemplo:

1
2
volumes:
  db_data:

Ao definir um volume no nível principal do arquivo, você o torna acessível para qualquer serviço que precise de armazenamento persistente.

4. networks

A diretiva networks permite criar redes personalizadas para os serviços. Isso possibilita controlar a comunicação entre os containers e definir redes isoladas para segurança.

Exemplo:

1
2
3
networks:
  backend:
    driver: bridge

A criação de redes permite que você configure a comunicação entre containers de maneira mais segura e organizada, definindo regras de isolamento e acessibilidade.


Estruturação e Organização do Arquivo YAML

A estrutura YAML do docker-compose.yml é simples, mas é essencial manter a indentação correta para evitar erros. Seguir um padrão organizacional ajuda na leitura e manutenção do arquivo. Alguns pontos para estruturar melhor o arquivo incluem:

  • Definir version na primeira linha
  • Listar serviços principais e suas configurações logo após services
  • Separar volumes e networks na parte inferior

Exemplo Completo Estruturado:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"

  db:
    image: postgres:13
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    volumes:
      - db_data:/var/lib/postgresql/data

volumes:
  db_data:

networks:
  backend:
    driver: bridge

Exemplo Simples de Configuração com Dois Serviços

Aqui está um exemplo de um arquivo docker-compose.yml simples que define dois serviços, um servidor web e um banco de dados, e inclui configurações de volume e rede:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
version: '3.8'

services:
  app:
    image: myapp:latest
    ports:
      - "8080:8080"
    networks:
      - backend

  database:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: example
    volumes:
      - db_storage:/var/lib/mysql
    networks:
      - backend

volumes:
  db_storage:

networks:
  backend:
    driver: bridge

Neste exemplo:

  • O serviço app expõe a porta 8080 e se conecta à rede backend.
  • O serviço database usa a imagem mysql:5.7, define uma senha de root e monta o volume db_storage para persistência.
  • A rede backend conecta ambos os serviços, permitindo que eles se comuniquem diretamente.

Conclusão

Neste capítulo, exploramos a estrutura básica do arquivo docker-compose.yml e as principais diretivas usadas para definir os serviços, volumes e redes. No próximo capítulo, Configurando Serviços e Containers, veremos como configurar cada serviço individualmente dentro do docker-compose.yml, incluindo a definição de variáveis de ambiente, portas, comandos e mais.


4. Configurando Serviços e Containers

Objetivo

Demonstrar como configurar cada serviço individualmente dentro do docker-compose.yml, usando opções como image, build, ports, environment, entre outras, para personalizar containers.

Conteúdo

  • Definindo Containers em services
  • Configuração de Opções do Serviço
    • image
    • build
    • ports
    • environment
  • Exemplo Prático de Configuração com um Serviço Web e Banco de Dados

Definindo Containers em services

No Docker Compose, cada container é definido como um serviço na seção services do arquivo docker-compose.yml. Para cada serviço, podemos especificar uma série de configurações que determinam o comportamento e as características do container.

Configuração de Opções do Serviço

Abaixo estão algumas das principais opções de configuração de serviço que podem ser utilizadas:

1. image

A opção image define qual imagem Docker será usada para o serviço. Pode ser uma imagem oficial do Docker Hub ou uma imagem personalizada de um repositório privado.

Exemplo:

1
2
3
services:
  web:
    image: nginx:alpine

2. build

A opção build permite compilar uma imagem personalizada para o serviço diretamente com o Docker Compose, usando um diretório que contém um Dockerfile. Isso é útil quando você deseja construir imagens a partir de código-fonte e configurá-las com o Compose.

Exemplo:

1
2
3
4
5
services:
  app:
    build:
      context: ./app
      dockerfile: Dockerfile

No exemplo, o Docker Compose usará o Dockerfile localizado no diretório ./app para construir a imagem.

3. ports

A opção ports define quais portas serão expostas pelo container e como elas serão mapeadas para o host. O formato host:container é usado para mapear as portas.

Exemplo:

1
2
3
4
5
services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"

Neste exemplo, a porta 80 do container está mapeada para a porta 8080 do host.

4. environment

A opção environment permite definir variáveis de ambiente específicas para cada serviço. Isso é útil para configurar informações como credenciais, configurações de banco de dados e outros valores que podem variar entre diferentes ambientes.

Exemplo:

1
2
3
4
5
6
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: example_password
      MYSQL_DATABASE: example_db

Neste exemplo, as variáveis MYSQL_ROOT_PASSWORD e MYSQL_DATABASE configuram o serviço de banco de dados com a senha de root e o nome do banco.

Exemplo Prático de Configuração com um Serviço Web e Banco de Dados

Aqui está um exemplo de configuração docker-compose.yml que cria dois serviços: uma aplicação web e um banco de dados MySQL. Esse exemplo cobre as principais opções de configuração mencionadas.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
version: '3.8'

services:
  web:
    build:
      context: ./web
      dockerfile: Dockerfile
    ports:
      - "8080:80"
    environment:
      - APP_ENV=production
    depends_on:
      - db

  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: example_password
      MYSQL_DATABASE: example_db
    volumes:
      - db_data:/var/lib/mysql

volumes:
  db_data:

Neste exemplo:

  • O serviço web é construído a partir de um Dockerfile localizado no diretório ./web e expõe a porta 8080 no host para a porta 80 no container.
  • O serviço db usa a imagem mysql:5.7 e é configurado com variáveis de ambiente para definir a senha e o banco de dados inicial.
  • Um volume db_data é montado em /var/lib/mysql no container db, garantindo a persistência dos dados do banco de dados.

Conclusão

Configurando serviços no Docker Compose, você pode personalizar o comportamento de cada container de forma flexível. Definindo imagens, portas, variáveis de ambiente e dependências, é possível criar aplicações multi-containers que compartilham configurações e se comunicam de maneira integrada. No próximo capítulo, Configurando Volumes para Persistência de Dados, exploraremos como usar volumes no Compose para armazenar dados entre reinicializações e garantir a persistência necessária para aplicativos de produção.


5. Configurando Volumes para Persistência de Dados

Objetivo

Ensinar como configurar volumes no Docker Compose para persistir dados entre reinicializações de containers, garantindo que informações essenciais, como dados de banco de dados e arquivos de configuração, permaneçam preservadas.

Conteúdo

  • Introdução ao Uso de Volumes no Docker Compose
  • Definindo Volumes no docker-compose.yml
  • Montagem de Volumes em Serviços
  • Exemplos Práticos de Volumes com Banco de Dados e Armazenamento de Arquivos

Introdução ao Uso de Volumes no Docker Compose

Volumes em Docker são uma forma de armazenamento persistente que permite que dados sejam mantidos mesmo após o container ser destruído ou reiniciado. Em aplicações de produção, volumes são essenciais para armazenar dados críticos que não podem ser perdidos, como informações de bancos de dados, arquivos de configuração e logs.

Definindo Volumes no docker-compose.yml

No Docker Compose, os volumes podem ser definidos na seção volumes, no nível mais alto do arquivo docker-compose.yml. Definir um volume globalmente torna-o acessível a qualquer serviço que precise de armazenamento persistente.

Exemplo:

1
2
3
volumes:
  db_data:
  app_logs:

Neste exemplo, dois volumes são definidos:

  • db_data: Pode ser usado para armazenar dados de um banco de dados.
  • app_logs: Pode ser utilizado para armazenar logs da aplicação.

Montagem de Volumes em Serviços

Após definir um volume, é necessário montá-lo em um serviço específico. Isso é feito na configuração do serviço, utilizando a diretiva volumes. Cada volume pode ser montado em um diretório específico dentro do container, de acordo com as necessidades do serviço.

Sintaxe:

1
2
volumes:
  - volume_nome:/caminho/dentro/do/container

Exemplos Práticos de Volumes com Banco de Dados e Armazenamento de Arquivos

Abaixo, apresentamos exemplos práticos de como montar volumes para persistir dados de um banco de dados MySQL e arquivos de uma aplicação web.

Exemplo 1: Volume para Persistência de Banco de Dados

Neste exemplo, vamos configurar um volume db_data para armazenar os dados de um serviço de banco de dados MySQL.

1
2
3
4
5
6
7
8
9
10
11
12
13
version: '3.8'

services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: root_password
      MYSQL_DATABASE: my_database
    volumes:
      - db_data:/var/lib/mysql

volumes:
  db_data:

Explicação:

  • Volume db_data: Montado no diretório /var/lib/mysql dentro do container. Este é o diretório padrão onde o MySQL armazena seus dados, garantindo que o banco de dados persista entre reinicializações do container.

Exemplo 2: Volume para Armazenamento de Arquivos da Aplicação

Neste exemplo, configuramos um volume app_files para armazenar dados da aplicação, como uploads de usuários.

1
2
3
4
5
6
7
8
9
10
11
12
version: '3.8'

services:
  web:
    image: nginx:alpine
    volumes:
      - app_files:/usr/share/nginx/html/uploads
    ports:
      - "8080:80"

volumes:
  app_files:

Explicação:

  • Volume app_files: Montado no diretório /usr/share/nginx/html/uploads dentro do container Nginx. Esse diretório é onde os arquivos de uploads da aplicação são armazenados, garantindo que eles sejam preservados mesmo se o container web for destruído ou atualizado.

Conclusão

O uso de volumes no Docker Compose é essencial para a persistência de dados em containers Docker. Com volumes, dados críticos, como informações de bancos de dados e arquivos de aplicação, permanecem disponíveis entre reinicializações, atualizações e recriações de containers. No próximo capítulo, Configurando Redes e Comunicação entre Serviços, exploraremos como configurar redes no Docker Compose para permitir que containers se comuniquem com segurança e eficiência.


6. Configurando Redes e Comunicação entre Serviços

Objetivo

Demonstrar como configurar redes no Docker Compose para conectar serviços de forma segura e permitir comunicação entre containers.

Conteúdo

  • Introdução ao Uso de Redes no Docker Compose
  • Tipos de Redes e Suas Aplicações (bridge, host, overlay)
  • Configurando Redes no docker-compose.yml
  • Exemplo Prático de Rede Personalizada para Comunicação Segura

Introdução ao Uso de Redes no Docker Compose

No Docker Compose, redes são essenciais para controlar como os containers se conectam entre si e com o mundo externo. Usando redes, é possível configurar a comunicação entre serviços e limitar o acesso externo a containers específicos, criando um ambiente mais seguro e controlado.

Tipos de Redes e Suas Aplicações

O Docker Compose suporta diferentes tipos de redes que servem a propósitos variados. Aqui estão os principais:

  1. bridge: Rede padrão do Docker, usada para conectar containers em um único host. Ideal para isolar serviços e configurar comunicações entre containers em um mesmo host.
  2. host: Rede que usa a pilha de rede do host, onde o container compartilha o endereço IP do host. Comumente usada para containers que precisam de desempenho máximo de rede.
  3. overlay: Rede que permite comunicação entre containers em múltiplos hosts, ideal para uso em clusters Docker Swarm.

Para configurações locais e de desenvolvimento, a rede bridge é geralmente a mais indicada, enquanto em clusters Docker Swarm a rede overlay permite orquestração entre múltiplos nós.

Configurando Redes no docker-compose.yml

Você pode configurar redes no nível mais alto do arquivo docker-compose.yml para definir redes que estarão disponíveis para os serviços ou diretamente dentro de cada serviço para especificar a rede que ele deve utilizar.

Definindo Redes no Nível Principal

No exemplo abaixo, duas redes são definidas: frontend e backend.

1
2
3
4
5
networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge

Conectando Serviços a Redes

Uma vez que as redes foram definidas, você pode conectá-las aos serviços no docker-compose.yml, especificando em quais redes cada serviço deve estar presente.

Exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    networks:
      - frontend

  app:
    image: myapp:latest
    networks:
      - frontend
      - backend

  db:
    image: postgres:13
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    networks:
      - backend

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge

Explicação:

  • O serviço web está conectado apenas à rede frontend, o que significa que ele só pode se comunicar com containers que estão na mesma rede frontend.
  • O serviço app está conectado às redes frontend e backend, permitindo comunicação tanto com o serviço web quanto com o serviço db.
  • O serviço db está conectado somente à rede backend, mantendo-o isolado da rede frontend e, portanto, inacessível diretamente pelo serviço web.

Essa configuração de rede aumenta a segurança e ajuda a controlar o fluxo de dados entre serviços.


Exemplo Prático de Rede Personalizada para Comunicação Segura

Abaixo está um exemplo de configuração de rede personalizada que define a comunicação entre uma aplicação web, um backend e um banco de dados. Nesse exemplo, o banco de dados é isolado do serviço web, acessível apenas pelo backend.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    networks:
      - frontend

  backend:
    image: myapp:backend
    networks:
      - frontend
      - backend

  database:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: secure_password
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - backend

volumes:
  db_data:

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge

Explicação do Exemplo:

  • Isolamento do Banco de Dados: A rede backend conecta o database ao backend, mas não ao web, garantindo que o banco de dados só seja acessível pelo serviço que realmente precisa dele.
  • Comunicação Controlada: O backend se comunica tanto com o database quanto com o web, permitindo o fluxo de dados necessário, enquanto o serviço web permanece isolado da camada de dados.
  • Persistência: O volume db_data mantém os dados do banco mesmo após a reinicialização dos containers.

Esse exemplo é uma configuração segura e comum para sistemas de produção, onde diferentes serviços têm níveis variados de acesso e comunicação.


Conclusão

Configurar redes no Docker Compose é fundamental para controlar a comunicação entre serviços de maneira eficiente e segura. Com redes personalizadas, você pode definir quais serviços devem se comunicar e isolar aqueles que não precisam estar acessíveis a outros containers, melhorando a segurança do ambiente. No próximo capítulo, Comandos Essenciais do Docker Compose, vamos explorar os comandos principais para gerenciar aplicações multi-containers com Docker Compose.


7. Comandos Essenciais do Docker Compose

Objetivo

Apresentar os principais comandos do Docker Compose que facilitam a gestão de aplicações multi-containers, incluindo comandos para iniciar, parar, escalar, visualizar logs e inspecionar o status dos serviços.

Conteúdo

  • Principais Comandos do Docker Compose
    • docker-compose up
    • docker-compose down
    • docker-compose ps
  • Controle de Logs com docker-compose logs
  • Outros Comandos Úteis
    • docker-compose restart
    • docker-compose exec
  • Exemplo de Uso dos Comandos em Diferentes Cenários

Principais Comandos do Docker Compose

Aqui estão alguns dos comandos mais utilizados para iniciar, parar e monitorar aplicações no Docker Compose.

1. docker-compose up

O comando docker-compose up cria e inicia os containers definidos no arquivo docker-compose.yml.

  • Execução do Comando:
    1
    
    docker-compose up
    
  • Execução em Segundo Plano (Modo Detach): Use a opção -d para rodar os containers em segundo plano, permitindo que o terminal fique livre para outros comandos.
    1
    
    docker-compose up -d
    

Este comando compila as imagens, configura redes e inicia os containers, facilitando a inicialização rápida do ambiente.

2. docker-compose down

O comando docker-compose down encerra e remove todos os containers, redes e volumes criados pelo comando up, mas mantém as imagens.

  • Execução do Comando:
    1
    
    docker-compose down
    
  • Remoção de Volumes Associados: Adicione a opção -v para remover também os volumes persistentes.
    1
    
    docker-compose down -v
    

Esse comando é útil para “limpar” o ambiente após o uso, garantindo que não haja containers e redes remanescentes.

3. docker-compose ps

O comando docker-compose ps exibe uma lista de todos os containers que estão sendo gerenciados pelo Compose, mostrando informações como status e portas expostas.

  • Execução do Comando:
    1
    
    docker-compose ps
    

Esse comando é útil para verificar o status dos containers e confirmar que todos os serviços estão ativos.


Controle de Logs com docker-compose logs

O comando docker-compose logs exibe os logs gerados pelos containers em tempo real. Ele é útil para depurar problemas e monitorar o funcionamento dos serviços.

  • Exibir Logs de Todos os Serviços:
    1
    
    docker-compose logs
    
  • Exibir Logs de um Serviço Específico: Especifique o nome do serviço para filtrar os logs.
    1
    
    docker-compose logs web
    
  • Exibir Logs em Tempo Real: Adicione a opção -f para seguir os logs em tempo real, permitindo monitorar a execução contínua.
    1
    
    docker-compose logs -f
    

Outros Comandos Úteis

1. docker-compose restart

O comando docker-compose restart reinicia todos os containers ou containers específicos, sem precisar parar o ambiente por completo.

  • Reiniciar Todos os Serviços:
    1
    
    docker-compose restart
    
  • Reiniciar um Serviço Específico:
    1
    
    docker-compose restart web
    

Esse comando é especialmente útil após alterações de configuração que não exigem a recriação completa dos containers.

2. docker-compose exec

O comando docker-compose exec permite executar comandos específicos dentro de um container em execução. É uma alternativa prática para entrar no container e executar comandos sem interromper o serviço.

  • Execução de Comandos em um Container Específico:
    1
    
    docker-compose exec web sh
    

Nesse exemplo, estamos executando um shell interativo (sh) dentro do container do serviço web. Esse comando é útil para realizar verificações, rodar comandos de administração e depurar o container.


Exemplo de Uso dos Comandos em Diferentes Cenários

Vamos explorar alguns cenários práticos em que esses comandos podem ser utilizados para gerenciar o ciclo de vida de uma aplicação multi-containers.

  1. Iniciar o Ambiente e Visualizar Logs em Tempo Real

    1
    2
    
    docker-compose up -d
    docker-compose logs -f
    

    Primeiro, iniciamos o ambiente em segundo plano com up -d e, em seguida, visualizamos os logs em tempo real para acompanhar o status dos containers.

  2. Reiniciar um Serviço após Alteração de Configuração

    1
    
    docker-compose restart web
    

    Este comando reinicia apenas o serviço web, útil após modificar configurações no arquivo docker-compose.yml para esse serviço.

  3. Executar Comandos Dentro do Container

    1
    
    docker-compose exec db mysql -u root -p
    

    Neste exemplo, acessamos o banco de dados MySQL diretamente dentro do container db, permitindo realizar tarefas administrativas diretamente.

  4. Encerrar e Limpar o Ambiente

    1
    
    docker-compose down -v
    

    Esse comando encerra todos os containers e remove também os volumes, garantindo uma limpeza completa do ambiente para futuras execuções.


Conclusão

Com os comandos essenciais do Docker Compose, você tem controle total sobre o ciclo de vida dos containers, facilitando o gerenciamento de aplicações multi-containers de forma simples e eficiente. No próximo capítulo, Variáveis de Ambiente e .env no Docker Compose, veremos como gerenciar configurações dinâmicas e sensíveis usando um arquivo .env, permitindo maior flexibilidade e segurança.


8. Variáveis de Ambiente e .env no Docker Compose

Objetivo

Mostrar como gerenciar variáveis de ambiente e configurações dinâmicas no Docker Compose usando um arquivo .env. Isso facilita o controle de configurações sensíveis e permite que valores dinâmicos sejam configurados de forma segura e consistente entre diferentes ambientes.

Conteúdo

  • Introdução ao Uso de Variáveis de Ambiente no Docker Compose
  • Criação e Configuração de um Arquivo .env
  • Referência a Variáveis de Ambiente no docker-compose.yml
  • Exemplo Prático de Configuração de Variáveis Sensíveis

Introdução ao Uso de Variáveis de Ambiente no Docker Compose

No Docker Compose, variáveis de ambiente permitem parametrizar a configuração de serviços e ajustar valores dinâmicos sem a necessidade de modificar diretamente o arquivo docker-compose.yml. As variáveis são usadas para definir dados sensíveis, como credenciais, URLs de APIs e portas, promovendo uma configuração mais flexível e segura.

O Compose busca variáveis de ambiente de duas fontes principais:

  1. Variáveis Definidas no Arquivo .env: Ideal para armazenar variáveis específicas para o ambiente.
  2. Variáveis do Ambiente do Sistema: Valores definidos diretamente no terminal ou no sistema operacional.

Criação e Configuração de um Arquivo .env

O arquivo .env é um arquivo de texto simples onde cada linha contém uma variável de ambiente na forma NOME_VARIAVEL=valor. Ele deve estar no mesmo diretório que o arquivo docker-compose.yml para que o Compose o reconheça automaticamente.

Exemplo de um Arquivo .env:

1
2
3
4
5
6
# Arquivo .env
MYSQL_ROOT_PASSWORD=strong_password
MYSQL_DATABASE=my_database
MYSQL_USER=my_user
MYSQL_PASSWORD=my_user_password
APP_PORT=8080

No exemplo acima:

  • Variáveis de configuração para um serviço MySQL são definidas (MYSQL_ROOT_PASSWORD, MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD).
  • Uma variável APP_PORT especifica a porta onde a aplicação deve estar disponível.

Referência a Variáveis de Ambiente no docker-compose.yml

Dentro do arquivo docker-compose.yml, as variáveis de ambiente podem ser referenciadas com a sintaxe ${NOME_VARIAVEL}. Se a variável for encontrada no arquivo .env ou nas variáveis do ambiente do sistema, seu valor será substituído automaticamente.

Exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "${APP_PORT}:80"
    environment:
      - NGINX_HOST=${HOST}
      - NGINX_PORT=${APP_PORT}

  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql

volumes:
  db_data:

Explicação:

  • A variável APP_PORT no serviço web define a porta de exposição do Nginx.
  • No serviço db, as variáveis de ambiente para o MySQL (MYSQL_ROOT_PASSWORD, MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD) são atribuídas diretamente a partir do arquivo .env.

Se o arquivo .env contiver as variáveis necessárias, o Compose as lerá automaticamente quando o comando docker-compose up for executado.


Exemplo Prático de Configuração de Variáveis Sensíveis

Vamos configurar um ambiente de exemplo usando variáveis de ambiente para gerenciar credenciais e portas, e usaremos o arquivo .env para centralizar essas configurações.

  1. Crie o Arquivo .env:

    Crie o arquivo .env no mesmo diretório que o docker-compose.yml com o seguinte conteúdo:

    1
    2
    3
    4
    5
    
    MYSQL_ROOT_PASSWORD=my_secret_password
    MYSQL_DATABASE=production_db
    MYSQL_USER=prod_user
    MYSQL_PASSWORD=prod_password
    APP_PORT=3000
    
  2. Configure o Arquivo docker-compose.yml:

    No arquivo docker-compose.yml, faça referência às variáveis de ambiente definidas no .env:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    version: '3.8'
    
    services:
      web:
        image: myapp:latest
        ports:
          - "${APP_PORT}:80"
        environment:
          - APP_ENV=production
          - APP_DEBUG=false
    
      db:
        image: mysql:5.7
        environment:
          MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
          MYSQL_DATABASE: ${MYSQL_DATABASE}
          MYSQL_USER: ${MYSQL_USER}
          MYSQL_PASSWORD: ${MYSQL_PASSWORD}
        volumes:
          - db_data:/var/lib/mysql
    
    volumes:
      db_data:
    
  3. Execute o Docker Compose:

    Ao executar o comando docker-compose up, o Docker Compose lerá as variáveis do arquivo .env e as aplicará aos serviços conforme configurado no docker-compose.yml.

    1
    
    docker-compose up -d
    

    Isso criará o ambiente com as configurações dinâmicas de porta e banco de dados, sem a necessidade de alterar o arquivo docker-compose.yml diretamente.


Conclusão

O uso de variáveis de ambiente com .env no Docker Compose permite configurar aplicações de forma flexível e segura, facilitando a mudança de valores entre ambientes sem modificar o arquivo principal docker-compose.yml. No próximo capítulo, Build de Imagens Customizadas com Docker Compose, vamos explorar como construir imagens personalizadas diretamente a partir do Docker Compose, usando um Dockerfile e variáveis de build para personalização adicional.


9. Build de Imagens Customizadas com Docker Compose

Objetivo

Ensinar como construir imagens personalizadas diretamente pelo Docker Compose, configurando o contexto de build, definindo argumentos, e aplicando configurações de cache para otimizar o processo de build.

Conteúdo

  • Introdução ao Build de Imagens com Docker Compose
  • Definindo build no docker-compose.yml
  • Configuração de context, dockerfile e args
  • Exemplo de Configuração para Construção de Imagens Personalizadas

Introdução ao Build de Imagens com Docker Compose

Em projetos onde o código-fonte precisa ser transformado em uma imagem Docker antes de ser executado, o Docker Compose pode gerenciar a construção dessas imagens. Isso é feito usando a opção build, que permite definir um diretório de contexto contendo o código e um Dockerfile com as instruções para criar a imagem.

Definindo build no docker-compose.yml

A diretiva build é usada no Docker Compose para compilar uma imagem a partir de um Dockerfile específico. Dentro de build, é possível especificar o diretório de contexto (context), o caminho do Dockerfile e argumentos de build (args) que podem ser usados para customizar a imagem.

Exemplo Básico de build:

1
2
3
4
5
services:
  app:
    build:
      context: ./app
      dockerfile: Dockerfile

No exemplo acima:

  • context: Define o diretório onde o Dockerfile e os arquivos da aplicação estão localizados. Neste caso, o contexto é ./app.
  • dockerfile: Especifica o nome do Dockerfile. Por padrão, o Compose espera um arquivo chamado Dockerfile, mas você pode definir outros nomes.

Configuração de context, dockerfile e args

Além de context e dockerfile, é possível usar args para definir variáveis de build, que podem ser acessadas dentro do Dockerfile. Essas variáveis permitem que a imagem seja personalizada no momento da construção.

1. Contexto (context) e Dockerfile

O context define o diretório onde o Docker Compose buscará o Dockerfile e os recursos necessários para construir a imagem.

Exemplo com Contexto e Dockerfile:

1
2
3
4
5
services:
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile.prod

2. Argumentos de Build (args)

Os args são variáveis passadas para o Dockerfile durante o processo de construção. Eles são úteis para customizar a imagem de acordo com o ambiente ou com opções específicas de configuração.

Exemplo com args:

1
2
3
4
5
6
7
services:
  backend:
    build:
      context: ./backend
      args:
        NODE_ENV: production
        API_KEY: my_secure_api_key

Neste exemplo:

  • NODE_ENV e API_KEY são passadas para o Docker durante o build e podem ser usadas no Dockerfile para ajustar a imagem de acordo com o ambiente.

Dockerfile Utilizando args: No Dockerfile, você pode usar ARG para declarar e acessar os argumentos de build.

1
2
3
4
5
6
7
8
9
# Dockerfile
FROM node:14

ARG NODE_ENV
ARG API_KEY

# Usando o argumento no build
ENV NODE_ENV=${NODE_ENV}
RUN echo "Building with API Key: ${API_KEY}"

Exemplo de Configuração para Construção de Imagens Personalizadas

Abaixo está um exemplo completo que mostra como usar o Docker Compose para construir uma aplicação web personalizada com diferentes ambientes (development e production), cada um com suas configurações específicas.

  1. Arquivo docker-compose.yml:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    version: '3.8'
    
    services:
      web:
        build:
          context: ./web
          dockerfile: Dockerfile
          args:
            - NODE_ENV=production
            - API_URL=https://api.production.com
        ports:
          - "8080:80"
        environment:
          - NODE_ENV=production
    
  2. Arquivo Dockerfile (web/Dockerfile):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    # Dockerfile para a aplicação web
    FROM node:14
    
    # Argumentos de build
    ARG NODE_ENV
    ARG API_URL
    
    # Definindo variáveis de ambiente
    ENV NODE_ENV=${NODE_ENV}
    ENV REACT_APP_API_URL=${API_URL}
    
    WORKDIR /app
    COPY . .
    
    RUN npm install
    RUN npm run build
    
    CMD ["npm", "start"]
    

Explicação:

  • NODE_ENV e API_URL são argumentos de build usados para definir o ambiente e a URL da API.
  • Esses valores são passados do docker-compose.yml e, durante o build, são configurados no ambiente da aplicação.
  1. Executando o Build com Docker Compose:

    Para iniciar a construção e execução do serviço web, basta executar o comando:

    1
    
    docker-compose up --build
    

    A opção --build força a recompilação da imagem sempre que o Compose é iniciado, aplicando novas configurações e mudanças no código.


Conclusão

Com o Docker Compose, é possível construir imagens personalizadas diretamente a partir do código-fonte, utilizando o Dockerfile e argumentos de build para ajustar a imagem conforme o ambiente. No próximo capítulo, Escalando Serviços com Docker Compose, vamos explorar como escalar serviços para aumentar a capacidade de processamento, configurando múltiplas instâncias de containers para um único serviço.


10. Escalando Serviços com Docker Compose

Objetivo

Demonstrar como escalar serviços no Docker Compose de forma horizontal, ou seja, aumentando o número de instâncias (réplicas) de um serviço para melhorar o desempenho e atender a uma maior demanda.

Conteúdo

  • Introdução ao Escalonamento de Serviços
  • Como Escalar Serviços no Docker Compose
  • Considerações de Rede e Balanceamento de Carga
  • Exemplo Prático de Escalonamento com um Serviço Web

Introdução ao Escalonamento de Serviços

Escalonar serviços em Docker Compose permite criar múltiplas réplicas de um mesmo serviço, que rodam em containers separados. Isso é particularmente útil para:

  • Aumentar a Capacidade de Processamento: Com mais instâncias, a aplicação pode atender a mais usuários simultaneamente.
  • Redundância e Alta Disponibilidade: Se uma instância falha, outras continuam disponíveis para garantir a continuidade do serviço.

O Docker Compose facilita o escalonamento em ambientes de desenvolvimento e teste, enquanto em produção o Docker Swarm ou Kubernetes são normalmente usados para escalabilidade em larga escala.

Como Escalar Serviços no Docker Compose

Para escalar um serviço com o Docker Compose, você pode usar o comando docker-compose up com a opção --scale, ou especificar o parâmetro replicas na configuração docker-compose.yml.

1. Escalonando com o Comando --scale

O comando --scale permite definir o número de instâncias para um serviço ao iniciar o Docker Compose.

Exemplo de Comando:

1
docker-compose up -d --scale web=3

Neste exemplo, o serviço web será escalado para 3 instâncias (ou réplicas). Cada container será criado como uma nova instância do serviço, permitindo que eles compartilhem recursos e se comuniquem pela rede.

2. Configurando Réplicas no Arquivo docker-compose.yml

Se você estiver usando a versão 3 do Docker Compose com Docker Swarm, é possível definir o número de réplicas diretamente no docker-compose.yml usando o parâmetro deploy e replicas.

Exemplo no docker-compose.yml:

1
2
3
4
5
6
7
8
9
version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    deploy:
      replicas: 3

Neste exemplo, o serviço web será escalado para 3 instâncias ao iniciar o Compose com Docker Swarm. Essa configuração é útil em ambientes de produção onde o Swarm é ativado para gerenciamento de clusters.

Nota: A opção deploy só é aplicável ao usar Docker Swarm. Em um ambiente Compose padrão, use --scale diretamente no comando up.

Considerações de Rede e Balanceamento de Carga

Quando um serviço é escalado, cada instância (ou réplica) compartilha a mesma configuração de rede. No Docker Compose, as instâncias escaladas de um serviço podem se comunicar entre si usando o nome do serviço como hostname.

Por padrão, Docker Compose não configura um balanceador de carga, mas o Docker Swarm oferece balanceamento automático. Em um ambiente Docker Compose padrão, o balanceamento pode ser feito através de um proxy reverso como o Nginx ou o Traefik.

Configuração com Proxy Reverso

Usando o Nginx como proxy reverso, é possível distribuir o tráfego entre as instâncias de um serviço escalado. Isso requer a criação de um serviço de proxy separado, que distribui as requisições entre as réplicas.


Exemplo Prático de Escalonamento com um Serviço Web

Aqui está um exemplo de configuração docker-compose.yml que escala um serviço web com múltiplas instâncias.

  1. Arquivo docker-compose.yml:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    version: '3.8'
    
    services:
      web:
        image: nginx:alpine
        ports:
          - "8080:80"
        deploy:
          replicas: 3
    
  2. Iniciar o Docker Compose com Escalonamento:

    Para iniciar o serviço com escalonamento em Docker Compose, utilize o comando abaixo:

    1
    
    docker-compose up -d --scale web=3
    

    Este comando cria três containers para o serviço web, distribuindo o tráfego entre as réplicas.

  3. Teste de Escalonamento:

    Após iniciar o ambiente escalado, você pode verificar o status e as instâncias em execução com o comando:

    1
    
    docker-compose ps
    

    Isso mostrará as instâncias escaladas do serviço web, listando cada container criado para atender ao serviço.


Conclusão

Escalar serviços no Docker Compose é uma prática poderosa que permite testar como uma aplicação se comporta com várias instâncias. Isso simula um ambiente de alta disponibilidade e maior capacidade de atendimento, especialmente útil em desenvolvimento e testes. No próximo capítulo, Saúde e Monitoramento de Containers com Healthchecks, exploraremos como configurar verificações de saúde (healthchecks) para monitorar o status de containers, garantindo que os serviços estejam sempre disponíveis.


11. Saúde e Monitoramento de Containers com Healthchecks

Objetivo

Aprender a configurar healthchecks no Docker Compose para monitorar o status de containers e garantir que os serviços estejam funcionando corretamente. Healthchecks são especialmente úteis para detectar e reiniciar containers em caso de falhas.

Conteúdo

  • Introdução aos Healthchecks
  • Configuração de Healthchecks no docker-compose.yml
    • Comandos, Intervalo e Retries
  • Exemplo Prático de Healthcheck para um Banco de Dados e uma API

Introdução aos Healthchecks

Healthchecks são verificações automáticas que monitoram o estado de um container, executando comandos que retornam se o serviço está saudável ou falhou. Um container saudável está funcionando conforme o esperado, enquanto um container unhealthy pode exigir atenção, reinicialização ou correção.

Usando healthchecks no Docker Compose, você pode configurar:

  • Comando a ser executado para verificar a saúde do container.
  • Intervalo entre as verificações.
  • Número de Tentativas antes de marcar o container como falho.

Configuração de Healthchecks no docker-compose.yml

No Docker Compose, você pode configurar um healthcheck para cada serviço dentro do docker-compose.yml, especificando o comando de verificação, o intervalo entre tentativas, o tempo limite de execução e o número de tentativas antes de uma falha ser declarada.

Estrutura do Healthcheck

Aqui está uma estrutura básica de configuração de um healthcheck:

1
2
3
4
5
6
healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"]
  interval: 1m30s
  timeout: 10s
  retries: 3
  start_period: 30s

Parâmetros do Healthcheck:

  • test: Define o comando para verificar a saúde do container.
  • interval: Tempo entre as verificações consecutivas (ex.: 1m30s).
  • timeout: Tempo máximo para o comando de healthcheck ser executado antes de falhar.
  • retries: Número de tentativas antes de o container ser considerado como unhealthy.
  • start_period: Tempo inicial para o container estar totalmente pronto antes do primeiro healthcheck ser executado.

Exemplo Prático de Healthcheck para um Banco de Dados e uma API

1. Healthcheck para um Banco de Dados MySQL

Aqui está uma configuração de healthcheck para um serviço de banco de dados MySQL, onde o comando verifica a conexão com o MySQL.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
version: '3.8'

services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: example_password
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 30s
      timeout: 10s
      retries: 3
    volumes:
      - db_data:/var/lib/mysql

volumes:
  db_data:

Explicação:

  • O comando mysqladmin ping -h localhost verifica se o MySQL está respondendo a conexões.
  • Intervalo: Verificação a cada 30 segundos.
  • Timeout: Se o comando levar mais de 10 segundos, ele será considerado falho.
  • Retries: Após 3 tentativas com falha consecutivas, o container é marcado como unhealthy.

2. Healthcheck para uma API Web

No caso de uma API Web, o healthcheck pode utilizar uma chamada HTTP para garantir que o servidor esteja respondendo. Abaixo está uma configuração de healthcheck para uma API em Node.js que responde em http://localhost:3000.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
version: '3.8'

services:
  api:
    build:
      context: ./api
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 1m
      timeout: 5s
      retries: 3
      start_period: 30s

Explicação:

  • Comando de Teste: curl -f http://localhost:3000/health verifica a resposta da API. A API deve ter um endpoint /health que retorna um status positivo (200 OK) se tudo estiver correto.
  • Intervalo e Timeout: O healthcheck é executado a cada 1 minuto e falha se o comando leva mais de 5 segundos.
  • Retries e Start Period: Após 3 tentativas consecutivas com falha, o container é considerado unhealthy. O período inicial (start_period) de 30 segundos dá tempo para a API ser iniciada completamente antes da primeira verificação.

Monitorando o Status de Healthcheck

Após configurar e executar o Docker Compose, você pode monitorar o status de saúde dos containers com o comando docker ps ou docker inspect. Containers saudáveis mostrarão o status healthy, enquanto containers com falha mostrarão unhealthy.

1
2
docker-compose up -d
docker ps

A saída do comando docker ps exibirá a coluna STATUS, indicando o estado atual (ex.: healthy, unhealthy) de cada container.


Conclusão

Com os healthchecks no Docker Compose, é possível monitorar o status de cada serviço de forma automática e responder rapidamente a problemas. Esta prática é crucial em ambientes de produção, onde a detecção de falhas e a recuperação rápida são essenciais para a estabilidade do sistema. No próximo capítulo, Usando Dependências de Inicialização e Ordem de Inicialização, vamos aprender como configurar dependências e garantir a ordem de inicialização dos containers para evitar problemas de conectividade entre serviços dependentes.


12. Usando Dependências de Inicialização e Ordem de Inicialização

Objetivo

Aprender a configurar dependências entre serviços no Docker Compose para garantir que os containers iniciem na ordem correta. Isso é essencial para aplicações onde certos serviços devem estar prontos antes que outros possam funcionar corretamente.

Conteúdo

  • Importância da Ordem de Inicialização em Ambientes Multi-Containers
  • Usando depends_on para Definir Dependências entre Containers
  • Limitações do depends_on e Soluções para Ordens de Inicialização Complexas
  • Exemplo Prático de Dependências com Banco de Dados e Serviço Web

Importância da Ordem de Inicialização em Ambientes Multi-Containers

Em ambientes multi-containers, alguns serviços dependem de outros para funcionar. Por exemplo, uma aplicação web pode depender de um banco de dados ou de uma API externa. Se o container de banco de dados não estiver pronto quando a aplicação web iniciar, a conexão pode falhar. Configurar a ordem de inicialização garante que os serviços dependentes só iniciem quando suas dependências estiverem disponíveis.

Usando depends_on para Definir Dependências entre Containers

A diretiva depends_on no Docker Compose permite definir uma ordem básica de dependência entre containers. Ao usar depends_on, você informa ao Docker Compose que um serviço deve ser iniciado antes de outro, mas o depends_on não garante que o serviço esteja pronto, apenas que seu container foi iniciado.

Exemplo com depends_on:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
version: '3.8'

services:
  web:
    image: nginx:alpine
    depends_on:
      - app

  app:
    image: myapp:latest
    depends_on:
      - db

  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: example_password

Explicação:

  • O serviço web depende do serviço app, e o serviço app depende do serviço db.
  • O Docker Compose iniciará os containers na ordem correta (dbappweb), mas depends_on não verifica se o db está pronto para receber conexões antes de iniciar app.

Limitações do depends_on e Soluções para Ordens de Inicialização Complexas

O depends_on define apenas a ordem de inicialização, sem verificar o status de saúde dos serviços. Em situações onde você precisa garantir que um serviço esteja totalmente pronto (por exemplo, com o banco de dados aceitando conexões), é melhor usar um healthcheck em conjunto com scripts de espera, como wait-for-it, wait-for ou dockerize, que esperam até que um serviço específico esteja respondendo.

Exemplo de Script de Espera com wait-for-it

  1. Adicionar o Script wait-for-it: Baixe o script wait-for-it.sh e o adicione ao seu diretório de código.

  2. Configurar o Serviço para Esperar o Banco de Dados:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    version: '3.8'
    
    services:
      app:
        image: myapp:latest
        depends_on:
          - db
        entrypoint: ["./wait-for-it.sh", "db:3306", "--", "npm", "start"]
    
      db:
        image: mysql:5.7
        environment:
          MYSQL_ROOT_PASSWORD: example_password
        healthcheck:
          test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
          interval: 30s
          timeout: 10s
          retries: 5
    

Explicação:

  • Healthcheck no Banco de Dados (db): Verifica se o banco de dados está pronto para aceitar conexões.
  • entrypoint no Serviço app: Usa o script wait-for-it.sh para aguardar até que o banco de dados esteja escutando na porta 3306 antes de iniciar a aplicação.

Esse exemplo garante que o app não tente se conectar ao banco de dados antes que ele esteja pronto para aceitar conexões.

Exemplo Prático de Dependências com Banco de Dados e Serviço Web

Abaixo, apresentamos um exemplo mais completo que inclui um serviço web, um backend de aplicação, e um banco de dados. O backend espera o banco de dados estar pronto antes de iniciar.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    depends_on:
      - app

  app:
    build:
      context: ./app
    environment:
      DATABASE_URL: mysql://user:password@db:3306/mydb
    depends_on:
      - db
    entrypoint: ["./wait-for-it.sh", "db:3306", "--", "npm", "start"]

  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: example_password
      MYSQL_DATABASE: mydb
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 30s
      timeout: 10s
      retries: 5

Explicação:

  • Serviço db: Inclui um healthcheck para verificar se o MySQL está ativo.
  • Serviço app: Usa wait-for-it.sh no entrypoint para esperar o banco de dados (db) estar pronto antes de iniciar.
  • Serviço web: Inicia somente após o backend (app) estar em execução.

Esse exemplo garante que o banco de dados esteja totalmente funcional antes que o app tente se conectar, e que o web só seja acessado quando o backend estiver pronto.


Conclusão

A configuração de dependências e ordem de inicialização no Docker Compose é fundamental para aplicações com serviços interdependentes. Embora o depends_on organize a sequência de inicialização, o uso de healthchecks e scripts de espera garante que os serviços dependentes estejam prontos antes de serem acessados, reduzindo falhas. No próximo capítulo, Práticas de Deploy em Produção com Docker Compose, exploraremos as melhores práticas para usar o Docker Compose em ambientes de produção, cobrindo configurações de segurança e performance.


13. Práticas de Deploy em Produção com Docker Compose

Objetivo

Explorar práticas recomendadas e configurações específicas para o uso do Docker Compose em produção, com foco em segurança, persistência e gerenciamento de logs para garantir a estabilidade e segurança dos serviços em ambientes reais.

Conteúdo

  • Considerações para Uso em Produção
  • Configurações Específicas para Produção
    • Diferenças entre docker-compose.yml e docker-compose.prod.yml
    • Configurações de Persistência e Logs
    • Medidas de Segurança
  • Exemplo de Arquivo docker-compose.prod.yml para Produção

Considerações para Uso em Produção

Embora o Docker Compose seja amplamente usado para desenvolvimento e teste, ele pode ser adaptado para ambientes de produção em cenários mais simples. Para ambientes de produção de larga escala, recomenda-se o uso de ferramentas de orquestração como Kubernetes ou Docker Swarm, que oferecem funcionalidades avançadas, como escalonamento e balanceamento de carga.

Em produção com Docker Compose, é essencial ajustar as configurações para melhorar a segurança, garantir a persistência de dados e configurar logs adequados para monitoramento.

Configurações Específicas para Produção

1. Diferença entre docker-compose.yml e docker-compose.prod.yml

Para separar configurações de desenvolvimento e produção, recomenda-se criar um arquivo específico para produção (docker-compose.prod.yml). Este arquivo inclui apenas as diferenças de configuração específicas para o ambiente de produção.

Exemplo de Comando para Usar um Arquivo Específico:

1
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

2. Configurações de Persistência e Logs

Em produção, é importante garantir que os dados sejam persistentes e que os logs sejam configurados para análise e monitoramento.

  • Persistência de Dados: Certifique-se de usar volumes para armazenar dados importantes, como bancos de dados, arquivos de configuração e logs. Isso evita a perda de dados ao reiniciar ou recriar containers.
  • Gerenciamento de Logs: Configure a coleta de logs para análise e monitoramento contínuo, especialmente para detectar falhas e tendências de desempenho.

Exemplo de Configuração de Volume para Persistência:

1
2
3
4
5
6
7
8
services:
  db:
    image: postgres:13
    volumes:
      - db_data:/var/lib/postgresql/data

volumes:
  db_data:

3. Medidas de Segurança

Para garantir que o ambiente seja seguro, aplique as seguintes práticas de segurança:

  • Usuário Não-Root: Defina um usuário não-root para rodar os containers, reduzindo o risco de exploração de vulnerabilidades.
  • Variáveis de Ambiente Sensíveis: Utilize variáveis de ambiente ou arquivos .env para definir configurações sensíveis, como senhas e chaves de API, e mantenha esses arquivos fora do repositório de código.
  • Rede Isolada: Utilize redes isoladas para restringir a comunicação entre serviços, limitando o acesso de containers ao mínimo necessário.

Exemplo de Configuração Segura para Produção:

1
2
3
4
5
6
7
8
9
10
11
12
13
services:
  app:
    image: myapp:latest
    user: "1001:1001"  # Define um usuário não-root
    environment:
      - APP_ENV=production
      - APP_DEBUG=false
    networks:
      - backend

networks:
  backend:
    driver: bridge

Exemplo de Arquivo docker-compose.prod.yml para Produção

Aqui está um exemplo completo de um arquivo docker-compose.prod.yml que aplica configurações de segurança e persistência, além de usar variáveis de ambiente para senhas e credenciais sensíveis.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    networks:
      - frontend

  app:
    image: myapp:latest
    environment:
      DATABASE_URL: mysql://user:password@db:3306/production_db
      APP_ENV: production
    depends_on:
      - db
    networks:
      - frontend
      - backend

  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: secure_password
      MYSQL_DATABASE: production_db
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - backend
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 30s
      timeout: 10s
      retries: 5

volumes:
  db_data:

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge

Explicação do Exemplo:

  • Segurança: Usuário não-root, variáveis de ambiente para senhas e configuração de redes isoladas.
  • Persistência: Volume db_data para garantir a persistência dos dados do banco de dados.
  • Healthcheck: Monitoramento do serviço de banco de dados para detectar falhas rapidamente.

Executando o Compose com Arquivo de Produção

Para iniciar o ambiente em modo de produção usando os dois arquivos (docker-compose.yml e docker-compose.prod.yml), use o comando:

1
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Esse comando mescla as configurações do arquivo principal com o arquivo de produção, aplicando as configurações específicas do ambiente produtivo.


Conclusão

Configurar um ambiente de produção com Docker Compose requer ajustes para garantir persistência, segurança e monitoramento adequado. Separar as configurações de produção e desenvolvimento com arquivos docker-compose.prod.yml permite uma maior flexibilidade e segurança. No próximo capítulo, Executando Comandos em Containers com Docker Compose, veremos como executar comandos específicos e tarefas em containers com o Compose, permitindo a administração e manutenção direta dos serviços.


14. Executando Comandos em Containers com Docker Compose

Objetivo

Demonstrar como executar comandos específicos e tarefas dentro de containers usando o Docker Compose, uma técnica útil para administração de serviços, inicialização de scripts e execução de comandos pontuais em containers.

Conteúdo

  • Executando Comandos com docker-compose run
  • Executando Comandos com docker-compose exec
  • Exemplo Prático de Execução de Scripts e Comandos em Containers

Executando Comandos com docker-compose run

O comando docker-compose run permite iniciar um novo container baseado em um serviço definido no arquivo docker-compose.yml e executar um comando específico dentro dele. Este comando é útil para executar scripts de configuração ou comandos que devem ser executados uma única vez, como migrações de banco de dados ou tarefas de manutenção.

Sintaxe Básica:

1
docker-compose run <service> <command>

Exemplo:

1
docker-compose run app python manage.py migrate

Neste exemplo, o comando python manage.py migrate é executado no serviço app, que é iniciado temporariamente para rodar esse comando.

Nota: Como docker-compose run cria um novo container, ele não deve ser usado para comandos contínuos em containers já em execução.


Executando Comandos com docker-compose exec

O comando docker-compose exec é usado para executar comandos em containers que já estão em execução. Isso é útil para acessar um container para diagnóstico ou para rodar comandos administrativos sem reiniciar o container.

Sintaxe Básica:

1
docker-compose exec <service> <command>

Exemplo:

1
docker-compose exec db mysql -u root -p

Neste exemplo, o comando mysql -u root -p é executado dentro do container do serviço db, permitindo acesso direto ao MySQL.

Nota: Diferente de run, o comando exec não cria um novo container, mas acessa um container que já está em execução.

Exemplo Prático de Execução de Scripts e Comandos em Containers

Aqui está um exemplo de como usar docker-compose run e docker-compose exec para tarefas comuns, como migração de banco de dados e execução de um script de inicialização.

1. Executando Migrações de Banco de Dados com run

Para rodar migrações de banco de dados em uma aplicação web, use docker-compose run para iniciar o container e executar o comando de migração.

1
docker-compose run web python manage.py migrate

Neste exemplo:

  • Serviço: web
  • Comando: python manage.py migrate, que executa as migrações do banco de dados no ambiente definido para o serviço web.

2. Acessando um Container em Execução com exec

Para rodar comandos administrativos em um banco de dados MySQL que já está em execução, use docker-compose exec.

1
docker-compose exec db mysql -u root -p

Aqui:

  • Serviço: db
  • Comando: mysql -u root -p, que abre um shell interativo do MySQL dentro do container db.

3. Executando Scripts de Inicialização

No arquivo docker-compose.yml, é possível definir comandos específicos a serem executados durante a inicialização de um serviço usando a diretiva command.

Exemplo no docker-compose.yml:

1
2
3
4
5
6
services:
  web:
    image: myapp:latest
    command: python manage.py runserver 0.0.0.0:8000
    depends_on:
      - db

Neste exemplo:

  • O serviço web executa o comando python manage.py runserver 0.0.0.0:8000 automaticamente ao ser iniciado, inicializando o servidor de desenvolvimento da aplicação.

Comparação entre docker-compose run e docker-compose exec

Comando Quando Usar Exemplo
docker-compose run Para executar um comando em um novo container, especialmente para comandos que rodam uma única vez. docker-compose run app python manage.py migrate
docker-compose exec Para rodar comandos em containers que já estão em execução. Ideal para comandos administrativos e de debug. docker-compose exec db mysql -u root -p

Conclusão

Os comandos docker-compose run e docker-compose exec são ferramentas essenciais para administrar containers, permitindo a execução de comandos específicos e a realização de tarefas pontuais sem precisar modificar o ciclo de vida do container. No próximo capítulo, Troubleshooting e Solução de Problemas Comuns, abordaremos como diagnosticar e resolver problemas comuns em ambientes Docker Compose, com dicas para depuração e análise de logs.


15. Troubleshooting e Solução de Problemas Comuns

Objetivo

Identificar e resolver problemas comuns ao usar Docker Compose, com foco em técnicas de diagnóstico, uso de logs e comandos de inspeção para facilitar a solução de problemas que podem ocorrer em ambientes multi-containers.

Conteúdo

  • Uso de Logs para Diagnóstico
    • Comando docker-compose logs
  • Diagnóstico de Problemas de Conexão e Rede
  • Solução de Problemas de Persistência de Dados e Volumes
  • Debug de Variáveis de Ambiente
  • Comandos de Inspeção e Dicas Adicionais

Uso de Logs para Diagnóstico

O primeiro passo para diagnosticar problemas em Docker Compose é analisar os logs dos containers, pois eles fornecem informações detalhadas sobre a inicialização, execução e falhas dos serviços.

Comando docker-compose logs

O comando docker-compose logs exibe os logs dos containers gerenciados pelo Compose. É possível ver todos os logs dos serviços ou apenas os logs de um serviço específico.

  • Exibir Logs de Todos os Serviços:
    1
    
    docker-compose logs
    
  • Exibir Logs de um Serviço Específico:
    1
    
    docker-compose logs app
    
  • Seguir os Logs em Tempo Real:
    1
    
    docker-compose logs -f
    

Os logs podem revelar mensagens de erro, falhas de conexão e problemas de inicialização, ajudando a entender as causas das falhas.

Diagnóstico de Problemas de Conexão e Rede

Em ambientes multi-containers, problemas de rede são comuns. Algumas dicas para resolver problemas de comunicação entre containers incluem:

  1. Verificar se os Containers Estão na Mesma Rede: Use o comando docker network inspect <nome-da-rede> para verificar se os containers envolvidos estão conectados à mesma rede.

    1
    
    docker network inspect backend
    
  2. Teste de Conexão entre Containers: Use o comando docker-compose exec para acessar um container e testar a conexão com outro usando ping ou curl.

    1
    
    docker-compose exec app ping db
    

Se os containers não conseguirem se comunicar, verifique as configurações de rede no arquivo docker-compose.yml para garantir que estejam usando a mesma rede.

Solução de Problemas de Persistência de Dados e Volumes

Problemas com volumes podem resultar em dados ausentes ou inconsistentes. Algumas práticas para resolver problemas de volumes incluem:

  1. Verificar se o Volume Está Configurado: No docker-compose.yml, certifique-se de que os volumes foram definidos corretamente no nível global e também no serviço específico.

    1
    2
    
    volumes:
      db_data:
    
  2. Remover e Recriar Volumes: Em alguns casos, pode ser necessário remover um volume para resolver problemas de dados corrompidos.

    1
    2
    
    docker-compose down -v
    docker-compose up -d
    

Nota: Usar down -v remove todos os volumes, o que pode resultar em perda de dados. Use com cautela e certifique-se de fazer backup de dados importantes.

Debug de Variáveis de Ambiente

Problemas com variáveis de ambiente, como senhas e URLs incorretas, podem afetar o funcionamento dos serviços.

  1. Verificar Variáveis de Ambiente no .env: Confirme que o arquivo .env contém as variáveis necessárias e que elas estão definidas corretamente.

  2. Listar Variáveis de Ambiente de um Container: Use o comando docker-compose exec <serviço> printenv para listar todas as variáveis de ambiente definidas dentro de um container.

    1
    
    docker-compose exec app printenv
    

Esse comando permite verificar se as variáveis foram carregadas corretamente no container e identificar possíveis erros de configuração.

Comandos de Inspeção e Dicas Adicionais

Vários comandos do Docker podem ajudar a inspecionar e diagnosticar problemas com containers e redes.

1. Inspecionar Containers

Use o comando docker inspect para obter detalhes completos sobre um container específico, incluindo variáveis de ambiente, volumes e redes.

1
docker inspect <container_id>

2. Inspecionar Rede

Para verificar se todos os containers necessários estão conectados a uma rede, use o comando docker network inspect.

1
docker network inspect backend

Este comando mostra informações detalhadas sobre os containers conectados à rede, ajudando a resolver problemas de conectividade.

3. Verificar o Status dos Containers

Use docker-compose ps para verificar o status de cada container, incluindo se estão up (em execução) ou exited (finalizados).

1
docker-compose ps

Se um container estiver em estado exited, execute docker-compose logs <serviço> para identificar o motivo da falha.


Resumo de Comandos Úteis para Troubleshooting

Comando Descrição
docker-compose logs Exibe os logs de todos os containers
docker-compose exec app printenv Exibe as variáveis de ambiente de um container
docker network inspect Inspeciona detalhes de uma rede
docker inspect <container_id> Exibe detalhes completos sobre um container específico
docker-compose ps Exibe o status dos containers gerenciados pelo Compose

Conclusão

Com estas técnicas de troubleshooting e solução de problemas, você poderá identificar rapidamente problemas de configuração e execução em ambientes Docker Compose, garantindo que sua aplicação multi-containers funcione de forma estável e confiável. Este foi o último tópico do tutorial sobre Docker Compose!

Espero que este guia tenha sido útil e abrangente, cobrindo desde os fundamentos até práticas avançadas para gerenciar aplicações multi-containers de forma eficiente. Qualquer dúvida ou nova necessidade, estarei por aqui para ajudar!


Conclusão Geral

Ao longo deste tutorial, exploramos as principais funcionalidades e práticas recomendadas para o uso do Docker Compose, uma ferramenta que transforma a maneira de gerenciar aplicações multi-containers. Desde os conceitos básicos até configurações avançadas para produção, cada seção foi projetada para ajudá-lo a criar, escalar e monitorar seus containers de forma eficiente e segura.

O Docker Compose é uma solução poderosa para automatizar a infraestrutura de aplicações complexas, permitindo que os desenvolvedores concentrem seus esforços no desenvolvimento de recursos. Manter uma estrutura organizada e seguir as práticas recomendadas de configuração, persistência e segurança descritas aqui ajudará a garantir um ambiente estável e escalável para a sua aplicação. Seja em desenvolvimento ou produção, o Docker Compose permite um controle refinado e uma automação que impulsionam a produtividade e a confiabilidade.


This post is licensed under CC BY 4.0 by the author.