18
Ambiente PHP e Ngnix com Docker
Há alguns dias atrás precisei criar ou recriar um ambiente PHP semelhante ao ambiente de produção, em produção era utilizado o PHP na versão 7.2, com o Nginx na versão 1.14.0 e também o PHP-FPM que é o cara responsável por interpretar o código PHP já que o Nginx não consegue fazer isso, mais isso tudo diretamente pelo sistema usando unix sockets, tudo instalado diretamente no sistema.
Porém tive algumas dificuldades para criar o ambiente usando o fastcgi e então resolvi escrever este artigo para ajudar outras pessoas que venham a precisar e também para o meu eu do futuro que pode vir a precisar fazer algo semelhante.
Bem, primeiro precisamos criar um Dockerfile na raiz do projeto para termos uma imagem com o nosso projeto php, e já com o php-fpm. Podemos ter o Dockerfile o seguinte conteúdo:
FROM php:7.2.24-fpm
COPY . /var/www/html
WORKDIR /var/www/html
RUN chmod -R 777 /var/www/html
EXPOSE 9000
CMD ["php-fpm"]
FROM php:7.2.24-fpm
: Com isso vamos ter uma imagem com o php-fpm na versão 7.2.24.COPY . /var/www/html
: Aqui fazemos a cópia de todos os arquivos do projeto (.
) para a pasta/var/www/html
do container.WORKDIR /var/www/html
: E precisamos mudar o diretório de trabalho para que seja o primeiro e consigamos ter acesso aos arquivos nesse container.RUN chmod -R 777 /var/www/html
: Esse comando é para evitar possíveis erros caso o projeto precise criar ou gerenciar arquivos dentro do container.EXPOSE 9000
: Aqui liberamos a porta 9000 para podermos acessar de fora, ou no caso em outros conatiners.CMD ["php-fpm"]
: Por fim, executamos o php-fpm.
Agora que temos o Dockerfile, precisamos criar um docker-compose.yml
na raiz do projeto para usarmos o Dockerfile criado anteriormente. E nesse docker-compose temos o seguinte conteúdo:
version: '3.7'
services:
php:
build:
context: .
dockerfile: Dockerfile
container_name: dev-site
volumes:
- ./nginx/php-fpm.conf:/etc/php/7.2/fpm/php-fpm.conf
networks:
- site-network
nginx:
image: nginx:1.14.0
container_name: dev-nginx
ports:
- "8001:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/sites.conf/:/etc/nginx/conf.d/default.conf
command: [ nginx-debug, '-g', 'daemon off;' ]
networks:
- site-network
networks:
site-network:
driver: bridge
services
: Temos dois serviços, um para o PHP e o outro para o Nginx.Serviço
php
: Nesse bloco fazemos o build na imagem a partir do nosso Dockerfile criado anteriormente. Adicionamos um nome ao container para facilitar a utilização do mesmo. Também fizemos um bind do arquivo de configuração do php-fpm (php-fpm.conf
) para o container. E por fim adicionamos a rede que é criada no bloconetworks
que é o último bloco do arquivo para podermos fazer a comunicação entre ambos os containers.Serviço
Nginx
: Nesse bloco usamos uma imagem pronta do Nginx na versão 1.14.0 que é a versão que estava sendo executada em produção, também adicionamos um nome para facilitar o uso. E liberamos a porta8001
da máquina para a porta80
do container, isso porque podemos já utilizar a porta 80 da máquina por algum outro motivo. E adicionamos os volumes, na verdade fazemos apenas o bind donginx.conf
e dosites.conf
que ambos estão dentro da pastanginx
na raiz do projeto com o/etc/nginx/nginx.conf
e/etc/nginx/conf.d/default.conf
respectivamente. Você pode estar se perguntando sobre esses arquivos, mas calma, ainda vamos ver esses arquivos mais adiante. Também executamos um comando para habilitar o modo dedebug
do nginx para podemos ver possíveis problemas quando executarmos o mesmo. E por fim a rede para comunicação com o container PHP.networks
: Criamos esse bloco apenas para criar a rede e conseguimos comunicar ambos os containers.
Como você deve ter visto anteriormente fazemos o bind da configuração do Nginx, isso porque nossa configuração pode ser diferente da configuração default. Mas nesse ponto mantive quase a mesma configuração do Nginx:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
load_module modules/ngx_http_image_filter_module.so;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
Não vou entrar muito nessa parte de configuração do Nginx porque penso que foge um pouco do escopo deste artigo.
E chegamos a outro ponto importante de toda essa configuração que é a comunicação entre o Nginx e o php-fpm, e essa configuração pode ser feita de duas formas.
A primeira forma é usando o proxy reverso do Nginx, e para isso utilizamos o proxy_pass
para encaminhar a requisição para o nosso outro container.
Então naquele arquivo sites.conf
que fizemos o bind para o container:
- ./nginx/sites.conf/:/etc/nginx/conf.d/default.conf
Teríamos o seguinte conteúdo:
upstream container {
least_conn;
server dev-site:9000;
}
server {
listen 80;
location / {
proxy_pass http://container;
}
}
Explicando: Aqui criamos um upstream
com o nome container
, e esse basicamente aponta para o nosso container, que pode ser acessado usando o nome que criamos lá no docker-compose dev-site
e indicando a porta 9000 que foi a porta que liberamos no container (EXPOSE 9000
). E em seguida, no bloco server
passamos para o proxy_pass o upstream
criado acima porém usando o HTTP, isso porque aqui estamos enviando via HTTP.
A outra forma, e nesse caso a mais interessante é usando o fastcgi que é um protocolo para a comunicação entre o PHP e o Nginx. Também não vou entrar nesse foco aqui. Teremos a seguinte configuração naquele arquivo sites.conf
(no lugar da configuração anterior):
server {
listen 80;
root /var/www/html;
location / {
include fastcgi_params;
fastcgi_pass dev-site:9000;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
}
}
Nesse caso não teremos o upstream
, apenas o bloco server
e os pontos importantes aqui são as linhas:
include fastcgi_params;
: que inclui os outros parâmetros, que ficam no arquivofastcgi_params
dentro dos arquivos de configuração do Nginx.fastcgi_pass dev-site:9000;
: Essa linhas é responsável pelo direcionamento das requisições para o php-fpm, por isso indicamos o nome e a porta do nosso container do phpdev-site:9000
.fastcgi_param SCRIPT_FILENAME $document_root/index.php;
: E aqui indicamos qual o arquivo deve ser executado no container do php.
Agora é só subir os containers usando o comando docker-compose up
estando dentro da pasta do projeto e logo em seguida acessar o endereço http://localhost:8001 no navegador.
18