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:
Linux:
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:
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”.
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.
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.
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:
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.
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{% raw %}`.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)
Top comments (6)
Parabéns, muito bom e fácil só tive um erro pois não tinha o mysql instalado.
Muito legal, funcionou perfeitamente.
Agora como faria para adicionar o Composer ao PHP?
Acessei o bash do php
E lá realizei a instalação do Command-line installation descrito em getcomposer.org/download/
Até são gerados os arquivos mas o sistema ainda não consegue enxergar o ventor/autoload.php...
Quando descobrir coloco aqui
Obrigado pelas informações
Muito bom...
Só tive um problema de conexão do PHP com Mysql:
ERROR: SQLSTATE[HY000] [2002] No such file or directory
Alguém tem alguma ideia do que pode ser?
No meu aqui deu essa mensagem também, eu olhei e tinham uns espaços a mais ali na explicação:
$conn = new PDO(“mysql: host = $host;
dbname = $db”, $username, $password);
Corrigindo fica:
$conn = new PDO("mysql:host=$host;dbname=$db, $username, $password);
Obrigado pelo comentário, irei ajustar no post esse exemplo.
No arquivo onde criou a conexão com DB, altera o hostname de "localhost" para "db" que resolve.