Como criar containers com PHP, MySQL e NGINX utilizando o Docker Compose
Tags: docker, mysql, nginx, php
Published: 2022-02-27 00:37:57

Nesse post vamos aprender a subir containers com PHP 7.3, MySQL 5.7 e Nginx utilizando o Docker Compose para subir os ambientes com apenas um comando de forma clara, objetiva e padronizada.

**O que é Docker?**

Docker é uma plataforma Open Source escrito em Go, que é uma linguagem de programação de alto desempenho desenvolvida dentro do Google, que possibilita a criação e administração de ambientes isolados ao invés de um Sistema Operacional completo, como acontece nos ambientes de virtualização tradicionais.

**Quais as vantagens de utilizar o Docker?**

O Docker permite o empacotamento de um serviço ou de um ambiente inteiro dentro de um único container, com isso todo esse ambiente torna-se portável para qualquer outra máquina que tenha o Docker instalado.
Com isso é possível reduzir muito o tempo de deploy do ambiente ou aplicação, pois não há necessidade de realizar nenhum ajuste nesse ambiente para o correto funcionamento da aplicação, pois o ambiente é sempre o mesmo, após configurá-lo uma vez é possível replicá-lo quantas vezes quiser.

**Mas e o Docker Compose?**

Docker Compose é uma ferramenta utilizada para subir vários contêineres com somente um comando a partir de um arquivo chamado docker-compose que é semelhante ao Dockerfile, esse arquivo é escrito em YAML “YAML Ain’t Markup Language” (em português, “YAML não é linguagem de marcação”).

**Passo 1: Instalando e configurando no Windows e Linux**

**Em Windows:**


Para baixar o Docker é necessário criar um ID no docker.com e após autenticado basta acessar:


https://hub.docker.com/editions/community/docker-ce-desktop-windows

Após baixar o docker, siga o passo a passo do instalador, você irá precisar aceitar os termos de uso, autorizar a instalação e esperar o Docker carregar todos os arquivos, ao final, clique em “Finish”.

Após isso, busque por “Docker” na barra de pesquisa do Windows e aperte dê um duplo clique sobre o ícone do Docker for Windows para executá-lo.

Pronto, agora o docker já está rodando em seu computador e já podemos criar nosso primeiro container.

**Em Linux:**

Para instalar o Docker com o Docker Compose no Linux, basta executar o comando abaixo no terminal do seu Linux:

**sudo apt install docker docker-compose -y**

**Passo 2: Configurando o servidor Web**

Primeiro passo é definir onde vamos criar o diretório do projeto, no meu caso, criei na área de trabalho um diretório chamado “Projeto”:

Windows:

![Imagem ilustrativa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/chkvj12sfzz5wsto1n2o.png)

Linux:

![Imagem ilustrativa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/obxrayme93oc9heeomwt.png)

Dentro desse diretório vamos criar um arquivo chamado docker-compose.yml contendo as configurações do nosso servidor web, insira as seguintes linhas nesse arquivo:


```YML
services:
 web:
  image: nginx:latest
  container_name: nginx
  restart: always
  ports:
   - "80:80"
```


- **Linha 1:** É o nome do serviço que vamos subir, nesse caso, o serviço é web.
- **Linha 2:** É a imagem e versão que vamos utilizar, nesse caso, vamos utilizar a imagem do Nginx na sua última versão disponível.
- **Linha 3:** Definimos um nome para nosso container, nesse caso, vamos chamá-lo de “nginx”.
- **Linha 4:** Por padrão a política de reinicialização do Docker é “no”, ou seja, não reinicia o container em hipótese alguma, nessa linha alteramos essa política para “Always” para que o Docker reinicie o container sempre que necessário.
- **Linhas 5 e 6:** Nessas duas linhas definimos as portas que vão ser utilizadas pelo nosso servidor web, primeiro a porta que vamos ouvir em nossa máquina e depois a porta que o servidor web está ouvindo no container.


Com essa configuração definida, já podemos subir nosso primeiro container utilizando o Docker Compose, para isso, basta rodar o comando abaixo através do terminal no diretório do projeto:

_**docker-compose up –d**_

**Lembrando:** No Linux é necessário rodar o comando com sudo no início.

Após executar esse comando no diretório do nosso projeto, caso tudo ocorra bem, será mostrada a seguinte mensagem no terminal “Creating nginx… done”.

![Imagem ilustrativa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lt0syxxir0phhg74fb86.png)

Podemos ver os containers que estão rodando e as portas utilizadas com o comando pelos respectivos containers com o seguinte comando:

**_docker-compose ps_**

**Lembrando:** No Linux é necessário rodar o comando com sudo no início. 

![Imagem ilustrativa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ovi2hkvvpgrqt0l95u17.png)


Como definimos que a porta 80 do container vai ser mapeada pela 80 de nossa máquina, para testar o acesso ao nosso servidor web, basta digitar http://localhost no navegador e apertar enter, se o servidor estiver rodando corretamente, será apresentado a tela de boas-vindas do Nginx.

![Imagem ilustrativa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dihhjbv3inpicc925fkq.png)


Agora que já temos um servidor web rodando, vamos mapear uma pasta de nosso computador para ser a raiz desse nosso servidor e também mapear o arquivo de configurações desse servidor, para isso, vamos inserir as seguintes linhas no docker-compose.yml criado anteriormente:  


```YML
  volumes:
   - ./www:/www
   - ./site.conf:/etc/nginx/conf.d/site.conf
```

- **Linha 1:** Declaração de que vamos mapear volumes nas linhas abaixo.
- **Linha 2:** Nessa linha declaramos que o diretório www dentro da pasta do nosso projeto vai passar a mapear o diretório www dentro de nosso container.
- **Linha 3:** Nessa linha declaramos que o arquivo site.conf vai ser passar a mapear o caminho /etc/nginx/conf.d/site.conf dentro do nosso container.

Agora no mesmo nível do docker-compose.yml, vamos criar um diretório chamado www.

![Imagem ilustrativa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v1gd2yptg3uz28v96q9t.png)

Ainda no diretório do nosso projeto, vamos criar o arquivo chamado site.conf que vai possuir toda a configuração do host docker.localhost de nosso servidor Nginx, nesse arquivo inclua as seguintes linhas:


```
server {
    index index.html index.php;
    server_name docker.localhost;
    error_log /var/log/nginx/error.log;
    access_log /var/log/nginx/access`.log;
    root /www;
}
```
 
- **Linha 1:** Tag de abertura da configuração do servidor Nginx.
- **Linha 2:** Nessa linha definimos os arquivos iniciais de nosso host.
- **Linha 3:** Definimos qual host vai utilizar essa configuração, nesse exemplo vamos utilizar o host docker.localhost.
- **Linha 4:** Aqui definimos o caminho onde serão salvos os logs de erro.
- **Linha 5:** Aqui definimos o caminho onde serão salvos os logs de acesso ao host.
- **Linha 6:** Nessa linha definimos o diretório raiz do nosso host, nesse caso, definimos o diretório www que foi mapeado para o diretório www do diretório de nosso projeto.

**Lembrando:** Por padrão a imagem do Nginx já possui um default.conf que ira configurar o acesso para o endereço http://localhost, por isso não podemos criar uma nova conf para esse mesmo endereço, caso deseje substituir essa configuração padrão para subir a sua aplicação em http://localhost basta criar o arquivo chamado default.conf ao invés do site.conf e montar um volume apontando para /etc/nginx/conf.d/default.conf como feito com site.conf.

![Imagem ilustrativa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z6sdebv4obtssqwjrp7t.png)

Precisamos agora acessar o diretório www, nesse diretório vamos criar uma página bem básica para testar se a configuração do servidor web está funcionando corretamente, para isso, basta criar um arquivo chamado index.html e incluir as seguintes linhas:

```HTML
<html>
<head>
    <title>Ola</title>
</head>
<body>
    <h2>Ola Docker!<h2>
</body>
</html>
```

![Imagem ilustrativa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ww6vdrowmk484b0touss.png)
 
Tudo pronto, agora vamos reiniciar o nosso container com os seguintes comandos:


**docker-compose down**
**docker-compose up -d**


**Lembrando:** No Linux é necessário rodar o comando com sudo no início.

![Imagem ilustrativa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ysbit6sculyxhimfgj9.png)
 

**No Windows:**

Abra o Bloco de Notas como administrador, agora com Bloco de Notas aberto clique em Arquivo > Abrir, na sequência, vá até a seguinte pasta: C: > Windows > System32 > Drivers > etc. Ali, no lado do campo Nome, mude a opção Documentos de texto (*.txt) para Todos os arquivos (*.*), o arquivo hosts aparecerá, clique nele, com o arquivo aberto no Bloco de Notas vá até o final do arquivo e inclua a seguinte linha:

127.0.0.1 docker.localhost

Após basta salvar o arquivo indo em Arquivo > Salvar.

![Imagem ilustrativa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/19dgg9q5lh3xs0ptb5p0.png)


No Linux:

Abra o terminal do seu Linux e digite o comando abaixo:

**sudo nano /etc/hosts**

Com arquivo aberto em seu terminal, vá até o final do arquivo e inclua a seguinte linha:

127.0.0.1 docker.localhost

![Imagem ilustrativa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1w6e15jwo3fhgwdw3b7h.png)


Após isso basta salvar a alteração teclando Ctrl + O e depois Enter, para sair da edição do arquivo pressione Ctrl + X.

Pronto, finalmente podemos testar o acesso ao endereço http://docker.localhost, caso tudo esteja correto, será apresentado um “Ola Docker!”.

![Imagem ilustrativa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7jw5gmd54dmioq12hn9k.png)

**Passo 3: Configurando o PHP-FPM em nosso servidor Nginx**

Agora que nosso servidor web já está funcionando, vamos configurar o PHP-FPM e fazer a ligação com o serviço web, para isso, vamos abrir novamente o arquivo docker-compose.yml e incluir as seguintes linhas:


```YML
  links:
  - php
 php:
  image: php:7.3-fpm
  container_name: php-fpm
  volumes:
  - ./www:/www
```

- **Linha 1 e 2:** Nessas linhas criamos um link do php para o serviço web tenha acesso a ele.
- **Linha 3:** Definimos o nome do nosso serviço.
- **Linha 4:** Nome da imagem e versão que iremos utilizar.
- **Linha 5:** Definimos o nome do nosso container.
- **Linha 6 e 7:** Mapeamos o diretório www de nosso projeto também no container do PHP-FPM para que o mesmo também tenha acesso aos arquivos.

Após incluir a configuração do PHP-FPM e linkar o serviço PHP no serviço web, vamos incluir as seguintes linhas no site.conf, dentro da tag server:

```
location ~ \.php$ {
 try_files $uri =404;
 fastcgi_split_path_info ^(.+\.php)(/.+)$;
 fastcgi_pass php:9000;
 fastcgi_index index.php;
 include fastcgi_params;
 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 fastcgi_param PATH_INFO $fastcgi_path_info;
}
```

Vamos agora acessar o diretório www e renomear a index.html para index.php e substituir seu conteúdo por:

```PHP
<?php
echo phpinfo();
```

Antes de testar vamos rodar os comandos abaixo para encerrar todos containers que estão rodando e subi-los novamente, incluindo o do serviço php.


**docker-compose down**
**docker-compose up –d**

**Lembrando:** No Linux é necessário rodar os comandos com sudo no início.


![Imagem ilustrativa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tp5n3zbizc5cfqr52ifb.png)

Pronto, finalmente podemos testar o acesso ao endereço http://docker.localhost.

![Imagem ilustrativa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o5ozdr87rn740n47zc50.png)


Agora que temos o servidor rodando com PHP, vamos configurar o MySQL 5.7, para isso, vamos retornar ao arquivo docker-compose.yml e incluir as seguintes linhas no final do arquivo:

```YML
  links:
  - db
 db:
  image: mysql:5.7
  container_name: mysql
  ports:
  - "3306:3306"
  command: --default-authentication-plugin=mysql_native_password
  restart: always
  environment:
    MYSQL_ROOT_PASSWORD: root
    MYSQL_DATABASE: teste
```

- Linha 1 e 2: Nessas linhas criamos um link do serviço de Banco de Dados para que o PHP tenha acesso a ele.
- Linha 3: Aqui definimos o nome do nosso serviço.
- Linha 4: Nome da imagem e versão que vamos utilizar.
- Linha 5: Definimos o nome do nosso container.
- Linha 6 e 7: Nessas duas linhas definimos as portas que vão ser utilizadas pelo nosso servidor MySQL, primeiro a porta que queremos ouvir em nossa máquina e depois a porta que o servidor MySQL está ouvindo no container.
- Linha 8: Nessa linha definimos que vamos utilizar o método nativo de autenticação do MySQL.
- Linha 9: Definimos a política de restart do Docker para “Always” para que o Docker reinicie o container sempre que necessário.
- Linha 10: Nessa linha dizemos que abaixo vamos definir algumas variáveis de ambiente.
- Linha 11: Definimos a senha do root como “root”.
- Linha 12: Nessa linha definimos que vamos utilizar uma base chamada teste, quando subirmos o container a base em questão vai ser criada automaticamente.

Após isso, vamos rodar os comandos abaixo para encerrar todos containers e subi-los novamente:

**docker-compose down**
**docker-compose up –d**

**Lembrando:** No Linux é necessário rodar os comandos com sudo no início.

![Imagem ilustrativa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wn7ke6nr09a5dw1x5h7u.png)


Para verificar se o servidor MySQL está rodando corretamente e possui a base “teste” criada, vamos acessar esse container via bash com o seguinte comando:

**docker-compose exec db bash**

**Lembrando:** No Linux é necessário rodar o comando com sudo no início.

Após rodar esse comando você está no bash do container onde o MySQL está rodando, agora vamos acessar o MySQL com usuário root e senha root que definimos no arquivo docker-compose.yml com o seguinte comando:

**mysql -u root –proot**

Após rodar esse comando você vai estar logado no MySQL com usuário root e pode ver as bases criadas, para isso basta executar o seguinte comando:

**show databases;**

Com isso, será mostrada todas as bases criadas, entre elas deve existir a base chamada teste. 


![Imagem ilustrativa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7r6n38otg9lfphfbeimy.png)


Perfeito, agora temos o servidor Nginx rodando com PHP e o MySQL, já podemos criar um script em PHP para se conectar a base teste e verificar se está tudo funcionando corretamente.

Para testar a conexão, primeiro precisamos instalar a extensão PDO para MySQL no PHP pois essa não vem configurado por padrão, é possível definir a instalação dessa extensão no arquivo Dockerfile para que seja instalada já no primeiro build do serviço, como nesse post não iremos abordar o arquivo Dockerfile, vamos realizar essa instalação de forma manual com um comando, para isso vamos executar o seguinte comando no diretório de nosso projeto:

**docker exec -it php-fpm docker-php-ext-install pdo pdo_mysql**
**docker-compose restart**

**Lembrando:** No Linux é necessário rodar os comandos com sudo no início. 

Agora que já temos o driver de conexão ao MySQL instalado e configurado no PHP, vamos criar um arquivo chamado db.php dentro do diretório www com o seguinte código:

```PHP
<?php
$host = "db";
$username = "root";
$password = "root";
$db = "teste";
try {
    $conn = new PDO("mysql:host=$host;dbname=$db", $username, 
    $password);
    $conn->setAttribute(PDO::ATTR_ERRMODE, 
    PDO::ERRMODE_EXCEPTION);
echo '<h2>Conectado com sucesso.<h2>';
} catch (PDOException $e) {
    echo 'ERROR: ' . $e->getMessage();
}
?>
```

Por fim, podemos acessar http://docker.localhost/db.php para testar a conexão do PHP ao nosso servidor MySQL, caso tudo funcione como esperado, você vai ver a mensagem “Conectado com sucesso.” no seu navegador.


![Imagem ilustrativa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/25ol4cge2d699lfhg215.png)

Agora você tem um ambiente que pode ser replicado facilmente para qualquer outra máquina que possua o Docker instalado, para isso basta apenas copiar o arquivo docker-compose.yml.


**Conclusão**

Há muito mais sobre o Docker Compose do que o que foi mostrado nesse post, mas acredito que isso deve ser suficiente para começar a utilizar e aproveitar toda facilidade que o Docker Compose proporciona para realizar o deploy dos seus ambientes de desenvolvimento, teste, produção, etc.

**Meus contatos:**

E-mail: nunesjr1993@gmail.com
Linkedin: https://www.linkedin.com/in/jrnunes1993/

**Endereço do repositório do projeto no Github:**

https://github.com/jrnunes1993/Docker

**Links interessantes para estudo e usados na construção deste post:**

https://docs.docker.com/
https://nginx.org/en/docs/
https://pt.wikipedia.org/wiki/YAML
https://pt.wikipedia.org/wiki/Docker_(software)