Como configurar múltiplos bancos de dados em Docker Compose

1. Introdução à orquestração de múltiplos bancos com Docker Compose

Em projetos modernos de software, é comum precisar de mais de um banco de dados simultaneamente. Um sistema pode usar PostgreSQL para dados relacionais, MongoDB para documentos flexíveis e Redis para cache — tudo rodando no mesmo ambiente de desenvolvimento. O Docker Compose resolve esse problema de forma elegante, permitindo definir, iniciar e gerenciar múltiplos contêineres de banco com um único arquivo YAML.

As vantagens são claras: ambientes reproduzíveis, isolamento entre serviços, facilidade de configuração e a possibilidade de simular a arquitetura de produção localmente. Para acompanhar este guia, você precisa ter Docker e Docker Compose instalados, além de conhecimento básico de sintaxe YAML.

2. Estrutura básica do arquivo docker-compose.yml

O coração da configuração é o arquivo docker-compose.yml. Cada banco de dados se torna um serviço, com sua imagem, portas, volumes e variáveis de ambiente. Um exemplo mínimo para três bancos:

version: '3.8'

services:
  mysql:
    image: mysql:8.0
    container_name: mysql-db
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: app_db
    ports:
      - "3306:3306"
    volumes:
      - mysql_data:/var/lib/mysql
    networks:
      - db_network

  postgres:
    image: postgres:15
    container_name: postgres-db
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: adminpass
      POSTGRES_DB: app_pgdb
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - db_network

  mongodb:
    image: mongo:6
    container_name: mongo-db
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: mongo123
    ports:
      - "27017:27017"
    volumes:
      - mongo_data:/data/db
    networks:
      - db_network

volumes:
  mysql_data:
  postgres_data:
  mongo_data:

networks:
  db_network:
    driver: bridge

Cada serviço define um volume persistente — essencial para não perder dados ao reiniciar contêineres. As variáveis de ambiente configuram credenciais e bancos iniciais.

3. Configuração de bancos relacionais em paralelo

Rodar MySQL e PostgreSQL lado a lado exige cuidado com portas conflitantes. O exemplo acima já mapeia portas diferentes (3306 e 5432), mas você pode personalizar ainda mais. Para criar bancos customizados automaticamente, utilize scripts de inicialização.

Crie uma pasta init-scripts/mysql/ com um arquivo init.sql:

CREATE DATABASE IF NOT EXISTS analytics;
CREATE USER 'analyst'@'%' IDENTIFIED BY 'analyst123';
GRANT ALL PRIVILEGES ON analytics.* TO 'analyst'@'%';
FLUSH PRIVILEGES;

Monte esse script no serviço MySQL:

mysql:
  image: mysql:8.0
  volumes:
    - ./init-scripts/mysql:/docker-entrypoint-initdb.d
    - mysql_data:/var/lib/mysql

O Docker executa automaticamente todos os arquivos .sql ou .sh na pasta docker-entrypoint-initdb.d na primeira inicialização. Para PostgreSQL, o processo é similar com a pasta /docker-entrypoint-initdb.d.

4. Adicionando bancos NoSQL ao ambiente

MongoDB e Redis complementam o ecossistema. O MongoDB já foi configurado no exemplo inicial com autenticação. Para Redis como cache:

redis:
  image: redis:7-alpine
  container_name: redis-cache
  command: redis-server --requirepass redispass
  ports:
    - "6379:6379"
  volumes:
    - redis_data:/data
  networks:
    - db_network

Redis não precisa de volume persistente obrigatório (funciona em memória), mas é útil para manter dados entre reinicializações. Se sua aplicação depende do Redis para funcionar, use depends_on:

app:
  image: myapp:latest
  depends_on:
    - redis
    - mysql
    - postgres
    - mongodb

Isso garante que os bancos iniciem antes da aplicação, embora não espere o banco estar pronto — apenas o contêiner. Para esperar a prontidão, considere scripts de health check.

5. Gerenciamento de redes e comunicação entre contêineres

A rede personalizada db_network no exemplo permite que todos os serviços se comuniquem pelo nome do serviço. Assim, sua aplicação pode conectar-se a mysql:3306, postgres:5432 e mongodb:27017 sem precisar de IPs fixos.

Para isolar bancos em redes diferentes, crie múltiplas redes:

networks:
  relational_network:
  nosql_network:

E atribua cada serviço à rede apropriada. Isso é útil em ambientes com múltiplas aplicações que não devem compartilhar todos os bancos.

6. Segurança e boas práticas na configuração

Nunca coloque senhas diretamente no docker-compose.yml. Use um arquivo .env na raiz do projeto:

# .env
MYSQL_ROOT_PASSWORD=seguro123
POSTGRES_PASSWORD=postgresseguro
MONGO_PASSWORD=mongoseguro
REDIS_PASSWORD=redisseguro

Referencie as variáveis no YAML:

environment:
  MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
  POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}

Adicione .env ao .gitignore para não vazar credenciais. Em produção, nunca exponha portas de banco ao host — remova o bloco ports ou limite a 127.0.0.1.

Crie usuários específicos para cada banco com permissões mínimas. No MySQL, por exemplo, evite usar root para tudo.

7. Automatização e scripts de inicialização avançados

Além de scripts SQL, você pode usar entrypoint e command para personalizar. Por exemplo, para iniciar o PostgreSQL com configurações específicas:

postgres:
  image: postgres:15
  command: >
    -c shared_buffers=256MB
    -c max_connections=200
  volumes:
    - ./init-scripts/postgres:/docker-entrypoint-initdb.d

Para migrações de schema, integre ferramentas como Flyway ou Liquibase. Exemplo com Flyway em um serviço separado:

flyway:
  image: flyway/flyway:9
  command: -url=jdbc:mysql://mysql:3306/app_db -user=root -password=${MYSQL_ROOT_PASSWORD} migrate
  volumes:
    - ./migrations:/flyway/sql
  depends_on:
    - mysql

Isso automatiza a aplicação de migrações sempre que o ambiente é iniciado.

8. Testando e depurando o ambiente multi-banco

Comandos essenciais para diagnóstico:

# Ver logs de todos os serviços
docker-compose logs -f

# Ver status dos contêineres
docker-compose ps

# Executar comando dentro de um contêiner
docker exec -it mysql-db mysql -u root -p

# Testar conectividade entre serviços
docker exec -it app-container ping mysql
docker exec -it app-container nc -zv postgres 5432

Problemas comuns e soluções:
- Conflito de porta: verifique se as portas não estão ocupadas no host com netstat -tulpn | grep 3306
- Falha de inicialização: use docker-compose logs mysql para ver erros específicos
- Banco não pronto: implemente health checks no YAML e use condition: service_healthy no depends_on

Exemplo de health check para PostgreSQL:

postgres:
  healthcheck:
    test: ["CMD-SHELL", "pg_isready -U admin"]
    interval: 10s
    timeout: 5s
    retries: 5

Conclusão

Configurar múltiplos bancos de dados com Docker Compose é uma habilidade essencial para desenvolvedores que trabalham com microsserviços, arquiteturas híbridas ou simplesmente precisam de ambientes de desenvolvimento completos. Com as técnicas apresentadas — desde a estrutura básica até health checks e migrações automatizadas — você pode replicar qualquer cenário de produção localmente.

Lembre-se de sempre priorizar segurança com variáveis de ambiente, usar volumes para persistência e testar a conectividade entre serviços. O Docker Compose transforma a complexidade de gerenciar múltiplos bancos em uma configuração declarativa e reproduzível.

Referências