Como implantar MySQL com Docker: persistência e replicação

O erro no terminal era impossível de ignorar: os dados de teste de duas semanas tinham sumido. Eu havia reiniciado o contêiner do MySQL naquela tarde, pensando que seria uma operação comum, mas os dados desapareceram junto com ele.
Implantar MySQL com Docker parece simples: basta executar docker run -e MYSQL_ROOT_PASSWORD=123456 mysql. Na prática, há armadilhas que só ficam claras depois de enfrentá-las: dados que somem, montagem de configuração que não funciona, aplicações locais sem conexão e replicação difícil de ajustar em produção. Este texto vai da persistência à replicação e explica cada configuração.
Fundamentos de uma implantação do MySQL com Docker
A forma mais simples de iniciar — e por que não a recomendo
Vamos começar pelo erro mais comum. Na primeira instalação do MySQL com Docker, muita gente executa diretamente:
docker run --name mysql-test -e MYSQL_ROOT_PASSWORD=123456 -d mysql:8.0
O contêiner inicia, o estado aparece como normal e o banco pode ser acessado. Tudo parece perfeito, mas há uma bomba-relógio nessa configuração.
O motivo é simples: contêineres são temporários. Quando você remove o contêiner — ou reinicia tudo sem perceber como os dados estão armazenados — pode perder o conteúdo. Por padrão, o MySQL grava os dados em /var/lib/mysql dentro do contêiner. Se essa camada for removida, o diretório desaparece com ela.
Na primeira vez que caí nessa armadilha, achei que fosse um bug do MySQL. Depois entendi que o problema não estava no banco: eu simplesmente não havia configurado a persistência.
Persistência de dados: a forma correta de montar volumes
Em termos práticos, persistir os dados significa mapear o diretório do MySQL para um armazenamento fora da camada descartável do contêiner. Assim, mesmo que o contêiner deixe de existir, os dados continuam disponíveis.
O Docker oferece três tipos de montagem:
- bind mount: mapeia diretamente um diretório do host, como
/home/mysql/data - named volume: o Docker gerencia o volume, sem exigir que você conheça sua localização física
- tmpfs: armazena em memória e perde tudo na reinicialização; quase não se usa para esse caso
Em 2024, a recomendação oficial do Docker era usar named volumes, cuja diferença de desempenho em relação a bind mounts já era pequena. Eu uso ambos conforme o cenário: named volume no desenvolvimento, pela praticidade, e bind mount em produção, para facilitar os backups.
Este é o comando completo:
docker run --name mysql-persistent \
-e MYSQL_ROOT_PASSWORD=rootpwd123 \
-p 3306:3306 \
-v mysql-data:/var/lib/mysql \
-d mysql:8.0
O ponto-chave é -v mysql-data:/var/lib/mysql. mysql-data é o nome do volume — o Docker o cria automaticamente — e /var/lib/mysql é o diretório de dados dentro do contêiner do MySQL.
Agora verifique se a persistência realmente funciona:
# Crie um banco de dados dentro do contêiner
docker exec -it mysql-persistent mysql -uroot -prootpwd123 -e "CREATE DATABASE testdb;"
# Pare e remova o contêiner
docker stop mysql-persistent
docker rm mysql-persistent
# Inicie outro contêiner com o mesmo volume
docker run --name mysql-persistent \
-e MYSQL_ROOT_PASSWORD=rootpwd123 \
-p 3306:3306 \
-v mysql-data:/var/lib/mysql \
-d mysql:8.0
# Consulte os bancos; testdb deve continuar disponível
docker exec -it mysql-persistent mysql -uroot -prootpwd123 -e "SHOW DATABASES;"
Se testdb ainda estiver lá, os dados estão realmente protegidos. É o tipo de confirmação que traz tranquilidade.
Montagem do arquivo de configuração: parâmetros personalizados do MySQL
Com a persistência resolvida, surge a próxima pergunta: como alterar a configuração do MySQL?
Talvez você queira usar utf8mb4 como conjunto de caracteres ou aumentar o número máximo de conexões. Sem montar um arquivo de configuração, seria preciso entrar no contêiner e alterar tudo manualmente; ao recriá-lo, o trabalho teria de ser repetido.
O MySQL lê arquivos de configuração em /etc/mysql/conf.d/. Basta montar o seu my.cnf nesse diretório.
Primeiro, crie o arquivo de configuração no host:
mkdir -p /home/mysql/conf
cat > /home/mysql/conf/my.cnf << 'EOF'
[mysqld]
# Configuração do conjunto de caracteres
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
# Configuração do número de conexões
max_connections=1000
# Plugin de autenticação para compatibilidade com alguns clientes
default_authentication_plugin=mysql_native_password
[client]
default-character-set=utf8mb4
EOF
Depois, monte o arquivo ao iniciar o contêiner:
docker run --name mysql-custom \
-e MYSQL_ROOT_PASSWORD=rootpwd123 \
-p 3306:3306 \
-v /home/mysql/conf:/etc/mysql/conf.d \
-v /home/mysql/data:/var/lib/mysql \
-d mysql:8.0
Observe que dois diretórios são montados: um para a configuração e outro para os dados.
Verifique se a configuração entrou em vigor:
docker exec -it mysql-custom mysql -uroot -prootpwd123 -e "SHOW VARIABLES LIKE 'character%';"
Se character_set_server aparecer como utf8mb4, a configuração foi aplicada.
Como resolver problemas de conexão externa
O contêiner está em execução, os dados são persistentes e a configuração foi montada. Agora você tenta conectar uma aplicação local ao MySQL e recebe:
ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (Connection refused)
ou:
ERROR 1045 (28000): Access denied for user 'root'@'172.17.0.1'
Também enfrentei esses dois erros e levei algum tempo para identificar a causa.
Problema 1: Connection refused
Na maioria das vezes, a porta não foi mapeada corretamente. Inclua -p 3306:3306 ao iniciar o contêiner para mapear a porta 3306 do contêiner para a mesma porta no host.
Se a porta 3306 do host já estiver ocupada — por exemplo, por uma instalação local do MySQL — use outra porta externa:
-p 3307:3306 # Acesse pela porta 3307 do host; dentro do contêiner, continua sendo 3306
Outra possibilidade é o bloqueio pelo firewall. Em um servidor Linux, confira as regras:
# CentOS/RHEL
sudo firewall-cmd --zone=public --add-port=3306/tcp --permanent
sudo firewall-cmd --reload
# Ubuntu
sudo ufw allow 3306/tcp
Problema 2: Access denied
Esse é um problema de permissão. Em algumas configurações, o usuário root do MySQL só pode se conectar a partir de localhost, e conexões vindas de outro IP são recusadas.
Uma solução é alterar o host do usuário root para %, permitindo conexões de qualquer IP:
# Entre no contêiner
docker exec -it mysql-custom mysql -uroot -prootpwd123
# Execute o SQL abaixo
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'rootpwd123';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
Há dois cuidados importantes:
- O plugin
mysql_native_passwordtem compatibilidade melhor com alguns clientes MySQL antigos - Nunca use essa abertura irrestrita em produção; crie um usuário específico e limite os IPs permitidos
Depois da alteração, a aplicação externa deve conseguir se conectar.
Isso encerra a primeira parte. Com esses pontos resolvidos, uma implantação básica do MySQL com Docker em uma única instância fica bem mais previsível.
Gerenciamento com Docker Compose
Por que usar Docker Compose
Para testes locais, os comandos docker run anteriores podem ser suficientes. No trabalho diário, porém, alguns problemas aparecem rapidamente:
- O comando é longo, e você precisa procurar no histórico toda vez
- É fácil errar um parâmetro, como o caminho do volume
- Em equipe, cada pessoa inicia o serviço de uma maneira, o que gera configurações inconsistentes
- Quando vários contêineres precisam trabalhar juntos — MySQL, Redis e Nginx, por exemplo — iniciá-los um por um dá trabalho
É aí que o Docker Compose ajuda.
Em resumo, ele coloca aquele comando extenso do docker run em um arquivo YAML. Depois, docker-compose up -d inicia os serviços, docker-compose down os interrompe, e o arquivo pode ser versionado no Git.
Quando uma pessoa nova na equipe perguntar como iniciar o MySQL, basta entregar o docker-compose.yml. Ela faz o git clone e inicia tudo com um comando, sem precisar reconstruir a configuração.
Configuração do MySQL em uma única instância com Docker Compose
A configuração completa está abaixo; em seguida, explico cada parte:
version: '3.8'
services:
mysql:
image: mysql:8.0
container_name: mysql-standalone
restart: always
environment:
MYSQL_ROOT_PASSWORD: rootpwd123
MYSQL_DATABASE: myapp
MYSQL_USER: appuser
MYSQL_PASSWORD: apppwd123
ports:
- "3306:3306"
volumes:
- mysql-data:/var/lib/mysql
- ./conf/my.cnf:/etc/mysql/conf.d/my.cnf
- ./logs:/var/log/mysql
networks:
- mysql-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-prootpwd123"]
interval: 10s
timeout: 5s
retries: 3
volumes:
mysql-data:
networks:
mysql-network:
driver: bridge
Veja o papel das principais opções:
Seção environment:
MYSQL_ROOT_PASSWORD: senha do root; obrigatóriaMYSQL_DATABASE: banco criado automaticamente quando o contêiner iniciaMYSQL_USEReMYSQL_PASSWORD: usuário comum criado automaticamente, mais seguro do que usar root
Seção volumes:
mysql-data:/var/lib/mysql: persistência com named volume./conf/my.cnf:/etc/mysql/conf.d/my.cnf: montagem do arquivo de configuração por caminho relativo./logs:/var/log/mysql: montagem do diretório de logs, útil para investigar problemas
restart: always: reinicia o contêiner automaticamente após uma falha e também inicia o serviço depois que o servidor é reiniciado
healthcheck: envia pings periódicos ao MySQL para verificar sua integridade
networks: define uma rede personalizada; outros contêineres que precisam se comunicar podem entrar na mesma rede
Siga estes passos:
- Crie a estrutura de diretórios:
mkdir -p mysql-docker/{conf,logs}
cd mysql-docker
- Crie o arquivo de configuração
conf/my.cnf:
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
max_connections=1000
default_authentication_plugin=mysql_native_password
[client]
default-character-set=utf8mb4
-
Crie o
docker-compose.ymlcom a configuração completa mostrada acima. -
Inicie os serviços:
docker-compose up -d
- Consulte o estado:
docker-compose ps
A saída será semelhante a esta:
Name Command State Ports
------------------------------------------------------------------------------------------------
mysql-standalone docker-entrypoint.sh mysqld Up (healthy) 0.0.0.0:3306->3306/tcp
O estado (healthy) indica que o healthcheck foi aprovado.
- Consulte os logs:
docker-compose logs -f mysql
O parâmetro -f acompanha os logs em tempo real, como tail -f. Se houver uma falha na inicialização, normalmente a causa aparecerá ali.
- Pare e remova os contêineres:
docker-compose down
Esse comando remove os contêineres, mas não o volume; portanto, os dados permanecem. Para remover também os dados, seria necessário usar:
docker-compose down -v # Cuidado: remove todos os dados
Hoje uso Docker Compose na maior parte do desenvolvimento local. A configuração é escrita uma vez, e depois basta um comando para iniciar ou parar tudo.
Replicação para produção
Como funciona a replicação do MySQL
Antes da configuração, vale entender por que usar replicação.
Uma única instância do MySQL pode bastar em projetos pequenos, mas se torna um gargalo quando a carga aumenta. A replicação atende principalmente a duas necessidades:
- Separação de leitura e escrita: o servidor principal recebe INSERT, UPDATE e DELETE, enquanto as réplicas atendem SELECT. Como muitas aplicações têm mais leituras do que escritas, distribuir as consultas entre réplicas melhora o desempenho
- Backup e alta disponibilidade: se o servidor principal falhar, a réplica ainda pode atender leituras e ajudar na recuperação do serviço
O princípio é simples:
- O servidor principal (Master) ativa o binlog, que registra todas as alterações nos dados
- A réplica (Slave) conecta-se ao servidor principal e lê o binlog
- Dois threads trabalham na réplica: o thread de IO baixa o binlog e o salva no relay log; o thread SQL executa as instruções desse relay log
- Assim, as alterações feitas no servidor principal são reproduzidas na réplica
No Docker, a configuração se resume a três pontos:
- Cada contêiner precisa ter um
server-iddiferente - O servidor principal precisa ter o binlog ativado
- A réplica precisa se conectar ao servidor principal e iniciar a replicação
Parece complexo à primeira vista, mas, depois de configurar o Docker Compose, basta iniciar os serviços.
Configuração do nó Master
O servidor principal precisa de três ajustes: ativar o binlog, definir o server-id e criar um usuário de replicação.
- Crie o arquivo
conf/master.cnf:
[mysqld]
# ID exclusivo do servidor; principal e réplica não podem usar o mesmo valor
server-id=1
# Ativa o log binário
log-bin=mysql-bin
# O formato ROW registra alterações linha por linha e é mais seguro
binlog-format=ROW
# Conjunto de caracteres
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
# Opcional: banco que será replicado; sem esta opção, todos são replicados
# binlog-do-db=myapp
# Opcional: bancos que não serão replicados
# binlog-ignore-db=mysql
# binlog-ignore-db=information_schema
- Configure o servidor principal no Docker Compose:
version: '3.8'
services:
mysql-master:
image: mysql:8.0
container_name: mysql-master
restart: always
environment:
MYSQL_ROOT_PASSWORD: rootpwd123
MYSQL_DATABASE: myapp
ports:
- "3306:3306"
volumes:
- master-data:/var/lib/mysql
- ./conf/master.cnf:/etc/mysql/conf.d/master.cnf
- ./logs/master:/var/log/mysql
networks:
- mysql-replication
volumes:
master-data:
networks:
mysql-replication:
driver: bridge
- Inicie o servidor principal:
docker-compose up -d mysql-master
- Crie o usuário de replicação:
Entre no contêiner do servidor principal e crie um usuário exclusivo para a replicação:
docker exec -it mysql-master mysql -uroot -prootpwd123
Execute o SQL abaixo:
-- Cria o usuário de replicação
CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'replpwd123';
-- Concede a permissão de replicação
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
-- Atualiza as permissões
FLUSH PRIVILEGES;
-- Mostra o estado do servidor principal; anote File e Position
SHOW MASTER STATUS;
SHOW MASTER STATUS retorna algo semelhante a:
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 | 156 | | |
+------------------+----------+--------------+------------------+
Importante: anote os valores de File e Position; eles serão usados para configurar a réplica.
Configuração do nó Slave
A configuração da réplica é um pouco mais simples.
- Crie o arquivo
conf/slave.cnf:
[mysqld]
# ID exclusivo do servidor, diferente do servidor principal
server-id=2
# Relay log
relay-log=relay-bin
# Mantém a réplica somente leitura para evitar escritas acidentais
read-only=1
# Conjunto de caracteres
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
- Atualize o
docker-compose.ymle adicione a réplica:
version: '3.8'
services:
mysql-master:
image: mysql:8.0
container_name: mysql-master
restart: always
environment:
MYSQL_ROOT_PASSWORD: rootpwd123
MYSQL_DATABASE: myapp
ports:
- "3306:3306"
volumes:
- master-data:/var/lib/mysql
- ./conf/master.cnf:/etc/mysql/conf.d/master.cnf
- ./logs/master:/var/log/mysql
networks:
- mysql-replication
mysql-slave:
image: mysql:8.0
container_name: mysql-slave
restart: always
environment:
MYSQL_ROOT_PASSWORD: rootpwd123
ports:
- "3307:3306" # A réplica é acessada pela porta 3307 do host
volumes:
- slave-data:/var/lib/mysql
- ./conf/slave.cnf:/etc/mysql/conf.d/slave.cnf
- ./logs/slave:/var/log/mysql
networks:
- mysql-replication
depends_on:
- mysql-master
volumes:
master-data:
slave-data:
networks:
mysql-replication:
driver: bridge
- Inicie a réplica:
docker-compose up -d mysql-slave
- Configure a conexão da réplica com o servidor principal:
Entre no contêiner da réplica:
docker exec -it mysql-slave mysql -uroot -prootpwd123
Execute o SQL abaixo, substituindo File e Position pelos valores anotados anteriormente:
-- Configura a conexão com o servidor principal
CHANGE MASTER TO
MASTER_HOST='mysql-master', -- Nome do contêiner principal, resolvido diretamente na rede Docker
MASTER_PORT=3306, -- Porta do servidor principal
MASTER_USER='repl', -- Usuário de replicação
MASTER_PASSWORD='replpwd123', -- Senha do usuário de replicação
MASTER_LOG_FILE='mysql-bin.000003', -- Arquivo binlog obtido em SHOW MASTER STATUS
MASTER_LOG_POS=156; -- Posição do binlog obtida em SHOW MASTER STATUS
-- Inicia a replicação
START SLAVE;
-- Mostra o estado da réplica
SHOW SLAVE STATUS\G
Como validar a sincronização
SHOW SLAVE STATUS\G exibe muitos campos. Estes são os mais importantes:
Slave_IO_Running: Yes # O thread de IO deve estar em execução
Slave_SQL_Running: Yes # O thread SQL deve estar em execução
Seconds_Behind_Master: 0 # Atraso da réplica em segundos; 0 indica sincronização imediata
Last_IO_Error: # Vazio indica que não há erro de IO
Last_SQL_Error: # Vazio indica que não há erro SQL
Se Slave_IO_Running e Slave_SQL_Running estiverem como Yes, a replicação foi configurada com sucesso.
Faça um teste de sincronização:
- Crie dados de teste no servidor principal:
docker exec -it mysql-master mysql -uroot -prootpwd123 -e "
USE myapp;
CREATE TABLE test_table (id INT PRIMARY KEY, name VARCHAR(50));
INSERT INTO test_table VALUES (1, 'test data');
"
- Consulte os dados na réplica:
docker exec -it mysql-slave mysql -uroot -prootpwd123 -e "
USE myapp;
SELECT * FROM test_table;
"
Se a linha inserida aparecer, a replicação está funcionando.
É tão satisfatório quanto ver o próprio código rodando corretamente em produção.
Solução de problemas comuns
A replicação não é difícil, mas a primeira configuração costuma apresentar alguns obstáculos. Estes são os mais comuns:
Problema 1: Slave_IO_Running aparece como No
Possíveis causas:
- Falha de rede: confira se os contêineres estão na mesma rede com
docker exec -it mysql-slave ping mysql-master - Permissões incorretas: confirme se o usuário
replfoi criado no servidor principal e recebeu a permissão adequada - Arquivo ou posição de binlog incorretos: execute
SHOW MASTER STATUSnovamente
Problema 2: Slave_SQL_Running aparece como No
Possíveis causas:
- Erro ao executar SQL: consulte
Last_SQL_Errore investigue a mensagem apresentada - Dados divergentes: se o servidor principal já tinha dados antes da configuração, exporte-os e importe-os na réplica antes de ativar a replicação
Problema 3: Seconds_Behind_Master permanece alto
Possíveis causas:
- Desempenho insuficiente da réplica: verifique CPU, memória e I/O de disco
- Escritas frequentes demais no servidor principal: considere adicionar réplicas para distribuir a carga
- Largura de banda insuficiente: confira a latência da rede
Se o problema persistir, redefina a réplica e repita a configuração:
-- Execute na réplica
STOP SLAVE;
RESET SLAVE;
-- Depois, execute novamente CHANGE MASTER TO e START SLAVE
Otimização de desempenho e boas práticas
Como otimizar o desempenho do MySQL no Docker
Muita gente teme que o Docker reduza o desempenho do MySQL. Alguns anos atrás esse impacto era mais perceptível, mas dados de 2024 indicavam uma perda inferior a 5%, quase imperceptível em muitos cenários intensivos em I/O.
Ainda assim, alguns ajustes são úteis.
1. Escolha do tipo de volume
Named volumes e bind mounts já têm desempenho semelhante, mas atendem a necessidades operacionais diferentes:
- named volume: gerenciado pelo Docker e associado automaticamente ao driver de armazenamento; recomendado para desenvolvimento
- bind mount: mapeia diretamente um diretório do host; recomendado para produção, pois facilita backup e monitoramento
# Exemplo com named volume
volumes:
- mysql-data:/var/lib/mysql
# Exemplo com bind mount
volumes:
- /data/mysql:/var/lib/mysql
2. Escolha do modo de rede
A rede bridge padrão atende à maioria dos casos. Se cada fração de desempenho for importante, você pode testar o modo host:
services:
mysql:
network_mode: "host" # Usa diretamente a rede do host para reduzir sobrecarga
No modo host, o mapeamento ports não é necessário: o contêiner escuta diretamente a porta 3306 do host.
3. Limites de recursos
Em produção, limite os recursos para impedir que o contêiner do MySQL consuma toda a capacidade do servidor:
services:
mysql:
image: mysql:8.0
deploy:
resources:
limits:
cpus: '2' # No máximo dois núcleos de CPU
memory: 2G # No máximo 2 GB de memória
reservations:
memory: 1G # Reserva de pelo menos 1 GB de memória
Essa configuração requer docker-compose --compatibility up ou o modo Docker Swarm.
4. Gerenciamento de logs
Sem limites, os logs do contêiner do MySQL podem ocupar todo o disco. Configure a rotação:
services:
mysql:
logging:
driver: "json-file"
options:
max-size: "100m" # Tamanho máximo de 100 MB por arquivo
max-file: "3" # Mantém no máximo três arquivos
Lista de boas práticas para produção
Estas recomendações vêm dos problemas que encontrei na prática e merecem atenção.
Segurança:
- Não use senhas padrão ou fáceis
# ❌ Não faça isto
MYSQL_ROOT_PASSWORD: 123456
# ✅ Use uma senha forte ou Docker secrets
MYSQL_ROOT_PASSWORD: "Mx8#kL9$pQ2@vN4!"
- Gerencie informações sensíveis com Docker secrets
services:
mysql:
image: mysql:8.0
secrets:
- mysql_root_password
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql_root_password
secrets:
mysql_root_password:
file: ./secrets/mysql_root_password.txt
- Restrinja o acesso à rede do contêiner
networks:
mysql-network:
driver: bridge
internal: true # Permite somente comunicação entre contêineres e bloqueia o acesso externo
Se o acesso externo for necessário, prefira um contêiner de aplicação como intermediário em vez de expor diretamente o contêiner do MySQL.
Operação:
- Faça backups periódicos do diretório de dados
# Script de backup simples
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
docker exec mysql-master mysqldump -uroot -prootpwd123 --all-databases > backup_$DATE.sql
# Ou faça backup direto do diretório de dados
tar -czf mysql-data-backup_$DATE.tar.gz /data/mysql/
Em produção, automatize um backup diário e mantenha pelo menos sete dias de histórico.
- Configure um healthcheck para monitorar o contêiner
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
Combine a reinicialização automática com alertas de monitoramento para detectar falhas.
- Monte os logs em um volume separado
volumes:
- ./logs:/var/log/mysql
Com os logs separados, fica mais fácil investigar problemas e eles não ocupam o espaço do volume de dados.
Alta disponibilidade:
- Use pelo menos um servidor principal e uma réplica; quando necessário, adicione outras réplicas
Em cenários com muito mais leituras do que escritas, um servidor principal pode atender de três a cinco réplicas, distribuindo entre elas as consultas de leitura.
- Separe leitura e escrita com balanceamento de carga
Você pode usar MySQL Router, ProxySQL ou a própria aplicação:
- Escritas (INSERT/UPDATE/DELETE) → servidor principal
- Leituras (SELECT) → réplicas, com balanceamento de carga
- Teste periodicamente o processo de promoção da réplica
Não espere o servidor principal falhar para descobrir que a réplica não pode assumir seu lugar. Simule a troca regularmente:
-- Execute na réplica
STOP SLAVE;
RESET SLAVE ALL;
SET GLOBAL read_only=0; -- Desativa o modo somente leitura e promove a réplica
Em produção, use uma solução madura de alta disponibilidade, como MHA ou Orchestrator, para automatizar a troca.
Conclusão
O processo completo começa com uma única instância do MySQL no Docker, passa pela persistência de dados, pela montagem do arquivo de configuração e pela solução de falhas de conexão, avança para o gerenciamento com Docker Compose e chega à replicação para produção. Esses são os cenários mais comuns de uma implantação do MySQL com Docker.
Vale reforçar alguns pontos:
- Persistência de dados é obrigatória: não execute o MySQL em um contêiner descartável sem volume
- A montagem da configuração é importante: defina antecipadamente conjunto de caracteres, limite de conexões e outros parâmetros
- Docker Compose simplifica o gerenciamento: centraliza a configuração e facilita o trabalho em equipe
- Replicação não precisa ser complicada: o essencial é acertar os arquivos e seguir a ordem das etapas
- Produção exige segurança e backup: evite senhas fracas e faça cópias periódicas dos dados
Todas as configurações do texto foram verificadas e podem servir como ponto de partida. Ajuste senhas e portas antes de usá-las no seu ambiente.
Se esta for sua primeira implantação do MySQL com Docker, comece por uma única instância. Entenda primeiro a persistência e a montagem da configuração; depois avance para a replicação. Fazer isso em etapas reduz bastante a chance de erro.
Quando surgir um problema, consulte os logs antes de alterar a configuração às cegas. Na maioria dos casos, a causa aparece ali. Se ainda restarem dúvidas, deixe um comentário para continuarmos a investigação.
Depois de configurado, o MySQL no Docker exige bem menos trabalho do que uma instalação tradicional. Uma configuração reproduzível pode ser executada em qualquer ambiente compatível.
Processo completo para implantar MySQL com Docker
Da persistência de dados à replicação, resolva problemas comuns como perda de dados, montagem de arquivos de configuração e falhas de conexão
⏱️ Estimated time: 1 hr
- 1
Step 1: Implantação em uma instância: persistência e montagem da configuração
Persistência de dados:
• Monte o diretório de dados em um volume:
docker run -d -v mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0
• Monte o arquivo de configuração:
docker run -d -v mysql-data:/var/lib/mysql -v ./my.cnf:/etc/mysql/conf.d/my.cnf -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0
• Defina as variáveis de ambiente:
MYSQL_ROOT_PASSWORD, MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD
Valide a persistência:
• Remova e recrie o contêiner; os dados devem continuar disponíveis - 2
Step 2: Configuração da replicação
Configure o servidor principal:
• Ative o binlog: defina log-bin=mysql-bin no my.cnf
• Defina o server-id: server-id=1
• Crie o usuário de replicação:
CREATE USER 'repl'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
Configure a réplica:
• Informe o endereço do servidor principal:
CHANGE MASTER TO
MASTER_HOST='master',
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=0;
• Inicie a replicação: START SLAVE;
• Verifique o estado: SHOW SLAVE STATUS\G; - 3
Step 3: Solução de problemas e implantação para produção
Resolva os problemas mais comuns:
• Falha de conexão: verifique o mapeamento -p 3306:3306, a rede e o firewall
• Perda de dados: configure a persistência em volume
• Problema de conjunto de caracteres: defina character-set-server=utf8mb4 no my.cnf
• Problema de permissão: confira as permissões do volume com chmod 755
Prepare a produção:
• Gerencie vários contêineres com docker-compose
• Configure uma verificação de integridade (healthcheck)
• Defina limites de recursos (deploy.resources)
• Adote uma estratégia de backup (backup periódico do volume)
• Use volumes nomeados para facilitar o gerenciamento
FAQ
Como evitar a perda de dados ao implantar MySQL com Docker?
1) Monte o diretório de dados em um volume:
docker run -d -v mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0
2) Monte o arquivo de configuração:
docker run -d -v mysql-data:/var/lib/mysql -v ./my.cnf:/etc/mysql/conf.d/my.cnf -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0
3) Defina as variáveis de ambiente:
• MYSQL_ROOT_PASSWORD
• MYSQL_DATABASE
• MYSQL_USER
• MYSQL_PASSWORD
Para validar, remova e recrie o contêiner. Os dados devem continuar disponíveis.
A causa do problema é que, por padrão, o Docker grava os dados na camada do contêiner. Quando o contêiner é removido, essa camada desaparece; por isso, é necessário configurar a persistência.
Como configurar a replicação do MySQL?
1) Ative o binlog (defina log-bin=mysql-bin no my.cnf)
2) Defina o server-id (server-id=1)
3) Crie o usuário de replicação:
CREATE USER 'repl'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
Configure a réplica:
1) Informe o servidor principal:
CHANGE MASTER TO
MASTER_HOST='master',
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=0;
2) Inicie a replicação: START SLAVE;
3) Verifique o estado: SHOW SLAVE STATUS\G;
Como resolver uma falha de conexão com o MySQL no Docker?
• Falha de conexão: confira o mapeamento -p 3306:3306, a rede e o firewall
• Perda de dados: configure a persistência em volume
• Problema de conjunto de caracteres: defina character-set-server=utf8mb4 no my.cnf
• Problema de permissão: confira as permissões do volume com chmod 755
Siga estes passos:
1) Confirme que o contêiner está em execução (docker ps)
2) Verifique o mapeamento de portas (docker port container-name)
3) Verifique a configuração de rede (docker network inspect network-name)
4) Consulte os logs do contêiner (docker logs container-name)
17 min de leitura · Publicado em: 18 dez 2025 · Atualizado em: 4 set 2026
Guia prático Docker
Se você chegou pela busca, o caminho mais rápido é ir para o post anterior ou próximo desta série.
Anterior
Guia completo para implantar Redis com Docker: persistência e autenticação por senha sem perda de dados
Aprenda passo a passo a implantar Redis com Docker, configurar persistência RDB/AOF e autenticação por senha, evitar a perda de dados ao reiniciar o contêiner e preparar o ambiente para produção.
Parte 23 de 34
Próximo
Como configurar Nginx no Docker: volumes, HTTPS e proxy reverso
Configure Nginx no Docker com volumes, HTTPS, renovação automática do Let's Encrypt e proxy reverso entre contêineres, além de práticas para produção.
Parte 25 de 34



Comentários
Entre com GitHub para comentar