Alison Juliano | Desenvolvedor Web, Full-Stack Developer

Docker: Ambiente de desenvolvimento PHP (Laravel) com Nginx e MySql.

Contate-me caso precise de um desenvolvedor

Tecnologias utilizadas:

  • PHP
  • LARAVEL
  • JAVASCRIPT
  • VUEJS
  • INTERTIAJS
  • TYPESCRIPT
  • QUASAR

Neste post vamos aprender a criar um ambiente de desenvolvimento PHP no docker, utilizando o Nginx como webserver, MySql como nosso banco de dados e para teste um projeto Laravel. Utilizaremos o docker-compose e um Dockerfile para isso.

Com o docker-compose estou rodando três containers  cada um com: PHP (junto ao composer, xdebug e configurações), Nginx e o MySql.

O proposito deste guia é apenas te dar alguma referencia e ajuda, não se sinta preso(a) nas mesmas configurações.

Índice

  1. Repositório GITHUB
    O ambiente já pronto no meu repositório do GITHUB.
  2. Pré-requisitos
    Antes de fazer qualquer coisa vamos instalar todos os pré-requisitos.
  3. Arvore de diretórios
    Onde seus projetos, backup e configurações vão estar.
  4. Makefile [opcional]
    Automatizando seu ambiente com um makefile.
  5. Configurando o php.dockerfile
    Instalando xdebug, composer, bibliotecas e setando configurações.
  6. Configurando o Nginx com certificado SSL.
    Configurando PHP-FPM para o Nginx, gerando um certificado SSL e o configurando no nosso servidor.
  7. docker-compose.yml
    Construindo nossas imagens nos containers.
  8. Rodando e testando nosso projeto

 


Repositório no GITHUB

 

Um método pratico e rápido para conseguir esse ambiente é clonando meu repositório no GITHUB, para isso você pode fazer o download em zip de todo o projeto, ou utilizar o GIT para fazer o clone dele.

Para realizar o clone do repositório utilizando o GIT, basta abrir seu terminal, navegar até o local onde deseja em que seu ambiente esteja e utilize o comando abaixo:

git clone https://github.com/julianoaj/docker-php-laravel-nginx-mysql

Pronto! Feito isso basta abrir seu navegador e entrar no seu localhost.


Instalando os pré-requisitos

 

Esse ambiente foi feito no windows, mas o docker funcionará em qualquer sistema operacional, basta seguir as orientações de instalação na documentação oficial:

Para checar se tudo foi instalado com sucesso basta entrar com os seguintes comandos no seu terminal:

docker-compose 
docker -v

[docker-compose] vai printar todos os comandos do docker-compose, [docker -v] vai printar a versão do docker.

Ferramentas opcionais:


Arvore de diretórios

 

Antes de começarmos configurar nosso ambiente precisamos de uma arvore de diretórios. Aqui você escolherá onde seus projetos, backups e configurações vão estar.

Minha arvore de diretórios:

\---environmentProject
    |   docker-compose.yml
    |   Makefile
    |   nginx.dockerfile
    |   php.dockerfile
    |   README.md
    |
    +---confs
    |   +---Mysql_db
    |   |       backup.ibd
    |   |
    |   +---servers
    |   |       server.conf
    |   |
    |   \---ssl
    |           localhost.crt
    |           localhost.key
    |
    \---projects
        \---www
                index.php

Makefile

 

Em vez de digitar comandos complexos no seu terminal você pode usar um Makefile para tornar isso mais fácil.

O pré-requisito para usar um Makefile é instalar o comando make que funciona em qualquer sistema operacional, basta seguir o manual de instalação na sessão de pré-requisitos.

Com o comando make instalado, eu não recomendo, mas você pode clonar meu repositório do github  e usar meu Makefile com alguns comandos de atalhos já definidos.

Para checar meu Makefile e a tabela de comandos que eu fiz é só dar uma passada no meu repositório do github.


Configurando o php.dockerfile

 

Está na hora de construirmos nosso container PHP com o xdebug, composer e configurações dentro de um Dockerfile, para isso precisamos criar o arquivo no nosso diretório raiz /environmentProject/php.dockerfile.

Dentro do arquivo vamos setar nossa versão do PHP. A versão que iremos usar aqui será a do PHP 7.4 FPM, para conseguirmos usar essa versão dentro do nosso Dockerfile precisamos verificar a tag dela no dockerhub. Com a tag em mãos a primeira linha do nosso Dockerfile deverá ficar assim:

FROM php:7.4-fpm

Lista de tags você pode verificar aqui!

Core Extensions:

Seguindo a versão vamos instalar as core extensions, ou seja, extensões necessárias para nosso ambiente:

RUN apt-get update && apt-get install -y \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        libpng-dev \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) gd \
    && docker-php-ext-install mysqli pdo pdo_mysql && docker-php-ext-enable pdo_mysql

Dependendo da versão do PHP que você vai usar algumas extensões já vem instaladas. Para verificar a lista de todas as extensões já instaladas na versão do PHP que você usou, no seu terminar use o comando docker run –rm php:7.4-fpm php -m

PECL extensions:

Está na vez de algumas extensões para performance e utilidade, porem não necessárias, para isso utilizaremos o PECL, um repositório de extensões do PHP.
Aqui instalaremos o xdebug, libmencached e o zlib1g. Com isso adicionaremos mais algumas linhas no nosso dockerfile:

RUN pecl install xdebug-3.0.4 \
    && docker-php-ext-enable xdebug
RUN apt-get install -y libmemcached-dev zlib1g-dev \
    && pecl install memcached-3.1.5 \
    && docker-php-ext-enable memcached
Packages:

Para instalação de pacotes utilizaremos o composer, junto ao zip e unzip:

RUN apt-get install zip unzip \
    && curl -sS https://getcomposer.org/installer -o composer-setup.php \
    && php composer-setup.php --install-dir=/usr/local/bin --filename=composer \
    && unlink composer-setup.php
Configurações:

Aqui vamos setar nosso timezone e ativaremos o opcache para performance do PHP:

RUN echo 'date.timezone="America/Sao_Paulo"' >> /usr/local/etc/php/conf.d/date.ini \
    && echo 'opcache.enable=1' >> /usr/local/etc/php/conf.d/opcache.conf \
    && echo 'opcache.validate_timestamps=1' >> /usr/local/etc/php/conf.d/opcache.conf \
    && echo 'opcache.fast_shutdown=1' >> /usr/local/etc/php/conf.d/opcache

Você pode verificar a lista de tags para timezone aqui.


Configurando o Nginx FastCGI com certificado SSL para o PHP e o Laravel

 

Para conseguirmos utilizar o PHP e o Laravel com Nginx precisamos configurar o FastCGI e algumas outras coisas. Vamos quebrar isso em dois passos:

  1. Gerar o certificado SSL [opcional]
    Você pode usar meu Makefile para gerar um certificado SSL usando apenas o comando make gen-ssl no seu terminal (caso você seja um usuário de windows) ou siga os passos deste GUIA.
  2. Server server.conf
    Para gerenciarmos nosso servidor do Nginx precisamos criar um arquivo do tipo .conf e vamos cria-lo em: /environmentProject /confs /servers /server.conf

Edite o server.conf e configure o seu servidor para que ouça a porta 80 e a 443 (porta ssl) do container, coloque o caminho de localização do seu certificado SSL na frente de ssl_certificate e ssl_certificate_key e por ultimo passe todas as configurações necessárias para a utilização do Nginx FastCGI do PHP-FPM. Exemplo:

  server {
    ############# Ports #################
    listen 80;
    listen 443 ssl;
    #####################################
    root /var/www/projects/;
    ########## SSL CERTIFICATE ##########
    ssl_certificate /var/www/ssl/localhost.crt;
    ssl_certificate_key /var/www/ssl/localhost.key; 
    #####################################
    autoindex on; 
    ########## FAST CGI CONFIG ##########
    location ~ \.php$ {
      fastcgi_index index.php;
      fastcgi_pass php:9000;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      include fastcgi_params;
    }
  }

Isso deverá ser o suficiente para rodar sua aplicação PHP nativa. Com o Laravel seu server.conf deverá ficar como:

server {
    listen 80;
    listen 443 ssl;
    server_name example.com;
    root /var/www/projects/example-app/public;
    ssl_certificate /var/www/ssl/localhost.crt;
    ssl_certificate_key /var/www/ssl/localhost.key; 
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff"; 
    index index.php; 
    charset utf-8; 
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    } 
    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; } 
    error_page 404 /index.php; 
    location ~ \.php$ {
        fastcgi_index index.php;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    } 
    location ~ /\.(?!well-known).* {
        deny all;
    }
}

Essa configuração foi tirada diretamente da documentação do Laravel.


docker-compose.yml

 

Chegou a hora de juntarmos tudo usando o docker-compose.

Eu não vou entrar em detalhes neste guia sobre versões, serviços, volumes, etc… caso fique com duvidas sobre alguma coisa de uma olhada na documentação.

Crie o arquivo do tipo .yml na seguinte localização: /environmentProject/docker-compose.yml.
Edite ele e vamos começar:

Versão:

A primeira linha do nosso docker-compose.yml deverá ser a versão do docker-compose que usaremos, no nosso caso iremos utilizar a ultima já lançada:

version: "3.9"
Serviços

Seguindo a linha de versionamento vamos aos serviços. Os services nada mais são do que containers, no nosso caso levantaremos 3 containers: Nginx, PHP e o MySql. Vamos quebrar tudo em etapas:

Um arquivo docker-compose.yml deve seguir todas as normas de indentação, caso contrario obteremos erros. De uma checada na documentação caso fique com duvidas.

  1. Nginx

    Aqui estamos construindo nosso container do Nginx. Apenas preste atenção nas configurações de volumes e portas, que serão onde você deverá colocar a localização da sua pasta de projetos, certificados e servidores. Esses caminhos serão compartilhados diretamente com o container. Sua configuração deverá se parecer com isso:

     services: 
          web-server:
            image: nginx:1.21.1
            container_name: webdev-nginx
            ports:
              - "80:80"
              - "443:443"
            networks:
              - web-dev
            volumes:
              - ./confs/servers/:/etc/nginx/conf.d/
              - ./projects:/var/www/projects
              - ./confs/ssl/:/var/www/ssl

    Com essa configuração de volumes você poderá configurar qualquer coisa sem a necessidade de ficar entrando no seu container.

  2. PHP

    volumes desse container deve ser o mesmo que o projects do Nginx.

        php:
          build:
            dockerfile: ./php.dockerfile
            context: .
          image: php7.4-fpm
          container_name: webdev-php
          volumes: 
            - "./projects:/var/www/projects"
          ports: 
            - "9000:9000"
          networks: 
            - web-dev
  3. MySql

    Aqui vamos setar nossas configurações de banco de dados. Em MYSQL_PASSWORD é onde você deverá colocar a sua senha, MYSQL_DATABASE o nome banco de dados criado na inicialização, MYSQL_USER nome de usuário. Caso queira mudar as portas fique a vontade também.

        db:
          image: mysql:8.0.26
          container_name: webdev-mysql
          volumes: 
            - ./confs/mysql_db:/var/lib/mysql
          command: --default-authentication-plugin=mysql_native_password
          environment:
            MYSQL_ROOT_PASSWORD: root
            MYSQL_DATABASE: test_db
            MYSQL_USER: devuser
            MYSQL_PASSWORD: devpass
          ports:
            - "3306:3306"
          networks: 
            - web-dev
  4. Network
    Nossa network vai trazer todos containers juntos em uma mesma rede e a configuração para isso é simples.

          networks: 
            web-dev:
              driver: bridge

Rodando e testando nossa aplicação

 

Com tudo já configurado chegou a hora de darmos vida ao nosso ambiente.

No seu terminal navegue até o diretório  /environmentProject/ e passe o comando para o docker-compose começar a construir os containers:

docker-compose build

Assim que a execução do comando for finalizada entre com o comando para começar a rodar os containers:

docker-composer up -d

Feito isso basta entrar no seu localhost e pronto!

Com tudo ja rodando, chegou a hora de testarmos nossa conexão com o banco de dados, para isso crie um arquivo dentro da pasta projects chamado de index.php (/environmentProject /projects /index.php). Dentro do arquivo cole o código a baixo:

<?php
$host = 'db';
$user = 'devuser';
$password = 'devpass';
$db = 'test_db';

$conn = new mysqli($host, $user, $password, $db);
if ($conn->connect_error){
    echo 'connection failed' . $conn->connect_error;
} else {
    echo 'Successfully connected to MySql';
}
?>

acesse http://localhost/index.php caso receba a mensagem de Successfully connected to MySql sua conexão está ok.

Caso queira testar sua conexão via Laravel você vai precisar editar o arquivo /example-app/.env e setar as seguintes configurações:

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=test_db
DB_USERNAME=devuser
DB_PASSWORD=devpass

Feito isso, salve e execute os seguintes comandos no seu terminal:

docker exec (container_id) composer dump-autoload
docker exec (container_id) php artisan migrate

Caso não receba nenhuma mensagem de erro sua conexão com o banco de dados está ok e você está pronto para começar a codar!

Agradeço sua paciência e espero que tenha conseguido criar seu ambiente de desenvolvimento. Caso ainda reste alguma duvida eu ficaria contente em te responder, basta entrar em contato. Muito obrigado e até a próxima!


 

Contate-me