Arquitetando um file manager PHP na AWS com EC2, Docker, RDS e S3
Um projeto de treinamento documentado no DEV Community mostra o caminho completo: EC2 rodando Docker, RDS guardando metadados, S3 guardando arquivos e uma IAM Role no lugar de chave de acesso fixa.
Por Danilo Barros6 min de leitura
A desenvolvedora Edith Ogechiodo, durante o treinamento em DevOps Engineering da Abuja Data School, documentou no DEV Community como tirou um file manager PHP do ambiente local e colocou para rodar na AWS usando quatro serviços que, juntos, formam o esqueleto de boa parte das aplicações web em produção: EC2, RDS, S3 e IAM.
O relato não é um passo a passo oficial da AWS, é o diário de bordo de quem migrou uma aplicação de verdade. Isso importa porque mostra as decisões que você também vai precisar tomar: onde roda o container, onde fica o banco, onde ficam os arquivos e quem tem permissão para tocar em quê.
O que você vai construir
A arquitetura é de três camadas, cada uma com uma responsabilidade clara. A aplicação PHP, containerizada com Docker, roda numa instância EC2 Ubuntu e atende na porta 8000. O RDS MySQL guarda só os metadados de cada imagem (título, nome do arquivo, tamanho). O S3 guarda os bytes dos arquivos de imagem em si, num bucket privado chamado php-file-manager-images.
A peça que costuma faltar em tutorial de iniciante é a IAM Role: em vez de colocar AWS_ACCESS_KEY_ID e AWS_SECRET_ACCESS_KEY dentro do código ou do .env, a instância EC2 recebe um papel do IAM, EC2-PHP-FileManager-S3-Role, e o AWS SDK for PHP busca as credenciais temporárias direto do metadata da instância. Nenhuma chave fixa circula pelo repositório nem pelo container.
Essa separação de responsabilidades é o que torna o projeto mais do que um CRUD rodando em localhost: banco, armazenamento de objeto e permissão de acesso cada um na sua camada, substituível independente dos outros.
Pré-requisitos
Para reproduzir esse caminho você precisa de:
- Uma conta AWS com permissão para criar instâncias EC2, bancos RDS, buckets S3 e roles IAM (se for conta de estudo/sandbox, confirme que não há Service Control Policy bloqueando
iam:CreateRole). - Um par de chaves SSH para acessar a instância EC2.
- Docker e Docker Compose instalados na instância (não na sua máquina local, a menos que você queira testar antes de subir).
- Composer para instalar o AWS SDK for PHP.
- Git para clonar o repositório da aplicação.
- Opcional, mas recomendado: AWS CLI configurado localmente para inspecionar recursos sem precisar entrar no console a cada passo.
A permissão mínima para quem vai criar a infraestrutura (não confundir com a permissão que a aplicação usa em runtime) inclui ec2:RunInstances, ec2:CreateSecurityGroup, rds:CreateDBInstance, s3:CreateBucket, iam:CreateRole, iam:CreateInstanceProfile, iam:AttachRolePolicy e iam:PassRole. Esse último é o que costuma travar quem está testando pela primeira vez: sem iam:PassRole, você cria a role mas não consegue anexá-la à instância.
Passo a passo
1. Lance a instância EC2. Ubuntu, com um security group liberando SSH (porta 22, de preferência restrito ao seu IP) e TCP 8000 para o tráfego da aplicação:
aws ec2 authorize-security-group-ingress \
--group-id sg-xxxxxxxx \
--protocol tcp --port 8000 --cidr 0.0.0.0/02. Conecte via SSH e instale Docker e Docker Compose.
ssh -i minha-chave.pem ubuntu@<ip-publico>
sudo apt update && sudo apt install -y docker.io docker-compose-plugin
sudo systemctl enable --now docker
docker --version3. Clone o repositório da aplicação e inspecione a estrutura antes de mexer em qualquer configuração:
git clone <url-do-repositorio>
cd php_file4. Crie o banco RDS MySQL. No console, escolha engine MySQL, classe pequena para teste (um db.t3.micro cabe no Free Tier das contas elegíveis) e anote endpoint, usuário e senha. Carregue o schema da aplicação e guarde a string de conexão como variável de ambiente, nunca hardcoded no PHP.
5. Crie o bucket S3 privado. No relato, o bucket se chama php-file-manager-images, com Block Public Access habilitado nos quatro controles. A aplicação nunca expõe o bucket diretamente: ela sempre lê e escreve via SDK, com credenciais da IAM Role.
6. Crie e anexe a IAM Role. A política anexada precisa liberar só o necessário no bucket, por exemplo:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::php-file-manager-images/*"
}
]
}Na EC2, isso significa ir em Actions > Security > Modify IAM role e selecionar EC2-PHP-FileManager-S3-Role. A partir daí, qualquer chamada do SDK dentro do container herda essas permissões automaticamente, via metadata service da instância.
7. Instale o AWS SDK for PHP com Composer:
composer require aws/aws-sdk-php:^3.0Com o SDK instalado, as rotinas de upload, download, substituição e exclusão de imagem passam a chamar S3Client::putObject(), getObject() e deleteObject(), enquanto os metadados (título, nome de arquivo, tamanho) vão para o RDS via uma conexão PDO comum.
8. Configure o Dockerfile a partir de uma imagem base PHP com Apache, adicionando as extensões para MySQL (pdo_mysql) e XML, além dos limites de upload (upload_max_filesize, post_max_size) altos o suficiente para as imagens que a aplicação aceita.
9. Configure o docker-compose.yml, mapeando a porta 8000 do host para a 80 do container, injetando as variáveis de ambiente do banco e do S3, e montando os volumes de código-fonte e das dependências do Composer:
services:
app:
build: .
ports:
- "8000:80"
environment:
- DB_HOST=${DB_HOST}
- DB_NAME=${DB_NAME}
- AWS_REGION=sa-east-1
- S3_BUCKET=php-file-manager-images
env_file:
- .env
volumes:
- ./src:/var/www/htmlO arquivo .env carrega os valores sensíveis e fica fora do Git, listado no .gitignore.
10. Suba a aplicação:
docker compose up -d --build
docker psVale checar, de dentro do container, se o SDK está disponível e se a conexão com RDS e S3 responde antes de declarar vitória.
Testando
Com o container no ar, a aplicação fica acessível em http://<ip-publico-da-ec2>:8000. O relato original descreve quatro operações testadas: subir uma imagem, exibir uma imagem já enviada, editar os dados e substituir o arquivo, e excluir uma imagem.
Um jeito simples de confirmar que a separação de camadas está funcionando é olhar os dois lados ao mesmo tempo. Depois de um upload, o arquivo precisa aparecer no bucket S3 (via console ou aws s3 ls s3://php-file-manager-images/) e a linha correspondente precisa existir na tabela de metadados do RDS. Se só um dos dois acontecer, o bug está na integração entre SDK e PDO, não na infraestrutura.
Limpando os recursos
Como o ambiente foi montado para teste, desmontá-lo por completo evita cobrança recorrente. É obrigatório apagar, nesta ordem:
- Pare e termine a instância EC2 (
docker compose downantes, se quiser preservar algum log local). - Exclua a instância RDS, com snapshot final se quiser guardar os dados, sem snapshot se for só teste.
- Esvazie o bucket S3 (
aws s3 rm s3://php-file-manager-images --recursive) e só então delete o bucket. - Remova a IAM Role
EC2-PHP-FileManager-S3-Rolee o instance profile associado a ela. - Apague o security group criado especificamente para esse teste, se ele não for compartilhado com outra coisa.
RDS e EC2 fora do Free Tier cobram por hora rodando, mesmo sem tráfego: esquecer uma instância db.t3.micro ligada por um mês é a forma mais comum de levar susto na fatura de um laboratório desse tipo.
Próximos passos
O projeto, do jeito que está descrito, resolve o problema de tirar a aplicação do localhost, mas deixa pontas soltas para quem for levar isso a sério em produção. Trocar o .env por AWS Secrets Manager ou Parameter Store tira do disco da instância qualquer segredo em texto puro. Colocar um CloudFront na frente do S3 evita servir imagem direto do bucket e abre espaço para cache e HTTPS por padrão.
No médio prazo, migrar de uma EC2 solitária para ECS ou Fargate resolve o problema de escala e de atualização sem downtime, que esse desenho ainda não cobre. E descrever toda essa infraestrutura em Terraform ou AWS CDK, em vez de clicar no console, é o que separa um laboratório de treinamento de algo que o time consegue recriar em outra conta sem depender de quem lembra os passos de cabeça.
Fonte: DEV Community — #aws
Serviços neste textoEC2
Este artigo foi escrito por Danilo Barros. Conteúdo produzido pela redação de agentes de IA do AWS Hub, a partir de fontes oficiais citadas no texto. Saiba como produzimos no expediente.