Docker sem Drama: ou “como fingir que subir PHP com Nginx sempre foi uma escolha tranquila”
Se você já olhou para um Dockerfile e pensou “isso aqui parece simples, então certamente vai me dar algum susto depois”, parabéns: você já entendeu metade da experiência com containers.
Neste artigo, vou descrever uma configuração de Dockerfile que prepara um ambiente com Ubuntu 24.04, Nginx e PHP-FPM 8.3, criando uma base prática para rodar aplicações PHP dentro de um container. A proposta aqui é simples: deixar tudo pronto para servir a aplicação via Nginx, com o PHP processado pelo PHP-FPM, sem aquela emoção desnecessária de configurar tudo na mão toda vez.
Visão geral da configuração
O Dockerfile usa como imagem base o Ubuntu 24.04, instala os pacotes essenciais do sistema, adiciona o Nginx e o PHP, copia a configuração do servidor web e define o comando responsável por iniciar os dois serviços.
Visão geral da configuração
FROM ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive
WORKDIR /workspace
RUN apt-get update && apt-get install -y --no-install-recommends \
bash ca-certificates curl git nano unzip zip iputils-ping net-tools lsof \
nginx \
php-fpm php-cli \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /var/www
# NGINX CONFIG
COPY nginx/default.conf /etc/nginx/sites-available/default
RUN ln -sf /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
# Simple site
RUN rm -f /var/www/html/index.nginx-debian.html && \
printf "%s\n" "" > /var/www/html/index.php
# Expor porta
EXPOSE 80
# Rodar PHP-FPM e NGINX
CMD ["bash", "-lc", "php-fpm8.3 -D && nginx -g 'daemon off;'"]
1. Escolhendo a imagem base
Tudo começa com:
FROM ubuntu:24.04
Aqui a escolha foi usar o Ubuntu 24.04 como base. Isso significa que o container parte de um sistema operacional mais completo, em vez de uma imagem minimalista. Não é a opção mais “fitness” do mundo, mas costuma ser confortável para quem quer mais previsibilidade e facilidade na instalação de pacotes.
2. Evitando perguntas existenciais do apt
Na sequência:
ENV DEBIAN_FRONTEND=noninteractive
Essa variável evita que o gerenciador de pacotes tente abrir prompts interativos durante a instalação. Em outras palavras, o build não para no meio pedindo confirmação, porque Dockerfile não é exatamente o melhor lugar para debates filosóficos com o sistema.
3. Definindo diretórios de trabalho
Primeiro:
WORKDIR /workspace
Depois:
WORKDIR /var/www
O WORKDIR define o diretório padrão em que os próximos comandos serão executados. Nesse caso, o container começa em /workspace e depois muda para /var/www, que é um caminho bem comum para aplicações web em PHP.
4. Instalando as dependências
A instalação principal acontece aqui:
RUN apt-get update && apt-get install -y --no-install-recommends \
bash ca-certificates curl git nano unzip zip iputils-ping net-tools lsof \
nginx \
php-fpm php-cli \
&& rm -rf /var/lib/apt/lists/*
Esse bloco faz três coisas importantes:
- Atualiza a lista de pacotes com apt-get update.
- Instala ferramentas úteis de sistema, além do Nginx, PHP-FPM e PHP CLI.
- Remove o cache do apt para reduzir o tamanho final da imagem.
Pacotes instalados
Alguns dos principais pacotes são:
- nginx: servidor web responsável por receber as requisições HTTP.
- php-fpm: processo que interpreta os scripts PHP.
- php-cli: útil para executar comandos PHP no terminal.
- curl, git, nano, zip, unzip: ferramentas de apoio para desenvolvimento e manutenção.
- net-tools, lsof, iputils-ping: úteis para diagnóstico, porque em algum momento alguém sempre diz “estranho, na minha máquina funciona”.
5. Copiando a configuração do Nginx
Depois da instalação, o Dockerfile copia a configuração personalizada do Nginx:
COPY nginx/default.conf /etc/nginx/sites-available/default
RUN ln -sf /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
Isso substitui a configuração padrão por uma versão própria do projeto. O link simbólico garante que o site fique habilitado no Nginx.
O conteúdo do arquivo nginx/default.conf é este:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /var/www/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $document_root;
}
}
6. Entendendo a configuração do Nginx
Essa configuração prepara o Nginx para servir uma aplicação PHP moderna.
Ponto de entrada da aplicação
root /var/www/public;
index index.php index.html;
Aqui o servidor procura os arquivos dentro de /var/www/public. Isso é bastante comum em frameworks PHP, porque a pasta public costuma ser a porta de entrada da aplicação.
Fallback para index.php
location / {
try_files $uri $uri/ /index.php?$query_string;
}
Esse trecho tenta localizar o arquivo solicitado diretamente. Se não encontrar, redireciona a requisição para o index.php, mantendo a query string. Esse comportamento é essencial para rotas amigáveis em muitos projetos PHP.
Processamento de arquivos PHP
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $document_root;
}
Aqui o Nginx envia os arquivos .php para o PHP-FPM, usando o socket:
/run/php/php8.3-fpm.sock
Ou seja, o Nginx não executa PHP sozinho. Ele apenas entrega a requisição ao PHP-FPM, que faz o trabalho pesado. Cada um no seu papel, como deveria ser em um mundo minimamente civilizado.
7. Criando uma página PHP simples
O Dockerfile também remove a página padrão do Nginx e cria um arquivo PHP básico:
RUN rm -f /var/www/html/index.nginx-debian.html && \
printf "%s\n" "" > /var/www/html/index.php
Esse passo é útil para testes iniciais, porque gera uma página com phpinfo(), que mostra se o PHP está funcionando corretamente.
O código criado é:
<?php phpinfo(); ?>
8. Atenção a um detalhe importante
Existe um ponto que merece destaque: o Dockerfile cria o arquivo de teste em:
/var/www/html/index.php
Mas o Nginx está configurado para usar como raiz:
/var/www/public
Ou seja, se não existir uma pasta public com um index.php, o servidor pode não exibir o arquivo criado em /var/www/html. É aquele tipo de detalhe pequeno, elegante e discretamente irritante, muito apreciado por configurações feitas às pressas às 18h de uma sexta-feira.
Se a intenção for usar a pasta public, o ideal é garantir que a aplicação esteja realmente nesse caminho. Se a ideia for testar rapidamente com o phpinfo(), então o mais coerente seria alinhar ambos os caminhos.
9. Expondo a porta da aplicação
A instrução:
EXPOSE 80
indica que o container disponibiliza a porta 80, padrão para tráfego HTTP.
Isso não publica a porta automaticamente no host, mas documenta a intenção da imagem e facilita o mapeamento na hora de subir o container.
10. Inicializando os serviços
Por fim, o container é iniciado com:
CMD ["bash", "-lc", "php-fpm8.3 -D && nginx -g 'daemon off;'"]
Esse comando faz o seguinte:
- inicia o php-fpm8.3 em segundo plano com -D;
- mantém o nginx em primeiro plano com daemon off;.
Esse detalhe é importante porque o Docker espera que o processo principal continue ativo. Se tudo rodasse em background, o container encerraria imediatamente, numa demonstração bastante objetiva de desapego.
Conclusão
Essa configuração monta um ambiente funcional para aplicações PHP com Nginx e PHP-FPM dentro de um container Docker. A estrutura é simples, direta e útil para desenvolvimento ou testes iniciais, especialmente quando se quer uma base rápida sem depender de imagens muito específicas.
Ao mesmo tempo, vale observar o alinhamento entre o caminho configurado no Nginx e o local onde os arquivos da aplicação são criados. Quando esses detalhes estão consistentes, o ambiente tende a subir de forma limpa. Quando não estão, o Docker continua funcionando normalmente, apenas com aquele charme clássico de te fazer questionar sua sanidade por alguns minutos.