Ambiente local do Magento 2 com Docker e Warden
Um projeto Magento 2 tem mais peças móveis do que a maioria das aplicações PHP. PHP-FPM, um servidor web, MySQL ou MariaDB, OpenSearch, Redis ou Valkey, Varnish, RabbitMQ e um mail catcher precisam rodar juntos, em versões iguais às da produção. Instalar tudo isso à mão no notebook funciona até o segundo projeto precisar de outra versão do PHP.
O Docker resolve o problema das versões. O Warden, uma ferramenta open source construída em cima do Docker Compose, resolve a fiação. Este artigo passa por um setup de Warden para o Magento 2.4.8, do primeiro env-init até uma loja funcionando com Xdebug, e os hábitos que mantêm tudo funcionando.
Por que um ambiente em containers
O ponto principal é a paridade. Se a produção roda PHP 8.3 com OpenSearch 2 e MariaDB, o ambiente local deve rodar o mesmo. Bugs que só aparecem com um modo específico do MySQL ou um analyzer específico do OpenSearch são muito mais fáceis de pegar quando as versões batem.
O segundo ponto é o isolamento. Cada projeto tem seus próprios containers, seu próprio banco e seus próprios hostnames. Você pode parar um projeto e subir outro sem desinstalar nada, e um dev novo consegue uma loja rodando a partir de um repositório e um dump de banco, em vez de uma página de notas de instalação.
O que o Warden oferece
O Warden roda alguns serviços globais uma vez por máquina e depois uma stack por projeto:
- Traefik como reverse proxy, para cada projeto ter um hostname como
app.myshop.test - Uma root CA local, para esses hostnames funcionarem em HTTPS sem avisos do navegador
- dnsmasq para resolver
*.testpara a sua máquina - Mailhog (ou Mailpit, conforme a versão) para capturar e-mails enviados
- Containers por projeto para nginx, PHP-FPM, um PHP-FPM separado com Xdebug, o banco, Redis, OpenSearch, Varnish e RabbitMQ, cada um ligável e desligável no
.envdo projeto
No macOS, o Warden sincroniza o código para dentro dos containers com Mutagen em vez de um bind mount simples. Essa é a diferença entre um ambiente utilizável e um em que toda página leva vários segundos.
Primeira execução
Instale o Docker e o Warden, depois suba os serviços globais uma vez:
warden svc up
Dentro da pasta do projeto, crie o arquivo de ambiente e um certificado para o domínio:
cd ~/Sites/myshop
warden env-init myshop magento2
warden sign-certificate myshop.test
O env-init escreve um arquivo .env. Esse arquivo é a configuração real da stack, então leia e ajuste antes de iniciar qualquer coisa.
O arquivo .env
Um exemplo resumido para um projeto 2.4.8:
WARDEN_ENV_NAME=myshop
WARDEN_ENV_TYPE=magento2
WARDEN_WEB_ROOT=/
TRAEFIK_DOMAIN=myshop.test
TRAEFIK_SUBDOMAIN=app
WARDEN_DB=1
WARDEN_OPENSEARCH=1
WARDEN_ELASTICSEARCH=0
WARDEN_VARNISH=1
WARDEN_RABBITMQ=1
WARDEN_REDIS=1
PHP_VERSION=8.3
COMPOSER_VERSION=2
MARIADB_VERSION=11.4
OPENSEARCH_VERSION=2.12
RABBITMQ_VERSION=3.13
REDIS_VERSION=7.2
VARNISH_VERSION=7.4
Os nomes exatos das variáveis e as versões disponíveis dependem da release do Warden que você tem, então confira o arquivo gerado em vez de copiar este. O hábito importante é definir cada versão igual ao que a produção roda e commitar o .env no repositório para todos usarem a mesma stack.
Se você não precisa de um serviço, desligue. Varnish e RabbitMQ consomem memória, e muitas tarefas não precisam deles. Você pode religá-los quando for trabalhar com full page cache ou consumers de queue.
Iniciando o ambiente
warden env up
warden shell
O warden env up baixa as imagens e inicia os containers do projeto. O warden shell abre um shell no container PHP como usuário www-data, na raiz do projeto. Tudo que toca no Magento roda de lá: Composer, bin/magento, PHPUnit.
Para comandos avulsos eu prefiro não abrir um shell interativo:
warden shell -c "bin/magento cache:flush"
warden shell -c "composer install"
Evite rodar o bin/magento no host. O PHP do host é de outra versão e tem outras extensões, e os hostnames db, redis e opensearch só resolvem dentro da rede do Docker. Rodar o docker exec direto também funciona, mas é fácil acabar como root e criar arquivos que o usuário do PHP-FPM não consegue gravar depois.
Instalando um Magento novo
Para um projeto novo, crie-o com Composer de dentro do shell e depois rode o instalador apontando para os hostnames dos containers:
bin/magento setup:install \
--backend-frontname=backend \
--db-host=db --db-name=magento \
--db-user=magento --db-password=magento \
--search-engine=opensearch \
--opensearch-host=opensearch --opensearch-port=9200 \
--opensearch-index-prefix=magento2 --opensearch-enable-auth=0 \
--amqp-host=rabbitmq --amqp-port=5672 \
--amqp-user=guest --amqp-password=guest \
--session-save=redis --session-save-redis-host=redis \
--session-save-redis-db=2 \
--cache-backend=redis --cache-backend-redis-server=redis \
--cache-backend-redis-db=0 \
--page-cache=redis --page-cache-redis-server=redis \
--page-cache-redis-db=1 \
--http-cache-hosts=varnish:80
bin/magento config:set web/unsecure/base_url https://app.myshop.test/
bin/magento config:set web/secure/base_url https://app.myshop.test/
bin/magento deploy:mode:set developer
As credenciais de banco magento / magento são o padrão do Warden. Toda opção acima acaba em app/etc/env.php, que é tratado com mais detalhe em env.php e config.php explicados.
Importando um projeto existente
Na maior parte do tempo você entra num projeto que já existe. Os passos são:
- Clone o repositório e rode
warden env up - Rode
composer installdentro do container - Importe um dump de banco sanitizado
- Crie ou ajuste o
app/etc/env.phppara os hostnames dos containers - Corrija as base URLs e rode
setup:upgrade
A importação do banco manda o dump em stream para o container do banco:
gunzip -c ~/dumps/myshop.sql.gz | warden db import
Depois, dentro do shell:
bin/magento setup:upgrade
bin/magento indexer:reindex
bin/magento cache:flush
Nunca importe um dump bruto de produção sem limpar. E-mails de clientes, credenciais de gateway de pagamento e endpoints de integração em core_config_data podem fazer uma loja local mandar e-mails de verdade ou chamar APIs reais. O artigo sobre sanitizar o banco mostra o que remover.
Xdebug
O Warden roda um segundo container PHP-FPM com o Xdebug carregado. As requisições só vão para ele quando o cookie XDEBUG_SESSION está presente, então os carregamentos normais de página continuam rápidos. Instale uma extensão de navegador que define o cookie, configure o PhpStorm com um server cujo nome combine com o domínio e cujo mapeamento de caminho aponte a raiz do projeto para /var/www/html, e comece a escutar.
Para comandos CLI, use o debug shell:
warden debug
O setup completo do PhpStorm e os motivos comuns para os breakpoints serem ignorados estão em depurando o Magento 2 com Xdebug.
Hábitos do dia a dia
Mantenha o developer mode e os caches certos
O developer mode mostra erros e gera código sob demanda. Mantenha a maioria dos caches ativos mesmo em developer mode e desative só os contra os quais você está trabalhando, normalmente layout, block_html e full_page para trabalho de frontend. Uma loja com todos os caches desligados é mais lenta do que precisa e esconde bugs relacionados a cache.
Limpe o código gerado com intenção
Quando a assinatura de um construtor muda, apague o generated/code das classes afetadas ou a pasta inteira. Limpar tudo depois de toda mudança desperdiça tempo, já que o Magento regenera na próxima requisição.
Pare o que você não está usando
Cada projeto com OpenSearch, MariaDB e RabbitMQ pode usar vários gigabytes de RAM. Rode warden env down quando trocar de projeto. O banco fica num volume do Docker, então sobrevive a uma parada.
Leia o mail catcher
Os e-mails transacionais vão para o mail catcher global em webmail.warden.test. É o lugar para testar templates de e-mail de pedido e de customer sem enviar nada de verdade.
Problemas comuns
- O navegador diz que o certificado é inválido. A root CA do Warden não foi confiada, ou o certificado foi assinado para um domínio diferente do
TRAEFIK_DOMAIN. Rode osign-certificatede novo com o nome certo e reinicie. - Loop de redirect ou redirect para a produção. As base URLs em
core_config_dataainda apontam para o domínio no ar. Atualize comconfig:setou direto no banco. - O container do OpenSearch encerra. Em geral é memória. Dê mais RAM ao Docker ou reduza o heap na configuração do serviço.
- Arquivos pertencentes ao root. Alguém rodou comandos como root no container. Corrija a propriedade e volte para o
warden shell.
Com o ambiente estável, o mesmo setup de containers é uma boa base para rodar testes localmente. Veja testes de integração no Magento 2 para rodar o framework de testes contra um banco separado na mesma stack.
FAQ
O Warden é melhor que docker-magento ou DDEV para Magento 2?
Os três funcionam. O Warden dá a cada projeto a própria stack atrás de um proxy Traefik compartilhado com TLS local, e o arquivo .env dele mantém as versões dos serviços próximas da produção. Escolha o que o seu time vai de fato manter.
Por que o Magento é lento no Docker no macOS?
Bind mounts entre o macOS e a VM Linux são lentos para uma base de código com dezenas de milhares de arquivos. O Warden sincroniza os arquivos com Mutagen no macOS para evitar isso. Dê também memória suficiente ao Docker, já que o OpenSearch e o MySQL precisam dela.
Devo rodar o bin/magento no host ou dentro do container?
Dentro do container. A versão do PHP, as extensões e hostnames como db e redis só existem lá. Use warden shell ou warden shell -c com o comando.
Posso usar um dump do banco de produção localmente?
Pode, mas sanitize antes. Remova ou anonimize dados de clientes, mude as base URLs e desative as configurações de pagamento, e-mail e integrações para a cópia local não conseguir falar com serviços reais.
Atendo como freelancer em Magento e Adobe Commerce, incluindo a montagem de ambientes locais para times. Se você precisa de ajuda com isso, fale comigo.
Artigos relacionados
Magento 2 em production mode: como mudar e fazer o deploy
O que o production mode do Magento 2 muda, como trocar com segurança e uma sequência de deploy para o 2.4.8 que tira compilação e static deploy do downtime.
Backup e restore no Magento 2: o que salvar e como
Como fazer backup e restore de uma loja Magento 2: dumps de banco que importam sem erro, mídia, env.php e a chave de criptografia, cópias offsite e restores testados.
Sanitizar o banco do Magento 2 para staging e ambiente local
Como copiar o banco de produção do Magento 2 para staging com segurança: anonimize clientes e pedidos, desative e-mails e integrações, troque segredos e bloqueie indexação.
Deploy do Magento 2 sem downtime em um único servidor
Um deploy sem downtime para o Magento 2.4 em um servidor: build numa pasta de release, compile fora do live, troca de symlink e rollback em segundos.