Docker Compose para implantar um ambiente PHP com um comando: guia completo de DNMP (Nginx + MySQL + PHP)

As mensagens de erro rolavam no terminal: “O Nginx não encontra o arquivo de socket do PHP-FPM”. Era o oitavo erro daquela noite. Ao instalar o ambiente LNMP manualmente, alterei três arquivos — nginx.conf, php-fpm.conf e my.cnf — e reiniciei os serviços mais de dez vezes, mas o ambiente ainda não funcionava.
Um colega da mesa ao lado comentou: “No meu computador funciona normalmente. Será que sua versão do PHP está errada?”
Ele usava o PHP 7.4; eu havia instalado o 8.1. O MySQL dele era o 5.7, enquanto eu havia instalado o 8.0 sem perceber. Não era surpresa o código não funcionar.
Cada pessoa da equipe usava um ambiente de desenvolvimento diferente. Uma pessoa recém-contratada levava metade do dia só para configurar tudo, enquanto alguém mais experiente precisava orientar cada etapa. O código funcionava no computador A e quebrava no B. Implantar no servidor era ainda mais incerto.
Esses problemas só desapareceram quando testei a implantação do DNMP com Docker Compose. Em 10 minutos, Nginx, MySQL e PHP estavam prontos. Todos passaram a usar o mesmo arquivo de configuração, e ninguém mais precisou dizer “no meu computador funciona”.
Por que usar o Docker Compose para implantar um ambiente PHP
Três grandes problemas da implantação tradicional de LNMP
Problema 1: a instalação e a configuração manuais são trabalhosas; um erro compromete todo o processo
Lembra da primeira vez que você instalou LNMP? Primeiro vem apt-get install nginx, depois php-fpm e, por fim, MySQL. Depois da instalação, ainda é preciso alterar os arquivos de configuração: regras de location no nginx.conf, extensões no php.ini e parâmetros no my.cnf.
Os três arquivos ficam espalhados em diretórios diferentes: /etc/nginx/, /etc/php/ e /etc/mysql/. Um único erro impede o serviço de iniciar. Para investigar, você precisa vasculhar os logs do Nginx, do PHP-FPM e do MySQL até ficar perdido no meio de tanta informação.
Já vi alguém passar três horas investigando por que o Nginx não encontrava o PHP: no php-fpm.conf, listen = 127.0.0.1:9000 havia sido trocado por listen = /run/php/php7.4-fpm.sock.
Problema 2: incompatibilidades entre versões viram uma dor de cabeça
Em toda equipe há quem fique preso a uma versão. Um projeto antigo roda no PHP 5.6, enquanto um novo exige o PHP 8.1. Uma consulta com GROUP BY aceita pelo MySQL 5.7 pode falhar no MySQL 8.0, pois a versão 8.0 ativa o modo ONLY_FULL_GROUP_BY por padrão.
Pior ainda: as máquinas da equipe podem ter combinações completamente diferentes:
- O Mac de Li usa PHP 7.4 + MySQL 5.7
- O Ubuntu de Wang usa PHP 8.0 + MySQL 8.0
- A nova pessoa estagiária usa PHP 8.1 + MariaDB 10.6 no Windows
O código funciona na máquina de Li, é enviado ao Git e falha assim que Wang faz o pull. O ambiente de testes usa outra combinação, e a produção, outra ainda. É uma receita para problemas.
Problema 3: a colaboração da equipe se torna muito ineficiente
No primeiro dia de uma pessoa recém-contratada, alguém mais experiente passa metade do dia ajudando a configurar o ambiente:
- Instalar o Nginx (20 minutos)
- Instalar o PHP e suas extensões (30 minutos, incluindo compilação)
- Instalar o MySQL (15 minutos)
- Configurar a comunicação entre os três serviços (1 hora, com vários obstáculos)
- Importar os dados de teste (10 minutos)
Com sorte, dá para começar a programar à tarde. Sem sorte? Fica para o dia seguinte.
Em uma startup onde trabalhei, uma diferença de ambiente causou uma falha em um recurso simples de cadastro. Os testes passaram no desenvolvimento, mas a produção retornou “falha na conexão com o banco de dados”. O motivo: no desenvolvimento, o usuário root do MySQL não tinha senha; em produção, tinha, mas esqueceram de alterar o arquivo de configuração. Tivemos de fazer um rollback de emergência durante a madrugada, e a reação do chefe quase não foi nada agradável.
Três grandes vantagens do Docker Compose
Vantagem 1: configuração como código, compartilhada por toda a equipe em um único arquivo
O Docker Compose reúne todas as configurações em um arquivo docker-compose.yml:
- Qual versão do Nginx usar? (
nginx:1.25-alpine) - Quais extensões instalar no PHP? (mysqli, pdo_mysql e redis)
- Quais parâmetros configurar no MySQL? (gerenciados de forma centralizada no my.cnf)
- Como os serviços se comunicam? (resolução DNS automática)
Basta versionar esse arquivo no Git para que toda a equipe obtenha exatamente o mesmo ambiente. Chegou alguém novo? É só clonar o projeto e executar docker-compose up -d. Quando voltar do café, o ambiente estará funcionando.
Não é mais necessário perguntar “qual é a senha do seu MySQL?”, “onde está o seu php.ini?” ou “você pode me mostrar sua configuração do Nginx?”. Um arquivo resolve tudo.
Vantagem 2: iniciar e remover tudo com um comando, sem deixar resíduos
Para iniciar todos os serviços:
docker-compose up -d
Para parar e remover todos os contêineres:
docker-compose down
Quer trocar a versão do PHP? Basta alterar uma linha, de image: php:7.4-fpm para image: php:8.1-fpm, e executar o up novamente.
Diferentemente do método tradicional, você não precisa desinstalar uma versão antiga do PHP nem limpar vários arquivos residuais com medo de apagar algo importante do sistema. Os contêineres Docker são totalmente isolados; ao removê-los, tudo fica limpo.
Vantagem 3: isolamento de ambiente e várias versões lado a lado
Quer executar PHP 7.4 e PHP 8.1 ao mesmo tempo? No método tradicional, seria preciso instalar duas versões, configurar portas diferentes e alterar o Nginx para usar valores distintos de fastcgi_pass. É trabalhoso.
Com Docker Compose, basta definir dois serviços PHP no arquivo de configuração:
php74:
image: php:7.4-fpm
php81:
image: php:8.1-fpm
Na configuração do Nginx, aponte para o nome do serviço correspondente. O projeto antigo continua com php74, enquanto o novo usa php81, sem interferência entre eles.
O projeto DNMP com mais estrelas no GitHub (imeepo/dnmp) tem mais de 5.000 estrelas, o que mostra que a abordagem já foi validada por muitas equipes. Não é uma novidade experimental, mas uma solução madura e confiável.
Arquitetura do DNMP em detalhes
O que é DNMP
DNMP é, na prática, a versão Docker do LNMP. Cada letra representa um componente:
- D = Docker: plataforma de contêineres que coloca cada serviço em um “contêiner” independente
- N = Nginx: servidor web que recebe requisições HTTP e as encaminha para o PHP
- M = MySQL: banco de dados relacional que armazena os dados (também pode ser substituído por MariaDB ou PostgreSQL)
- P = PHP: ambiente PHP-FPM que executa o código PHP
Além desses quatro componentes principais, é comum adicionar:
- Redis: serviço de cache para acelerar a leitura de dados
- PHPMyAdmin: ferramenta gráfica para administrar o MySQL
No LNMP tradicional, todos esses serviços são instalados diretamente e ficam misturados no sistema. No DNMP, cada um fica em seu próprio contêiner Docker, como se cada software estivesse em uma máquina virtual diferente, mas com muito menos sobrecarga.
Arquitetura de orquestração dos serviços
Imagine montar um sistema de som com amplificador, caixas e player. Cada aparelho funciona de forma independente, mas todos precisam estar conectados para reproduzir o áudio juntos.
O DNMP segue a mesma lógica. Nginx, PHP e MySQL ficam em três contêineres independentes, conectados por uma rede Docker:
Fluxo de uma requisição:
- O navegador envia uma requisição HTTP para
localhost:80 - O contêiner Nginx recebe a requisição e identifica um arquivo PHP
- O Nginx encaminha a requisição pela porta 9000 ao contêiner PHP (usando o nome de serviço
php) - O contêiner PHP executa o código e, quando precisa consultar o banco, conecta-se ao contêiner MySQL (usando o nome de serviço
mysql) - O PHP devolve o resultado ao Nginx
- O Nginx envia o HTML ao navegador
Mecanismo de comunicação:
O Docker Compose cria automaticamente uma rede bridge e conecta todos os serviços a ela. Cada serviço tem seu próprio nome, e o Docker faz a resolução DNS de forma automática.
Por exemplo, para o PHP acessar o MySQL, não é necessário usar 127.0.0.1:3306: basta usar mysql:3306. O Docker resolve mysql para o endereço IP do contêiner MySQL automaticamente.
Mapeamento de portas:
- Contêiner Nginx: porta 80 → porta 80 do host (acesse localhost para ver o site)
- Contêiner MySQL: porta 3306 → porta 3306 do host (permite usar ferramentas como Navicat)
- Contêiner PHPMyAdmin: porta 80 → porta 8080 do host (acesse localhost:8080 para administrar o banco)
- Contêiner Redis: porta 6379 → porta 6379 do host
Montagem de volumes:
Os dados somem quando o contêiner é removido? Não. Com volumes, os diretórios importantes do contêiner são mapeados para o host:
./www→/var/www/htmlnos contêineres Nginx e PHP (diretório do código)./mysql/data→/var/lib/mysqlno contêiner MySQL (arquivos do banco)./nginx/logs→/var/log/nginxno contêiner Nginx (logs de acesso)
Assim, mesmo que um contêiner seja removido e recriado, os dados continuam no host.
Estrutura de diretórios
Um projeto DNMP padrão tem a seguinte estrutura:
dnmp/
├── docker-compose.yml # Arquivo principal de orquestração, define todos os serviços
├── .env # Variáveis de ambiente (senhas, portas etc.)
├── .gitignore # Arquivos ignorados pelo Git (.env não é enviado)
├── nginx/
│ ├── conf.d/
│ │ └── default.conf # Configuração do site (diretório raiz e encaminhamento PHP)
│ └── logs/ # Logs de acesso e erros
│ ├── access.log
│ └── error.log
├── php/
│ ├── Dockerfile # Personalização da imagem PHP (instalação de extensões)
│ ├── php.ini # Configuração do PHP (limite de memória e tamanho de upload)
│ └── php-fpm.conf # Configuração do PHP-FPM (número de processos)
├── mysql/
│ ├── data/ # Diretório persistente dos arquivos do banco
│ └── my.cnf # Configuração do MySQL (charset e limite de conexões)
└── www/ # Diretório do código do projeto
└── index.php # Arquivo de teste
Arquivos principais:
docker-compose.yml: o arquivo central, que define imagens, volumes e mapeamentos de portas.env: variáveis de ambiente, comoMYSQL_ROOT_PASSWORD=123456, mantendo dados sensíveis separadosnginx/conf.d/default.conf: configuração do site no Nginx, incluindo a raiz e as regras de encaminhamento ao PHPphp/Dockerfile: imagem oficial do PHP complementada com extensões como mysqli e redismysql/data/: diretório dos arquivos do banco, preservado mesmo quando o contêiner é recriado
Parece haver muitos arquivos, mas cada um tem uma responsabilidade clara. É bem diferente de uma configuração LNMP tradicional espalhada pelo sistema.
Prática de 10 minutos: criando um ambiente DNMP do zero
Pré-requisitos
1. Instale o Docker
- Mac/Windows: baixe o Docker Desktop e instale. O docker-compose já vem incluído
- Linux (exemplo com Ubuntu):
sudo apt update sudo apt install docker.io docker-compose -y sudo systemctl start docker sudo systemctl enable docker
2. Verifique a instalação
docker --version
# Saída: Docker version 24.0.6, build xxx
docker-compose --version
# Saída: Docker Compose version v2.21.0
Se os números das versões aparecerem, a instalação foi concluída.
3. Configuração recomendada
- Memória: pelo menos 4 GB (é possível ajustar nas configurações do Docker Desktop)
- Disco: pelo menos 20 GB livres (as imagens ocupam algum espaço)
- Rede: acesso ao Docker Hub (se a conexão for lenta, configure um mirror adequado à sua região)
Opção 1 de implantação rápida: usar um projeto open source consolidado (recomendado)
Não quer perder tempo com a configuração? Use um projeto open source e conclua tudo em 10 minutos.
1. Clone o projeto
Recomendo o imeepo/dnmp, que oferece suporte a CPUs Arm (incluindo os chips Apple da série M):
git clone https://github.com/imeepo/dnmp.git
cd dnmp
2. Configure as variáveis de ambiente
Copie o arquivo de exemplo:
cp .env.example .env
Abra o arquivo .env e altere as configurações principais:
# Senha do root do MySQL (não use 123456, pois é muito fraca)
MYSQL_ROOT_PASSWORD=your_strong_password
# Fuso horário
TZ=Asia/Shanghai
# Mapeamento de portas (se a porta 80 estiver ocupada, use 8080)
NGINX_HTTP_PORT=80
MYSQL_PORT=3306
3. Inicie tudo com um comando
docker-compose up -d
O parâmetro -d executa os serviços em segundo plano. Na primeira inicialização, as imagens serão baixadas, o que pode levar alguns minutos. Se aparecer uma saída como esta, deu certo:
Creating network "dnmp_default" with the default driver
Creating dnmp_mysql_1 ... done
Creating dnmp_php_1 ... done
Creating dnmp_nginx_1 ... done
Creating dnmp_redis_1 ... done
4. Verifique a instalação
Abra http://localhost no navegador. Você deve ver a página do phpinfo com a versão do PHP, as extensões instaladas e outras informações.
Se essa página aparecer, Nginx e PHP estão funcionando.
Acesse também http://localhost:8080. A tela de login do PHPMyAdmin deve aparecer:
- Servidor:
mysql(não use localhost) - Usuário:
root - Senha: a senha definida no arquivo .env
Se o login funcionar, o MySQL também está pronto.
5. Veja o estado dos contêineres
docker-compose ps
A saída deve ser parecida com esta:
Name Command State Ports
--------------------------------------------------------------------
dnmp_nginx_1 nginx -g daemon off; Up 0.0.0.0:80->80/tcp
dnmp_php_1 php-fpm Up 9000/tcp
dnmp_mysql_1 docker-entrypoint... Up 0.0.0.0:3306->3306/tcp
dnmp_redis_1 redis-server Up 6379/tcp
Se State exibir Up, o contêiner está em execução.
Opção 2: escrever o docker-compose.yml manualmente (avançado)
Quer entender o funcionamento em profundidade? Escreva o arquivo de configuração.
1. Crie o diretório do projeto
mkdir my-dnmp && cd my-dnmp
mkdir -p nginx/conf.d php mysql/data www
2. Escreva o docker-compose.yml
Crie o arquivo docker-compose.yml com o conteúdo abaixo:
version: '3.8'
services:
# Serviço Nginx
nginx:
image: nginx:1.25-alpine # A versão alpine produz uma imagem menor
container_name: dnmp-nginx
ports:
- "80:80" # Mapeia a porta 80 para o host
volumes:
- ./www:/var/www/html # Diretório do código
- ./nginx/conf.d:/etc/nginx/conf.d # Configuração do site
- ./nginx/logs:/var/log/nginx # Diretório de logs
depends_on:
- php # Depende do serviço PHP; inicia o PHP antes do Nginx
networks:
- dnmp-network
# Serviço PHP
php:
build: ./php # Cria a imagem usando o Dockerfile
container_name: dnmp-php
volumes:
- ./www:/var/www/html # Mesmo diretório de código usado pelo Nginx
networks:
- dnmp-network
# Serviço MySQL
mysql:
image: mysql:8.0
container_name: dnmp-mysql
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root123456 # Senha do root
MYSQL_DATABASE: test_db # Banco de dados criado por padrão
TZ: Asia/Shanghai # Fuso horário
volumes:
- ./mysql/data:/var/lib/mysql # Persistência de dados
networks:
- dnmp-network
# Serviço Redis (opcional)
redis:
image: redis:7-alpine
container_name: dnmp-redis
ports:
- "6379:6379"
networks:
- dnmp-network
networks:
dnmp-network:
driver: bridge # Rede bridge para a comunicação entre contêineres
3. Crie o Dockerfile do PHP
Crie php/Dockerfile e instale as extensões mais usadas:
FROM php:8.1-fpm
# Instala as dependências do sistema
RUN apt-get update && apt-get install -y \
libzip-dev \
zip \
unzip
# Instala as extensões do PHP
RUN docker-php-ext-install \
mysqli \
pdo_mysql \
zip \
opcache
# Instala a extensão Redis
RUN pecl install redis && docker-php-ext-enable redis
# Define o diretório de trabalho
WORKDIR /var/www/html
4. Crie a configuração do site no Nginx
Crie nginx/conf.d/default.conf:
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html;
# Logs de acesso e erros
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# Encaminha arquivos PHP ao PHP-FPM
location ~ \.php$ {
fastcgi_pass php:9000; # php é o nome do serviço; o Docker resolve o IP
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# Retorna arquivos estáticos diretamente
location ~ \.(js|css|png|jpg|gif|ico)$ {
expires 7d;
}
}
5. Crie os arquivos de teste
Crie www/index.php:
<?php
phpinfo();
Crie www/db_test.php para testar a conexão com o banco:
<?php
$host = 'mysql'; // Nome do serviço, não localhost
$user = 'root';
$pass = 'root123456';
$db = 'test_db';
try {
$pdo = new PDO("mysql:host=$host;dbname=$db", $user, $pass);
echo "Conexão com o banco realizada com sucesso!<br />";
echo "Versão do MySQL: " . $pdo->getAttribute(PDO::ATTR_SERVER_VERSION);
} catch(PDOException $e) {
echo "Falha na conexão: " . $e->getMessage();
}
6. Inicie os serviços
docker-compose up --build -d
O parâmetro --build recria a imagem do PHP. A primeira inicialização demora um pouco mais porque precisa baixar a imagem base e instalar as extensões.
Verificação e testes
1. Teste o PHP
Acesse http://localhost. A página do phpinfo deve aparecer. Confira se:
- A versão do PHP é 8.1
- As extensões mysqli, pdo_mysql e redis aparecem como enabled
2. Teste a conexão com o banco de dados
Acesse http://localhost/db_test.php. Você deve ver uma mensagem de conexão bem-sucedida e o número da versão do MySQL.
Se a conexão falhar, confira:
- Se o contêiner MySQL iniciou:
docker-compose ps - Se o host foi definido como
localhost(deve sermysql) - Se a senha está correta
3. Verifique o estado dos contêineres
docker-compose ps
O State de todos os contêineres deve ser Up.
4. Consulte os logs para investigar erros
Se um contêiner não iniciar, consulte os logs:
docker-compose logs php # Logs do contêiner PHP
docker-compose logs -f nginx # Logs do Nginx em tempo real (parâmetro -f)
Os logs mostram o erro específico, como um problema de sintaxe no arquivo de configuração ou uma porta já ocupada.
Boas práticas de colaboração em equipe
Estratégia de controle de versão
Princípio fundamental: envie as configurações, mas não os dados sensíveis
Crie o arquivo .gitignore:
# Não envia dados sensíveis
.env
# Não envia os arquivos do banco (são grandes)
mysql/data/
# Não envia arquivos de log
nginx/logs/*.log
php/logs/*.log
# O diretório de código é gerenciado pelo projeto da aplicação, não pelo DNMP
www/*
!www/.gitkeep # Preserva a estrutura do diretório
Arquivos enviados ao Git:
git add docker-compose.yml
git add .env.example # Configuração de exemplo, sem senhas reais
git add nginx/conf.d/
git add php/Dockerfile
git add php/php.ini
git add mysql/my.cnf
git commit -m "feat: add DNMP environment config"
git push
Integração de uma pessoa nova em 3 minutos:
- Clone o projeto:
git clone xxx - Copie a configuração:
cp .env.example .env - Altere a senha: edite
.enve mudeMYSQL_ROOT_PASSWORD - Inicie o ambiente:
docker-compose up -d - Importe os dados:
docker exec -i dnmp-mysql mysql -uroot -p < backup.sql
Pronto. Ninguém precisa perguntar “onde está sua configuração do Nginx?” ou “quais extensões você instalou no PHP?”. Está tudo nos arquivos de configuração.
Como usar várias versões do PHP lado a lado
Cenário: o projeto antigo usa PHP 7.4 e o novo exige PHP 8.1. O que fazer?
Opção 1: defina vários serviços PHP no docker-compose.yml
services:
php74:
image: php:7.4-fpm
container_name: dnmp-php74
volumes:
- ./www:/var/www/html
networks:
- dnmp-network
php81:
image: php:8.1-fpm
container_name: dnmp-php81
volumes:
- ./www:/var/www/html
networks:
- dnmp-network
Aponte projetos diferentes para versões diferentes do PHP na configuração do Nginx:
nginx/conf.d/old-project.conf (projeto antigo):
server {
listen 80;
server_name old.local;
root /var/www/html/old-project;
location ~ \.php$ {
fastcgi_pass php74:9000; # Aponta para o PHP 7.4
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
nginx/conf.d/new-project.conf (projeto novo):
server {
listen 80;
server_name new.local;
root /var/www/html/new-project;
location ~ \.php$ {
fastcgi_pass php81:9000; # Aponta para o PHP 8.1
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Configure o arquivo hosts:
127.0.0.1 old.local
127.0.0.1 new.local
Ao acessar http://old.local, o projeto usa PHP 7.4; em http://new.local, usa PHP 8.1. Um não interfere no outro.
Persistência e backup de dados
A persistência de dados já é garantida pelo volume: ./mysql/data é mapeado para /var/lib/mysql no contêiner. Mesmo que o contêiner seja removido, os dados continuam lá.
Script de backup do banco de dados:
Crie scripts/backup.sh:
#!/bin/bash
BACKUP_DIR="./backups"
DATE=$(date +%Y%m%d_%H%M%S)
MYSQL_CONTAINER="dnmp-mysql"
MYSQL_USER="root"
MYSQL_PASSWORD="root123456"
DATABASE="test_db"
mkdir -p $BACKUP_DIR
echo "Iniciando backup do banco $DATABASE..."
docker exec $MYSQL_CONTAINER mysqldump -u$MYSQL_USER -p$MYSQL_PASSWORD $DATABASE > $BACKUP_DIR/${DATABASE}_${DATE}.sql
echo "Backup concluído: $BACKUP_DIR/${DATABASE}_${DATE}.sql"
Backup periódico com cron:
# Edita o crontab
crontab -e
# Executa o backup todos os dias às 2h
0 2 * * * /path/to/scripts/backup.sh
Restaure o banco de dados:
docker exec -i dnmp-mysql mysql -uroot -proot123456 test_db < ./backups/test_db_20251218.sql
Problemas comuns e soluções
Problema 1: a porta está ocupada e o contêiner não inicia
Sintoma:
Error starting userland proxy: listen tcp4 0.0.0.0:80: bind: address already in use
Diagnóstico:
# Mac/Linux
lsof -i :80
# Windows
netstat -ano | findstr :80
Soluções:
- Opção 1: pare o programa que está usando a porta 80, como Apache ou IIS
- Opção 2: altere o mapeamento no
.envparaNGINX_HTTP_PORT=8080e acesselocalhost:8080
Problema 2: permissões de arquivos no Linux/Mac
Sintomas:
- O Nginx retorna
403 Forbidden - O PHP não consegue gravar arquivos e retorna
Permission denied
Causa:
O usuário www-data no contêiner (UID 33) é diferente do usuário no host (UID 1000), impedindo o acesso aos arquivos montados.
Solução temporária para desenvolvimento:
chmod -R 777 ./www
Solução correta: altere o UID do usuário no contêiner
Edite php/Dockerfile para fazer o UID do usuário no contêiner corresponder ao UID do usuário no host:
FROM php:8.1-fpm
# Altera o UID do www-data para o UID do usuário no host (por exemplo, 1000)
RUN usermod -u 1000 www-data && groupmod -g 1000 www-data
# Outras configurações...
Recrie a imagem:
docker-compose build php
docker-compose up -d
Problema 3: extensões do PHP ausentes
Sintoma:
Fatal error: Call to undefined function mysqli_connect()
Diagnóstico:
docker exec dnmp-php php -m # Lista as extensões instaladas
Se mysqli não aparecer, a extensão não está instalada.
Solução:
Edite php/Dockerfile e adicione a extensão:
RUN docker-php-ext-install mysqli pdo_mysql
Recrie e reinicie:
docker-compose build php
docker-compose restart php
Problema 4: falha na conexão com o banco de dados
Sintoma:
SQLSTATE[HY000] [2002] Connection refused
Erros comuns:
- Erro 1: usar
localhostou127.0.0.1como host - Erro 2: tentar conectar antes de o contêiner MySQL concluir a inicialização
- Erro 3: usar uma senha incorreta
Forma correta:
$host = 'mysql'; // Use o nome do serviço, não localhost
$user = 'root';
$pass = 'root123456'; // Confira se é igual ao valor do .env
try {
$pdo = new PDO("mysql:host=$host;dbname=test_db", $user, $pass);
echo "Conexão realizada com sucesso";
} catch(PDOException $e) {
echo "Falha: " . $e->getMessage();
}
Se ainda não conectar, verifique se o MySQL terminou de iniciar:
docker-compose logs mysql
Quando aparecer mysqld: ready for connections, a inicialização foi concluída.
Problema 5: o contêiner encerra logo após iniciar
Sintoma:
docker-compose ps
# O Status de algum contêiner mostra Exit 1 ou Exit 127
Comando de diagnóstico:
docker-compose logs nome-do-serviço
Causas comuns:
-
Erro de sintaxe no arquivo de configuração:
- Falta um ponto e vírgula
;na configuração do Nginx - A indentação do docker-compose.yml está errada (use espaços, nunca Tab)
- Falta um ponto e vírgula
-
Variável de ambiente ausente:
- O MySQL não inicia porque
MYSQL_ROOT_PASSWORDnão foi definido
- O MySQL não inicia porque
-
Serviço dependente não iniciou:
- O Nginx depende do PHP, mas o contêiner PHP não consegue iniciar
Solução:
Corrija os arquivos conforme as mensagens dos logs e reinicie:
docker-compose down # Remove todos os contêineres
docker-compose up -d # Recria e inicia os contêineres
Conclusão
Depois de tudo isso, o valor central de implantar um ambiente DNMP com Docker Compose pode ser resumido em três pontos:
- Economia de tempo: tudo fica pronto em 10 minutos, sobrando tempo para mais duas xícaras de café
- Menos problemas: toda a equipe usa o mesmo ambiente, sem investigar durante a madrugada um bug que “funciona no meu computador”
- Manutenção simples: os arquivos de configuração também funcionam como documentação; uma pessoa nova entende o ambiente sem orientação individual
Quando eu instalava LNMP manualmente, muitas vezes chegava às duas da manhã sem conseguir fazer o ambiente funcionar. Com Docker Compose, a experiência virou realmente “execute up, tome um café e o ambiente estará pronto”.
Não deixe para depois: reserve 10 minutos antes de encerrar o dia e faça um teste. Primeiro, clone um projeto open source como o imeepo/dnmp e experimente a inicialização com um comando. Quando estiver familiarizado, escreva seus próprios arquivos de configuração para entender tudo em profundidade.
E, se surgir algum problema, não entre em pânico:
- Consulte os logs com
docker-compose logs - Pesquise nos Issues do GitHub; provavelmente outra pessoa já encontrou o mesmo problema
- Se não resolver, abra um Issue no repositório do projeto; a comunidade é bastante ativa
Por fim, o Docker Compose não serve apenas para ambientes PHP. Ele também funciona com Node.js, Python e Go. Depois de aprender essa abordagem, trocar de stack deixa de ser um problema de configuração de ambiente.
Próximos passos:
- Comece agora: execute
git clone https://github.com/imeepo/dnmp.gite coloque seu primeiro ambiente DNMP no ar - Aprofunde-se: consulte a documentação oficial do Docker Compose e aprenda recursos avançados, como o docker-compose.override.yml
- Compartilhe: se este artigo ajudou, envie-o a colegas que ainda instalam ambientes manualmente
Processo completo para implantar um ambiente PHP com Docker Compose
Guia completo de DNMP (Nginx + MySQL + PHP) para configurar tudo em 10 minutos e eliminar as diferenças de ambiente na equipe
⏱️ Estimated time: 10 min
- 1
Step 1: Entender o problema e a solução
Contexto do problema:
• Cada pessoa da equipe usa um ambiente de desenvolvimento diferente
• Uma pessoa recém-contratada leva metade do dia só para configurar o ambiente, com orientação individual de alguém mais experiente
• O código funciona no computador A, mas falha no computador B
• A implantação no servidor vira uma questão de sorte
• As versões do PHP são diferentes (7.4 vs. 8.1)
• As versões do MySQL são diferentes (5.7 vs. 8.0)
Solução:
• Usar o Docker Compose para implantar com um comando um ambiente de desenvolvimento DNMP (Docker + Nginx + MySQL + PHP)
• Concluir tudo em 10 minutos e eliminar as diferenças de ambiente na equipe
• Fazer toda a equipe usar a mesma configuração de ambiente - 2
Step 2: Configurar o docker-compose.yml e iniciar os serviços
Configuração completa:
• Configurar os três serviços Nginx, MySQL e PHP no docker-compose.yml
• Configurar a conexão de rede
• Configurar a persistência de dados
• Configurar as variáveis de ambiente
• Configurar verificações de integridade para garantir que os serviços iniciem corretamente
Implantação em 10 minutos:
1) Criar o arquivo docker-compose.yml
2) Configurar os serviços Nginx, MySQL e PHP
3) Iniciar os serviços: docker-compose up -d
4) Verificar o estado dos serviços: docker-compose ps
5) Testar a aplicação PHP: acessar http://localhost - 3
Step 3: Resolver problemas comuns e aplicar boas práticas
Problemas comuns:
• O Nginx não encontra o arquivo de socket do PHP-FPM
• Falha na conexão com o MySQL
• Extensões do PHP ausentes
• Arquivos de configuração sem efeito
Soluções:
• Corrigir os arquivos de configuração conforme as mensagens dos logs
• Reiniciar em seguida: docker-compose down e docker-compose up -d
Boas práticas:
• Fixar versões das imagens com tags
• Configurar a persistência de dados
• Configurar verificações de integridade
• Gerenciar configurações com variáveis de ambiente
• Atualizar as versões das imagens regularmente
• Documentar as configurações
Próximos passos:
• Comece agora: execute git clone https://github.com/imeepo/dnmp.git e coloque seu primeiro ambiente DNMP no ar
• Aprofunde-se: consulte a documentação oficial do Docker Compose para aprender recursos avançados
• Compartilhe: envie este guia a colegas que ainda configuram ambientes manualmente
FAQ
Por que implantar um ambiente PHP com Docker Compose?
• Cada pessoa da equipe usa um ambiente de desenvolvimento diferente
• Uma pessoa recém-contratada leva metade do dia só para configurar o ambiente, com orientação individual de alguém mais experiente
• O código funciona no computador A, mas falha no computador B
• A implantação no servidor vira uma questão de sorte
• As versões do PHP são diferentes (7.4 vs. 8.1)
• As versões do MySQL são diferentes (5.7 vs. 8.0)
Solução: usar o Docker Compose para implantar com um comando um ambiente de desenvolvimento DNMP (Docker + Nginx + MySQL + PHP) em 10 minutos, eliminando as diferenças de ambiente e garantindo a mesma configuração para toda a equipe.
Como implantar um ambiente DNMP com Docker Compose?
• Configurar os três serviços Nginx, MySQL e PHP no docker-compose.yml
• Configurar a conexão de rede
• Configurar a persistência de dados
• Configurar as variáveis de ambiente
• Configurar verificações de integridade para garantir que os serviços iniciem corretamente
Implantação em 10 minutos:
1) Criar o arquivo docker-compose.yml
2) Configurar os serviços Nginx, MySQL e PHP
3) Iniciar os serviços: docker-compose up -d
4) Verificar o estado dos serviços: docker-compose ps
5) Testar a aplicação PHP: acessar http://localhost
Quais são os problemas mais comuns ao implantar um ambiente DNMP?
• O Nginx não encontra o arquivo de socket do PHP-FPM
• Falha na conexão com o MySQL
• Extensões do PHP ausentes
• Arquivos de configuração sem efeito
Soluções:
• Corrigir os arquivos de configuração conforme as mensagens dos logs
• Reiniciar em seguida: docker-compose down e docker-compose up -d
Etapas de diagnóstico:
• Ver os logs dos contêineres: docker-compose logs
• Verificar o estado dos serviços: docker-compose ps
• Inspecionar a rede: docker network inspect
• Conferir se os arquivos de configuração estão corretos
Quais são as boas práticas para um ambiente PHP com Docker Compose?
• Fixar versões das imagens com tags
• Configurar a persistência de dados
• Configurar verificações de integridade
• Gerenciar configurações com variáveis de ambiente
• Atualizar as versões das imagens regularmente
• Documentar as configurações
Próximos passos:
• Comece agora: execute git clone https://github.com/imeepo/dnmp.git e coloque seu primeiro ambiente DNMP no ar
• Aprofunde-se: consulte a documentação oficial do Docker Compose para aprender recursos avançados
• Compartilhe: envie este guia a colegas que ainda configuram ambientes manualmente
19 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
Três pilares do Docker Compose em produção: healthcheck, política de reinicialização e limites de recursos
Entenda os três pilares do Docker Compose em produção: healthchecks para confirmar que os serviços estão prontos, políticas de reinicialização para autorrecuperação e limites de recursos para evitar sobrecarga. Inclui um modelo YAML completo para criar aplicações conteinerizadas estáveis e confiáveis.
Parte 12 de 34
Próximo
Guia prático de Docker Volumes: 5 exemplos para evitar a perda de dados em contêineres
Aprenda a usar Docker Volumes com cinco exemplos práticos, dos conceitos básicos à persistência no MySQL e no Redis, para que seus dados não desapareçam ao excluir um contêiner.
Parte 14 de 34



Comentários
Entre com GitHub para comentar