Quando eu postei o tutorial completo sobre Docker, muitos anos atrás, algumas pessoas comentaram pedindo mais detalhes a respeito desse trecho aqui que comentei no post:
Bom, depois de.. *check notes*, mais de OITO anos, chegou a hora de eu detalhar como funciona isso, afinal, antes tarde do que mais tarde, certo? Então vamos lá.
O Docker, como vocês bem sabem se vocês leram o post referido acima, consegue isolar os processos em containers que compartilham o mesmo kernel, mas cada processo deve ser um container próprio, isolado. Apesar disso, é possível estabelecer um setup onde os containers comunicam entre si, e também com o mundo exterior.
No caso desse blog que vos fala, conforme referido no trecho citado acima, temos três peças (2 rodando em containers) se comunicando entre si:
- Nginx - Que é instalado na máquina principal, e fica escutando na porta 80 e 443, e por onde a maior parte dos usuários se conecta
- MySQL - Que escuta na clássica porta 3306, mas que NÃO é exposta para fora de container algum, em nenhuma porta. Ficando mais "isolado", por assim dizer.
- PHP-FPM - Que escuta na porta 9000 dentro do container, mas é exposta apenas localmente (e isso é importante!) dentro da máquina como porta 2004. A ideia é que o Nginx consiga usar a porta 2004 rodando no host 127.0.0.1 (ou seja, o melhor host, o localhost!) para se comunicar com o PHP-FPM.
Note que em nenhum momento eu mencionei que há um link (que usando o legacy linking system seria algo tipo -l mysql:mysql
) entre o PHP-FPM e o MySQL. Mas, como você pode imaginar, por causa do WordPress tal conexão se faz necessária, caso contrário esse blog não funcionaria pois o PHP nunca conseguiria se comunicar com o MySQL (afinal, os containers são isolados, certo?).
Para fazer isso, usamos o que o Docker chama de "Docker User-Defined Network", ou Rede Docker definida pelo usuário, em tradução livre. O que é isso? Imagine que cada container Docker - apesar de rodar um único processo cada - é como se fosse uma rede de computadores. Com base no que sabemos até então, temos a seguinte situação:
Um rede definida pelo usuário, no Docker, nada mais é do que uma rede DENTRO do próprio Docker. No caso desse blog, temos uma rede no Docker chamada fjorgemota-com
, e a estrutura fica mais ou menos assim:
O que que isso implica, necessariamente? Implica que, assim como no caso da rede LOCAL na sua casa, onde seu celular consegue se comunicar com seu computador e vice-versa, cada container DENTRO da rede fjorgemota-com
também consegue se comunicar um com o outro. Porém, da mesma forma que alguém externo à rede local da sua casa NÃO consegue se conectar diretamente ao seu computador ou ao seu celular, um container que esteja FORA da rede fjorgemota-com
também não consegue se comunicar nem com o MySQL, e nem com o PHP.
Entretanto, assim como você PODE expor o seu computador conectado na rede interna da sua casa para o mundo exterior, o fato de um container estar dentro de uma rede definida por usuário também não o impossibilita de expor portas da mesma forma, como no caso do container do PHP-FPM cuja porta 9000 é exposta como 2004 dentro do servidor.
Tutorial
Como a configuração do Nginx pode variar DEMAIS de máquina para máquina, vamos fazer uma configuração mais simples aqui, usando o Caddy, que é bem mais simples de configurar (bastando um simples arquivo de configuração!). Vamos ao tutorial:
1) Baixe e instale o Docker (importante ter uma máquina de 64 bits, pois é o único ambiente no qual o Docker efetivamente roda..)
2) Baixe e instale o Caddy para sua máquina (basta clicar no botão de Download na página, você não precisa de nenhum plugin extra)
3) Crie uma rede definida por usuário, usando docker network create tutorial-fjorgemota-com
. A saída desse comando deve ser um simples hash, conforme mostrado abaixo:
4) Agora, vamos criar os containers! Primeiro, inicialize o MySQL usando docker run --name bd-tutorial-fjorgemota-com --network tutorial-fjorgemota-com --network-alias mysql -e
MYSQL_DATABASE
=tutorial_blog -e MYSQL_ROOT_PASSWORD=12345678 -d mysql
. A saida do Docker deve ser algo assim:
5) Baixe o WordPress e descompacte-o para uma pasta chamada wordpress
. No Linux, você pode usar wget -O wordpress.zip https://br.wordpress.org/latest-pt_BR.zip && unzip wordpress.zip
, conforme mostra a saída abaixo:
7) Crie um arquivo chamado Dockerfile
para preparar a imagem do PHP-FPM para ter as extensões necessárias para rodar o WordPress. O arquivo deve ter o seguinte conteúdo:
FROM php:8.3-fpm
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
libxpm-dev \
libwebp-dev \
libxslt1-dev \
libzip-dev \
libonig-dev \
libtidy-dev \
libicu-dev \
imagemagick \
libmagickwand-dev \
less \
&& pecl install imagick \
&& pecl install apcu \
&& docker-php-ext-configure gd --with-freetype --with-jpeg --with-xpm --with-webp \
&& docker-php-ext-install mbstring mysqli zip bcmath exif xsl intl pdo_mysql gd tidy \
&& docker-php-ext-enable imagick apcu \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
Para contextualização, aqui estamos apenas algumas dependêcnias necessárias para a execução do WordPress, uma vez que a imagem php:8.3-fpm
vem sem as extensões necessárias instaladas/ativadas.
8) Construa a imagem acima usando docker build -t tutorial-php-fjorgemota-com .
O comando deve mostrar algo assim:
9) Rode o container do PHP-FPM usando essa pasta do wordpress como volume, e mapeando para /wordpress
. Sem entrar na pasta wordpress
, criada acima, o comando fica assim docker run -v $(pwd)/wordpress:$(pwd)/wordpress --network tutorial-fjorgemota-com -p 127.0.0.1:2004:9000 -d tutorial-php-fjorgemota-com
Esse comando deve ter um simples hash como saída, conforme mostrado abaixo:
Com isso, você deve ter o container rodando PHP-FPM rodando na mesma rede do container do MySQL. E o PHP-FPM deve estar exposto na porta 2004 no seu computador.
7) Agora, vamos configurar o Caddy para se conectar no PHP-FPM na sua máquina. Na mesma pasta onde está a pasta wordpress
, crie um arquivo chamado Caddyfile
com o seguinte conteúdo:
:8080 {
root * wordpress
encode gzip
php_fastcgi 127.0.0.1:2004
file_server
}
8) Então, execute caddy run Caddyfile
Se tudo deu certo, você deve ver algo assim:
[fernando@fernando-ryzen ~]$ caddy run
2024/07/07 22:39:08.186 INFO using adjacent Caddyfile
2024/07/07 22:39:08.187 WARN Caddyfile input is not formatted; run 'caddy fmt --overwrite' to fix inconsistencies {"adapter": "caddyfile", "file": "Caddyfile", "line": 2}
2024/07/07 22:39:08.188 INFO admin admin endpoint started {"address": "localhost:2019", "enforce_origin": false, "origins": ["//127.0.0.1:2019", "//localhost:2019", "//[::1]:2019"]}
2024/07/07 22:39:08.188 INFO tls.cache.maintenance started background certificate maintenance {"cache": "0xc000429880"}
2024/07/07 22:39:08.188 INFO http.log server running {"name": "srv0", "protocols": ["h1", "h2", "h3"]}
2024/07/07 22:39:08.188 INFO autosaved config (load with --resume flag) {"file": "/home/fernando/.local/share/caddy/autosave.json"}
2024/07/07 22:39:08.188 INFO serving initial configuration
2024/07/07 22:39:08.189 WARN tls storage cleaning happened too recently; skipping for now {"storage": "FileStorage:/home/fernando/.local/share/caddy", "instance": "cf543b53-950d-435f-8cfc-59ea67aff4c5", "try_again": "2024/07/08 22:39:08.189", "try_again_in": 86399.99999981}
2024/07/07 22:39:08.189 INFO tls finished cleaning storage units
9) Acesse http://127.0.0.1:8080 no seu navegador. Você verá a tela de instalação do WordPress:
Clique em "Vamos lá!"
10) Nessa tela de configuração do banco de dados:
Informe os seguintes dados:
- Nome do banco de dados: tutorial_blog
- Nome de usuário: root
- Senha: 12345678
- Servidor do banco de dados: mysql
- Prefixo da tabela: wp_
Clique em "Enviar"
11) O WordPress te pedirá para criar um arquivo wp-config.php
com o código que ele passar:
Entre na pasta wordpress
e crie o arquivo wp-config.php
com aquele conteúdo informado.
Clique em "Instalar"
12) O WordPress te pedirá mais algumas informações, agora a respeito do site. Preencha com os dados que bem entender:
Clique em "Instalar WordPress"
13) O WordPress estará instalado:
Agora você tem o Caddy conectando ao PHP-FPM rodando dentro de um container Docker, e se comunicando com o MySQL em outro container Docker dentro da mesma rede.
Conclusão
Como dá pra ver, mesmo com o uso de containers, não há a necessidade de se preocupar em colocar TUDO dentro do Docker. É possível ter uma certa flexibilidade, ainda mais em termos de serviços de rede (como o MySQL ou o PHP-FPM).
Naturalmente, entretanto, ter mais containers rodando no Docker tende a facilitar mais a vida em alguns cenários. Em ambientes de desenvolvimento, por exemplo, quando você usa algo como o Docker Compose, todo o processo de instalação e configuração de um projeto se resume a alguns poucos comandos. Não há a necessidade de, por exemplo, pedir pela instalação de softwares adicionais (como o Caddy, no caso desse post), nem de configurações extras.
Portanto, como tudo na vida, decidir como estruturar sua aplicação é uma questão de custo benefício. No meu caso, o blog roda dessa forma (só que usando Nginx em vez do Caddy) pois isso me facilita a instalação e configuração de outros projetos, além do blog. Por exemplo, posso usar o Gitea (que é uma alternativa mais moderna ao Gogs, sobre o qual já falei aqui no blog), o Dokku e outros serviços tendo apenas um servidor web como "porta principal" do servidor. Logo, acaba valendo mais a pena ter tudo centralizado em uma única configuração do Nginx.
E você? Como gosta de estruturar os seus projetos? Compartilhe nos comentários!
Deixe um comentário