Implantar um aplicativo PHP usando o Docker-compose

Você está aqui:
Tempo estimado de leitura: 6 min

Aplicações PHP são geralmente compostas por um servidor web, um sistema de banco de dados relacional e o próprio interpretador de linguagem. Neste tutorial, vamos aproveitar uma pilha de aplicativos PHP completa usando o docker. Este é um tutorial detalhado no qual vamos construir e orquestrar containers para Nginx (o servidor web), MySQL (o sistema de banco de dados) e PHP.

Para o propósito deste tutorial, vamos escrever um aplicativo simples que leia uma lista de cidades de um banco de dados e as exiba em uma página da Web, assim demonstraremos um aplicativo PHP básico, mas funcional.

Este guia pressupõe que você tenha o Docker-CE já instalado e pelo menos um conhecimento mínimo de trabalho da janela de encaixe. Para esse assunto você pode rever os seguintes tutoriais:

Configurando nosso ambiente de trabalho

Um aplicativo baseado no Docker da vida real normalmente será composto de vários contêineres. Gerenciando estes manualmente pode facilmente tornar-se bastante confuso e pesado. É aí que o docker-compose entra em cena. Ele ajuda você a gerenciar vários contêineres por meio de um yamlarquivo de configuração simples .

Instalar o docker-compose.

curl -L https://github.com/docker/compose/releases/download/1.19.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

Crie uma pasta para armazenar todos os arquivos necessários deste exemplo e depois cdpara dentro dele. De agora em diante, este é o nosso diretório de trabalho e todos os comandos serão executados dentro desta pasta e todos os caminhos serão referenciados em relação a ela. Esta pasta pode ser referenciada posteriormente como WORKING_DIR.

mkdir ~/docker
cd ~/docker

Agora crie mais três pastas.

mkdir php nginx app

phppasta é onde nós iremos construir nossa imagem PHP personalizada, a nginxpasta conterá os arquivos necessários para nossa imagem nginx customizada e a apppasta é onde colocaremos o código fonte e a configuração do nosso aplicativo de amostra.

Configurando o Contêiner PHP

Neste exemplo, vamos usar php-fpmpara conectar ao servidor da web Nginx. Nós estaremos usando a imagem de base oficial do PHP. No entanto, também precisamos instalar e ativar algumas extensões para que possamos acessar o banco de dados. Dentro da phppasta, crie um arquivo chamado Dockerfilee coloque o seguinte conteúdo nele.

FROM php:7.1-fpm-alpine3.4
RUN apk update --no-cache \
    && apk add --no-cache $PHPIZE_DEPS \
    && apk add --no-cache mysql-dev \
    && docker-php-ext-install pdo pdo_mysql

Note que estamos usando a versão Alpine da imagem oficial do PHP. A Alpine é uma distribuição muito pequena voltada para contêineres, fornecendo pegadas muito menores. Além disso, observe o uso do comando docker-php-ext-install, a imagem oficial do PHP fornece este comando para facilitar o processo de instalação e configuração de extensões PHP.

Agora, vamos criar esta imagem do Docker, emitindo o seguinte (dentro do nosso WORKING_DIR):

docker build -t vultr-php php/

docker-compose.ymlarquivo

Como já mencionado, docker-composepermite gerenciar vários contêineres por meio de um arquivo de configuração simples. Este arquivo de configuração é geralmente chamado docker-compose.yml. Crie este arquivo dentro da apppasta.

touch app/docker-compose.yml

Agora coloque o seguinte conteúdo neste arquivo.

version: '2'
services:
  php:
    image: vultr-php
    volumes:
      - ./:/app
    working_dir: /app

Vamos explicar essa sintaxe. Primeiro, observe a primeira linha.

version: '2'

Isso especifica a versão do docker-compose.ymlarquivo de configuração usado. A próxima linha especifica os serviços ou, em outras palavras, os contêineres a serem provisionados.

services:
  php:
    image: vultr-php
    volumes:
      - ./:/app
    working_dir: /app

Note que todo serviço possui uma chave específica dentro do servicesbloco. O nome especificado aqui será usado para referenciar esse contêiner específico posteriormente. Observe também que dentro da phpconfiguração, definimos a imagem usada para executar o container (esta é a imagem que construímos anteriormente). Também definimos um mapeamento de volume.

volumes:
  - ./:/app

Isso informa docker-composepara mapear o diretório atual ( ./) para o /appdiretório dentro do contêiner. A última linha define a /apppasta dentro do contêiner como o diretório de trabalho, o que significa que essa é a pasta na qual todos os futuros comandos dentro de um contêiner são executados por padrão.

Agora podemos orquestrar nossos contêineres.

cd ~/docker/app
docker-compose up -d

Você pode executar o seguinte comando para certificar-se de que o contêiner PHP foi executado:

docker ps

Como executar comandos dentro dos contêineres

Ainda dentro da apppasta, podemos executar qualquer comando dentro de um contêiner de serviço definido com a ajuda do docker-composecomando.

docker-compose exec [service] [command]

[service]espaço reservado refere-se à chave de serviço. No nosso caso, isso foi php. Vamos executar um comando dentro do container para verificar nossa versão do PHP.

docker-compose exec php php -v

Você verá a seguinte saída.

PHP 7.1.14 (cli) (built: Feb  7 2018 00:40:45) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies

Configurando o Contêiner Nginx

Assim como o contêiner do PHP, precisamos criar uma imagem personalizada para o servidor da web. Mas neste caso, precisamos apenas fornecer uma configuração para o nosso virtual host. Certifique-se de estar dentro da nossa WORKING_DIRe crie um Dockerfiledentro da nginxpasta:

cd ~/docker
touch nginx/Dockerfile

Agora coloque o seguinte conteúdo para isso Dockerfile:

FROM nginx:1.13.8-alpine
COPY ./default.conf /etc/nginx/conf.d/default.conf

Estamos usando a imagem padrão Nginx baseada no Alpine. Neste arquivo do Docker, simplesmente copiamos um arquivo de configuração em nossa configuração de aplicativo. Antes de construir esta imagem, crie um arquivo de configuração.

touch nginx/default.conf

Agora preencha-o com este conteúdo.

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /app;
    index index.php;

    #server_name server_domain_or_IP;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

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

Note que na fastcgi_pass php:9000linha estamos referenciando o container PHP por seu nome dentro do servicebloco do docker-compose.ymlarquivo de configuração. docker-composeCria internamente uma rede e atribui o nome do serviço como o nome do host a cada um dos serviços definidos. Agora podemos construir a imagem Nginx.

docker build -t vultr-nginx nginx/

Atualizando docker-compose.yml

Agora atualize o app/docker-compose.ymlarquivo.

version: '2'
services:
  php:
    image: vultr-php
    volumes:
      - ./:/app
    working_dir: /app
  web:
    image: vultr-nginx
    volumes:
      - ./:/app
    depends_on:
      - php
    ports:
      - 80:80

Nós adicionamos apenas um novo serviço. A configuração é quase a mesma, exceto pelo seguinte.

depends_on:
  - php
ports:
  - 80:80

Quando o contêiner Nginx precisar que o serviço PHP seja totalmente inicializado, forçaremos esse requisito na depends_onopção. A portschave de configuração mapeia uma porta do host para uma porta de contêiner, aqui mapeamos a porta 80no host para a porta 80no contêiner.

Agora crie um arquivo chamado index.phpdentro da apppasta e coloque o seguinte nele.

<?php phpinfo();

Certifique-se de que a porta 80esteja acessível através do seu firewall e execute o seguinte.

cd ~/docker/app
docker-compose up -d

Mais uma vez, verifique novamente se o serviço está ativo.

docker ps

Abra um navegador e acesse [vultr-instance-ip]. Você pode descobrir o endereço IP da instância Vultr executando o seguinte.

hostname -I

Você verá a página de informações do PHP.

Configurando o contêiner do MySQL

A imagem oficial do MySQL permite configurar o contêiner através de variáveis ​​de ambiente simples. Isso pode ser feito com uma environmentopção dentro da definição de bloco de serviço. Atualize o ~/docker/app/docker-compose.ymlarquivo para o seguinte.

version: '2'
services:
  php:
    image: vultr-php
    volumes:
      - ./:/app
    working_dir: /app
  web:
    image: vultr-nginx
    volumes:
      - ./:/app
    depends_on:
      - php
    ports:
      - 80:80
  mysql:
    image: mysql:5.7.21
    volumes:
      - ./:/app
      - dbdata:/var/lib/mysql
    environment:
      - MYSQL_DATABASE=world
      - MYSQL_ROOT_PASSWORD=root
    working_dir: /app
volumes:
  dbdata:

Agora nós definimos um novo serviço para o banco de dados. Observe a linha dbdata:/var/lib/mysql. Isso monta o caminho no contêiner /var/lib/mysqlpara um volume persistente gerenciado pelo Docker, dessa forma, os dados do banco de dados persistem após a remoção do contêiner. Este volume precisa ser definido em um bloco de nível superior, como você pode ver no final do arquivo.

Antes de orquestrar nossa nova configuração, vamos baixar um exemplo de banco de dados MySQL. A documentação oficial do MySQL fornece alguns bancos de dados de amostra. Nós estaremos usando o conhecido banco de dados mundial. Este banco de dados fornece uma lista de países e cidades. Para baixar esse exemplo, execute o seguinte dentro da pasta do aplicativo.

curl -L http://downloads.mysql.com/docs/world.sql.gz -o world.sql.gz
gunzip world.sql.gz

Agora vamos orquestrar nossos contêineres.

docker-compose up -d

Como você já deve ter percebido, o docker-compose upcomando inicia apenas os contêineres que ainda não foram iniciados. Ele verifica as diferenças entre o docker-compose.ymlarquivo e a configuração atual dos contêineres em execução.

Mais uma vez, verifique se o contêiner do MySQL foi iniciado.

docker ps

Agora preencha o banco de dados mundial.

docker-compose exec -T mysql mysql -uroot -proot world < world.sql

Você pode verificar se o banco de dados foi preenchido selecionando dados diretamente do banco de dados. Primeiro, acesse o prompt do MySQL dentro do contêiner.

docker-compose exec mysql mysql -uroot -proot world

No prompt do MySQL, execute o seguinte.

select * from city limit 10;

Você verá uma lista de cidades. Agora saia do prompt do MySQL.

mysql> exit

Construindo nossa aplicação

Agora que todos os contêineres necessários estão em funcionamento, podemos nos concentrar em nosso aplicativo de amostra. Atualize o app/index.phparquivo para o seguinte.

<?php

$pdo = new PDO('mysql:host=mysql;dbname=world;charset=utf8', 'root', 'root');

$stmt = $pdo->prepare("
    select city.Name, city.District, country.Name as Country, city.Population
    from city
    left join country on city.CountryCode = country.Code
    order by Population desc
    limit 10
");
$stmt->execute();
$cities = $stmt->fetchAll(PDO::FETCH_ASSOC);

?>

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Vultr Rocks!</title>
</head>
<body>
    <h2>Most Populous Cities In The World</h2>
    <table>
    <thead>
        <tr>
            <th>Name</th>
            <th>Country</th>
            <th>District</th>
            <th>Population</th>
        </tr>
    </thead>
    <tbody>
        <?php foreach($cities as $city): ?>
            <tr>
                <td><?=$city['Name']?></td>
                <td><?=$city['Country']?></td>
                <td><?=$city['District']?></td>
                <td><?=number_format($city['Population'], 0)?></td>
            </tr>
        <?php endforeach ?>
    </tbody>
    </table>
</body>
</html>

Se você acessar [vultr-instance-ip]em um navegador da web, verá uma lista das cidades mais populosas do mundo. Parabéns, você implantou um aplicativo PHP totalmente funcional usando o docker.

Conclusão

Neste tutorial, demonstrei passo a passo como configurar um aplicativo PHP totalmente funcional. Criamos imagens personalizadas para PHP e Nginx e configuramos o docker-compose para orquestrar nossos contêineres. Apesar de ser muito básica e simples, essa configuração reflete um cenário da vida real.

Neste guia, criamos e codificamos nossas imagens localmente. Para uma configuração mais flexível, você pode enviar essas imagens para um registro do docker . Você pode enviar para o registro de encaixe oficial ou até mesmo configurar seu próprio registro de encaixe. Em qualquer caso, isso permitirá que você crie suas imagens em um host e as use em outro.

Para um uso mais detalhado docker-compose, você deve consultar a documentação oficial .

Dependendo dos requisitos de sua aplicação e da estrutura PHP que você usa, você pode querer adicionar mais extensões. Isso pode ser feito facilmente, modificando o Dockerfileusado para construir nossa imagem PHP personalizada. No entanto, algumas extensões precisam de dependências extras para serem instaladas no contêiner. Você deve consultar a lista de extensões na documentação oficial do PHP para revisar os requisitos básicos de cada extensão.

Esse artigo foi útil?
Não Gostei 0
Visualizações: 219