DEV Community

Jonilson Sousa
Jonilson Sousa

Posted on

4

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.

Dockerfile

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"]
Enter fullscreen mode Exit fullscreen mode

Explicando o Dockerfile

  • 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.

docker-compose

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
Enter fullscreen mode Exit fullscreen mode

Explicando o docker-compose

  • 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 bloco networks 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 porta 8001 da máquina para a porta 80 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 do nginx.conf e do sites.conf que ambos estão dentro da pasta nginx 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 de debug 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.

Nginx.conf

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/*;
}
Enter fullscreen mode Exit fullscreen mode

Não vou entrar muito nessa parte de configuração do Nginx porque penso que foge um pouco do escopo deste artigo.

Sites

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.

Proxy reverso

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
Enter fullscreen mode Exit fullscreen mode

Teríamos o seguinte conteúdo:

upstream container {
    least_conn;
    server dev-site:9000;
}

server {
    listen 80;
    location / {
        proxy_pass http://container;
    }
}
Enter fullscreen mode Exit fullscreen mode

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.

Fastcgi

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;
    }
}
Enter fullscreen mode Exit fullscreen mode

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 arquivo fastcgi_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 php dev-site:9000.

  • fastcgi_param SCRIPT_FILENAME $document_root/index.php;: E aqui indicamos qual o arquivo deve ser executado no container do php.

Conclusão

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.

Heroku

Deploy with ease. Manage efficiently. Scale faster.

Leave the infrastructure headaches to us, while you focus on pushing boundaries, realizing your vision, and making a lasting impression on your users.

Get Started

Top comments (0)

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

👋 Kindness is contagious

If this article connected with you, consider tapping ❤️ or leaving a brief comment to share your thoughts!

Okay