Levar um ambiente de desenvolvimento local para o docker compose em produção exige uma mudança drástica de mentalidade. O comando docker-compose up que funciona perfeitamente na sua máquina não possui, por padrão, o isolamento, a segurança ou a resiliência exigidos por um servidor exposto à internet.
Neste artigo, vamos detalhar as melhores práticas para arquitetar a rede (networking) e a persistência de dados (volumes) de forma profissional e segura.
1. Redes no Docker: Isolamento é a Primeira Linha de Defesa
O maior erro de deployments iniciantes é deixar todos os containers na rede bridge padrão. Ao arquitetar seu docker compose em produção, a regra de ouro é aplicar o princípio do menor privilégio: serviços não devem se enxergar a menos que precisem se comunicar.
Separe suas Redes: Frontend e Backend
A topologia mais segura divide a sua stack em pelo menos duas redes customizadas:
- Frontend (Pública/Proxy): Onde fica o seu Reverse Proxy (Nginx, Traefik, LiteSpeed). Esta rede tem contato com o mundo externo, recebendo as requisições HTTP/HTTPS.
- Backend (Privada/Dados): Onde residem o banco de dados (MariaDB, PostgreSQL), sistemas de cache (Redis) e a aplicação em si. A internet nunca toca nesta rede.
O proxy reverso é o único serviço configurado para participar de ambas as redes, atuando como um filtro rigoroso.
A Armadilha das Portas: expose vs. ports
Entender a diferença entre essas duas diretivas evita o vazamento acidental do seu banco de dados para a internet:
ports(Exposição Externa): Faz o bind de uma porta do container diretamente com uma interface do servidor host (ex:80:80). Use apenas no seu proxy reverso.expose(Exposição Interna): Declara que o container escuta em uma porta, mas ela só fica acessível para outros containers na mesma rede interna. Esta é a escolha correta para bancos de dados.
2. Persistência de Dados: Evitando a Perda de Estado
Containers são efêmeros. Se um container for recriado, os dados gravados em sua camada temporária desaparecem. A escolha correta do tipo de montagem no docker compose em produção evita a perda catastrófica de informações.
Named Volumes vs. Bind Mounts
Saber quando usar cada abordagem garante performance e estabilidade:
- Named Volumes (Volumes Nomeados): Gerenciados pelo próprio Docker (armazenados em
/var/lib/docker/volumes/). São a escolha oficial para dados reais, como o diretório/var/lib/mysql. Eles oferecem melhor performance de I/O e evitam problemas complexos de permissão (UID/GID) entre o host e o container. - Bind Mounts (Mapeamento de Host): Apontam para um caminho exato no seu servidor (ex:
/etc/nginx/conf.d/). Devem ser usados exclusivamente para arquivos estáticos, como injetar configurações ou certificados SSL.
Segurança com Montagens Somente Leitura (Read-Only)
Se o seu container precisa apenas ler um arquivo de configuração via Bind Mount, bloqueie o acesso de escrita adicionando :ro (read-only) ao final do mapeamento. Isso impede que uma vulnerabilidade na aplicação altere arquivos críticos do servidor.
3. Exemplo Prático: docker-compose.yml Seguro
Abaixo, um modelo base aplicando todas as regras discutidas:
services:
# PROXY REVERSO (Acessível externamente)
proxy:
image: nginx:alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
# Bind mount em Read-Only para configurações
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
networks:
- rede_frontend
# APLICAÇÃO (Isolada da internet direta)
app:
image: minha-app:latest
restart: unless-stopped
expose:
- "9000" # Comunica apenas com o proxy na rede interna
networks:
- rede_frontend
- rede_backend
# BANCO DE DADOS (Máximo isolamento)
db:
image: mariadb:10.11
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: app_db
volumes:
# Named volume para os dados (performance e segurança)
- db_data:/var/lib/mysql
# SEM DIRETIVA "ports" AQUI
networks:
- rede_backend
# DEFINIÇÃO DAS REDES
networks:
rede_frontend:
driver: bridge
rede_backend:
driver: bridge
internal: true # Impede roteamento externo para esta rede
# DEFINIÇÃO DOS VOLUMES
volumes:
db_data:
Conclusão
Rodar o docker compose em produção com segurança não precisa ser complexo, desde que você abandone os atalhos do ambiente de desenvolvimento. Segmentar suas redes, proteger as portas do banco de dados e escolher o tipo certo de volume formam a base de uma infraestrutura resiliente. Lembre-se: persistência de volume não é backup. Implemente sempre rotinas externas de dump e envio para storage remoto.
FAQ
expose e ports no Docker Compose?A diretiva ports mapeia a porta do container diretamente para o servidor host (expondo para a internet, útil para Proxy Reverso). Já o expose apenas libera a porta para a comunicação interna entre os containers da mesma rede, sendo a opção segura para bancos de dados.
A rede bridge padrão não oferece isolamento de segurança adequado e depende de links de containers legados em vez de resolução de nomes DNS interna moderna. Criar redes customizadas (como frontend e backend) garante que serviços expostos não tenham acesso direto a serviços críticos.
Para bancos de dados, utilize sempre Named Volumes (Volumes Nomeados). Eles são gerenciados de forma eficiente pelo próprio Docker, evitam problemas complexos de permissão de pastas do host e oferecem desempenho superior de I/O em comparação aos Bind Mounts.
Ao utilizar Bind Mounts para injetar configurações (como um nginx.conf), adicione a flag :ro (read-only) ao final do mapeamento no docker-compose.yml. Isso impede que o container tenha permissão de escrita sobre o arquivo original no servidor.
Veja Mais:
Docker para SysAdmins: Serviços Isolados sem Complicação
Como instalar Portainer para gerenciamento Docker com Nginx Proxy Manager no Ubuntu
Otimização de Código vs Servidor: Decisão Prática para Alta Performance
O que ninguém te conta sobre gerenciar servidores em produção
How to Install Portainer for Docker Management with Nginx Proxy Manager on Ubuntu
Mailcow Docker: Vale a Pena Rodar E-mail Próprio? Análise Completa

