Linux Servidor linux Dev ops

Docker Compose – Definindo aplicações com múltiplos containers

Docker Compose – Definindo aplicações com múltiplos containers

O Docker Compose é uma ferramenta desenvolvida para facilitar e agilizar a utilização do Docker, com ele podemos criar e executar aplicações com múltiplos containers de forma fácil. É necessário ter o Docker para utilizarmos o Compose, ele está disponível em versões para Linux, Windows e MacOS.

Para manipular o Compose iremos manipular um arquivo YAML, que é um formato de serialização de dados de fácil visualização. Neste arquivo configuramos os serviços que queremos na nossa aplicação. Após a definição deste arquivo de configuração, utilizamos o Docker Compose para baixar as imagens, criar e iniciar todos os serviços descritos.

O Docker Compose é uma ótima ferramenta para os desenvolvedores. Pois, temos liberdade para decidir quais aplicativos vamos utilizar e mesmo em ambientes complexos com vários serviços, podemos criar e iniciá-los em questão de segundos. Assim, o desenvolvimento de software torna-se mais fácil e mais eficaz.

O Docker Compose tem diversos comandos para gerenciar todos as etapas da aplicação:

➡ Iniciar, parar e reconstruir serviços;
➡ Ver os status dos serviços em execução;
➡ Transmitir a saída de logs para monitorar;
➡ Executar comandos num serviço;

Benefícios:

➡ Você monta e sobe todo o seu ambiente com um único comando;
➡ Executando os serviços pelo Compose, você não precisa manter diversos softwares na máquina local;
➡ Todo ambiente pode ser recriado e replicado facilmente, ajudando na colaboração de um projeto com outras pessoas;
➡ É fácil de compreender e manipular;

Instalando o Docker Compose

Vamos fazer a instalação no Linux, assim com os passos abaixo, iremos instalar o Docker Compose de acordo com a versão do seu Sistema, lembrando que precisa do Docker instalado para funcionar:

# curl -L https://github.com/docker/compose/releases/download/1.17.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

# chmod 755 /usr/local/bin/docker-compose

Podemos verificar se está instalado corretamente executando o comando abaixo para visualizar a versão:

# docker-compose --version

Para utilizarmos o autocompletar dos comandos, temos que adicionar o script no bash com o comando:

# curl -L https://raw.githubusercontent.com/docker/compose/1.17.0/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose

Criando uma aplicação simples

Vamos iniciar a criação do nosso arquivo YAML com um exemplo simples, devemos seguir alguns passos para montar nosso ambiente:

➡ Definir os serviços e a relação entre eles;
➡ Criar um arquivo docker-compose.yml com as definições dos serviços;
➡ Iniciar todos os serviços com um único comando;

Para organizar e facilitar a manutenção de nossos ambientes, vamos criar um diretório para armazenar nossos projetos:

# mkdir compose && cd compose

Dentro do diretório compose criaremos outro diretório que será o nosso primeiro ambiente:

# mkdir compose-nginx-php && cd compose-nginx-php

Obs.: Todos os arquivos criados estão disponíveis no GitHub: Linux Web Compose.

Todos os serviços da nossa aplicação serão definidos dentro de um arquivo chamado “docker-compose.yml“, também vamos criar alguns arquivos de configuração para o bom funcionamento do nosso exemplo.

Vamos criar nosso arquivo docker-compose.yml, com 2 serviços distintos:

web: Será um container com o servidor web Nginx.
php: Será um container com o serviço PHP-FPM.

Lembrando que o Nginx não possui módulo do PHP (como o Apache), ele faz uso de FastCGI (API), por isso vamos utilizar o PHP-FPM que é independente do servidor web. Abaixo temos o script completo:

# vim docker-compose.yml

web:
	image: nginx:latest
	ports:
		- "8000:80"
	volumes:
		- ./www:/var/www/html
		- ./default.conf:/etc/nginx/conf.d/default.conf
	links:
		- php
php:
	image: php:7-fpm
	volumes:
		- ./www:/var/www/html

Explicando o arquivo docker-compose.yml:

web: e php:
Definimos os nomes dos serviços pelos quais serão conhecidos dentro do nosso ambiente;

image:
Definimos quais imagens devem utilizar na criação dos containers;

ports:
Definimos a porta redirecionada do host com a porta exposta do container;

volumes:
Mapeamos volumes para uma pasta local, assim podemos adicionar arquivos ao nosso projeto, evitando a perda na reconstrução do ambiente.

No caso do serviço web, criamos uma pasta chamada www, dentro da pasta do projeto, que será mapeada com a pasta /var/www/html do Nginx. Assim, podemos adicionar nossos scripts (html, php, etc…) que serão interpretados pelo webserver. Também mapeamos o arquivo de configuração default.conf do Nginx.

No caso do serviço php, também mapeamos a pasta www, pois ele precisará ter acesso para interpretar os scripts PHP.

links:
Faz a ligação (/etc/hosts) entre os dois serviços, para que eles possam se comunicar.

Para finalizar, vamos precisar habilitar o PHP no Nginx, para isso vamos criar na raiz o arquivo default.conf que contém as configurações necessárias para o funcionamento. A linha & fastcgi_pass php:9000, indica ao Nginx que ele deve utilizar como interpretador PHP o serviço chamado php na porta 9000 (padrão da imagem php:7-fpm):

# vim default.conf

server {
	listen 80;
	index index.php index.html;
	server_name localhost;
	error_log  /var/log/nginx/error.log;
	access_log /var/log/nginx/access.log;
	root /var/www/html;

	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;
	}
}

Pronto, já podemos executar nosso ambiente! Para iniciar o processo de criação utilizamos o comando abaixo:

# docker-compose up

Este comando irá verificar a sintaxe do arquivo e se encarregará de baixar as imagens e criar todos os serviços da forma que definimos. Ao término do processo ele irá mostrar no console os logs dos serviços em execução. Para interromper o ambiente, tecle Ctrl + C.

Caso queira deixar o console livre, podemos executar o comando em segundo plano, para isso use o parâmetro -d:

# docker-compose up -d

No console podemos verificar o status dos serviços que acabamos de criar executando o comando:

Docker compose

Na imagem podemos ver algumas informações:

Name: Nome do container. Como não definimos no arquivo ele é escolhido pelo Compose.
Command: Comando executado dentro do container.
State: Estado do serviço, Up indica que está em execução, quando interrompido exibe Exit.
Ports: Exibe portas expostas nos containers e porta redirecionadas.

Agora já podemos acessar o servidor, pelo browser. Você poderá acessar pelo localhost ou IP da máquina onde está configurado o Docker Compose, na porta 8000. No caso utilizo o nome do servidor num DNS.

Se tentarmos acessar, iremos receber uma mensagem “403 Forbidden” do Nginx.

Docker compose

Isso ocorre, pois não criamos nenhuma página index dentro da pasta www do nosso ambiente. Para podermos testar melhor, vamos criar um arquivo index.php e acessar no browser novamente, para criar execute no terminal:

Docker compose

Pronto, nosso ambiente está funcionando. Todos os scripts da pasta www serão mantidos, mesmo se você derrubar os containers do Docker Compose.

Manipulando o Docker Compose

Parar e remover todo o projeto

Se quisermos derrubar nossos serviços, executamos o comando:

# docker-compose down
Parando serviços em execução

Se quiser interromper todos os serviços que estão em execução, use:

# docker-compose stop
Iniciando os serviços

Para iniciar os serviços que estão parados usamos o comando:

# docker-compose start
Reiniciar os serviços

Caso seja preciso reiniciar todos eles, podemos executar o comando:

# docker-compose restart

Visualizar os logs

Para visualizar a saída dos logs dos containers, podemos executar:

# docker-compose logs -f

Criando uma aplicação mais completa

Vamos criar um ambiente mais completo, contendo além do que já foi criado no exemplo anterior (Nginx e PHP), também vamos adicionar o banco MySql e phpMyAdmin para administrá-lo.

Para isso vamos criar no diretório compose uma pasta que conterá o nosso segundo ambiente:

# mkdir compose-nginx-php-mysql && cd compose-nginx-php-mysql

Vamos criar nosso arquivo docker-compose.yml, com os 4 serviços:

web: Container com o servidor web Nginx.
php: Container com o serviço PHP-FPM.
db: Container com o banco de dados MySql.
admin: Container com o phpMyAdmin.

# vim docker-compose.yml

version: '3.4'

services:
  web:
    image: nginx:latest
    container_name: web
    depends_on:
      - php
    ports:
      - "8000:80"
    volumes:
      - ./www:/var/www/html
      - ./default.conf:/etc/nginx/conf.d/default.conf
  php:
    build:
      context: .
      dockerfile: Dockerfile
    image: php-mysql
    container_name: php
    volumes:
      - ./www:/var/www/html
  db:
    image: mysql:5.7
    container_name: db
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: mysql
    volumes:
      - ./data:/var/lib/mysql
  admin:
    image: phpmyadmin/phpmyadmin
    container_name: admin
    depends_on:
      - db
    environment:
      - PMA_HOST = db
    ports:
      - 8080:80

Explicando o docker-compose.yml:

A partir da versão 2 do Docker Compose, foram adicionadas novas funcionalidades, uma delas foi a opção services, que permite que todos os serviços se enxerguem dentro da aplicação, sem a necessidade de utilizar a opção links. No nosso exemplo deixamos o arquivo com version 3.4.

Serviço web:

O serviço web não tem muita diferença em relação ao exemplo anterior. Apenas adicionamos a opção container_name que permite definir um nome para o container e a opção depends_on que inicia um serviço em ordem de dependência, no nosso caso, o serviço php será iniciado antes do web.

Podemos copiar o arquivo default.conf do exemplo anterior para a pasta desse ambiente, pois não precisamos fazer nenhuma alteração.

Serviço php:

No serviço php iremos criar uma imagem personalizada utilizando um (Dockerfile)[https://www.linuxnaweb.com/docker-gerenciamento-avancado-de-recursos/] para adicionar o pacote pdo_mysql para acessar o banco de dados MySql.

A opção build indica que iremos criar uma imagem, a opção context indica o diretório que se encontra o arquivo e a opção dockerfile diz qual é o nome do arquivo. Para finalizar a opção image indica o nome que terá a imagem, no caso php-mysql.

O arquivo Dockerfile terá como base a imagem do php:7.2-fpm e adicionaremos o pdo_mysql com a linha RUN. Veja como fica o arquivo:

# vim Dockerfile

FROM php:7.2-fpm

Maintainer Cesar Gaspar <rasec.rapsag@gmail.com>

RUN apt-get update && \
	apt-get install -y --no-install-recommends && \
	docker-php-ext-install pdo_mysql && \
	apt-get clean

Serviço db:

No serviço db estamos criando um container com a imagem do mysql na versão 5.7. Expomos a porta 3306 para que possamos acessar por qualquer interface (console ou gráfica).

Definimos as variáveis de ambiente MYSQL_ROOT_PASSWORD para senha usuário root e MYSQL_DATABASE para o nome do banco.

Para preservar os dados, mapeamos uma pasta chamada data no diretório do projeto, assim podemos recriar o serviço de banco de dados sem perder as informações já armazenadas.

Serviço admin:

No serviço admin estamos criando um container com a imagem do phpmyadmin que já tem as configurações necessárias para acessarmos a interface web do phpMyAdmin. Expomos a porta 8080 para acesso pelo browser.

Definimos a variável de ambiente PMA_HOST com o nome do serviço com o mysql. E com o depends_on informamos que o serviço deverá iniciar após o db.

Pronto, contudo configurado podemos iniciar nosso ambiente com o comando:

# docker-compose up -d

Verificando o status dos serviços que criamos para nosso projeto:

# docker-compose ps

Docker compose

Perceba que os nomes dos serviços aparecem como foram definidos pela opção container_name.

Agora a estrutura de pastas e arquivos ficou assim:

Docker compose

Temos a pasta www, onde adicionamos nossos scripts php e a pasta data onde ficam os arquivos do banco de dados MySql.

Como fizemos o direcionamento da porta do serviço do MySql, podemos acessar pelo console através do cliente do MySql:

# apt -y install mysql-client
# mysql -h 127.0.0.1 -u root -p

Docker compose

Também podemos acessar o banco pelo phpMyAdmin através da porta 8080, perceba que o banco criado no console já aparece:

Docker compose

Lembrando que o usuário e senha para acesso ao MySql é root e 123456, respectivamente, como foi definido no arquivo docker-compose.yml.

Para acessar o webserver usamos a porta 8000, como não criamos nenhuma página na pasta www, irá aparecer a mensagem de acesso proibido:

Docker compose

Podemos verificar os erros gerados pelo webserver pelo console:

# docker-compose logs -f web

Docker compose

Agora, para testar a conexão do MySql num script PHP, vamos primeiramente criar uma tabela chamada usuários no banco teste, inserindo alguns registros:

Docker compose

Criamos um pequeno script PHP para conectar no banco e trazer os registros:

# vim www/index.php

<?php
	try {
        $conn = new PDO( 'mysql:host=db;dbname=teste', 'root', '123456');
		$sql = 'SELECT * FROM usuarios';

		foreach( $conn->query( $sql ) as $row ) {
			echo '<li>' . $row['nome'] . '</li>';
		}

		$conn = null;

	} catch (PDOException $e) {
		echo "Erro!: " . $e->getMessage() . "<br/>";
		die();
	}    
?>

Acessando no browser temos:

Docker compose

Pronto! Ambiente está funcionando perfeitamente. Os arquivos desse artigo se encontram no GitHub Linux Web Compose

Como podemos ver o Docker Compose é uma forma ágil de criar um ambiente de desenvolvimento. Para mais informações e opções de configuração você pode acessar o site: https://docs.docker.com/compose/.

Boa sorte!!!

comments powered by Disqus

Assine nossa Newsletter! 🐧

Se una com os assinantes de nossa Newsletter, sempre que tiver postagem nova você será notificado.