O Compose au­to­ma­tiza a gestão de con­ten­to­res, fa­ci­li­tando assim o di­men­si­o­na­mento e a im­ple­men­ta­ção de apli­ca­ções no Docker. Neste tutorial, ana­li­sa­mos em pro­fun­di­dade a con­fi­gu­ra­ção e a uti­li­za­ção do Docker Compose para que possa aplicá-lo no seu próprio ambiente de produção.

O que é o Docker Compose?

O Docker Compose é utilizado para gerir apli­ca­ções e aumentar a efi­ci­ên­cia no de­sen­vol­vi­mento de con­ten­to­res. A con­fi­gu­ra­ção é guardada num único ficheiro YAML, o que permite criar e escalar apli­ca­ções fa­cil­mente. O Docker Compose é fre­quen­te­mente utilizado para con­fi­gu­rar um ambiente local, mas também pode fazer parte de um fluxo de trabalho de in­te­gra­ção contínua/entrega contínua (CI/CD). Os pro­gra­ma­do­res podem definir uma versão es­pe­cí­fica de con­ten­to­res para testes ou para uma fase es­pe­cí­fica do pipeline. Isto facilita a iden­ti­fi­ca­ção de problemas e a correção de erros antes que estes cheguem à produção.

Docker Compose: eis os re­qui­si­tos

Para a or­ques­tra­ção de con­ten­to­res, é ne­ces­sá­rio ter tanto o Docker Engine como o Docker Compose. Por con­se­guinte, deve ter uma das seguintes opções con­fi­gu­ra­das no seu sistema:

  • Docker Engine e Docker Compose: podem ser ins­ta­la­dos como binários in­de­pen­den­tes
  • Docker Desktop: ambiente de de­sen­vol­vi­mento com interface gráfica de uti­li­za­dor que inclui o Docker Engine e o Docker Compose
Dica

Nos nossos guias, pode aprender a instalar o Docker Compose em di­fe­ren­tes sistemas ope­ra­ti­vos:

Guia passo a passo: como utilizar o Docker Compose

Para te mostrar os conceitos do Docker Compose, vamos utilizar uma aplicação web simples em Python que inclui um contador de pedidos. Para tal, re­cor­re­mos ao framework Python Flask e à base de dados em memória Redis (também conhecida como In-Memory Database). Não vais precisar de instalar o Python nem o Redis, uma vez que os terás à dis­po­si­ção como imagens do Docker.

Passo 1. Criar os ficheiros do projeto

Abra o terminal e crie uma nova pasta para o projeto.

$ mkdir composedemo
shell

Em seguida, aceda à pasta que acabou de criar.

$ cd composedemo
shell

Crie o ficheiro app.py na pasta e insira o seguinte código:

import time
import redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)
def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)
@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I was here {} times.\n'.format(count)
python

Estamos a utilizar «redis» como nome de host e a porta «6379» como porta pre­de­fi­nida. Além disso, es­pe­ci­fi­cá­mos que a função get_hit_count() deve tentar ligar-se ao serviço várias vezes. Esta é a prática re­co­men­dada, uma vez que o Redis pode não estar dis­po­ní­vel logo após o arranque da aplicação ou pode apre­sen­tar problemas de ligação durante a sua execução.

Crie também o ficheiro re­qui­re­ments.txt com as de­pen­dên­cias ne­ces­sá­rias:

flask
redis
plaintext

Passo 2. Con­fi­gu­rar o Doc­ker­file

O Doc­ker­file é utilizado para criar a imagem do Docker. É aqui que se es­pe­ci­fi­cam todas as de­pen­dên­cias ne­ces­sá­rias à aplicação Python.

# syntax=docker/dockerfile:1
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]
shell

O Doc­ker­file indica ao Docker para utilizar a imagem Python 3.7. Também definimos as variáveis de ambiente para o comando flask. Com apk add, estamos a instalar o gcc e outras de­pen­dên­cias. Com EXPOSE, estamos a indicar que o contentor deve mo­ni­to­ri­zar a porta 5000. Com COPY, copiamos o conteúdo da pasta atual para o diretório de trabalho /code. Por fim, definimos flask run como comando padrão para o contentor.

Verifique se o ficheiro Doc­ker­file foi guardado sem extensão, uma vez que alguns editores adicionam au­to­ma­ti­ca­mente o sufixo .txt.

Passo 3. Criar o ficheiro YAML

Con­fi­gu­ra­mos os serviços «redis» e «web» no ficheiro docker-compose.yml.

version: "3.9"
services:
    web:
        build: .
        ports:
            - "8000:5000"
    redis:
        image: "redis:alpine"
yaml

O serviço «web» utiliza a imagem criada pelo Doc­ker­file e liga o contentor ao com­pu­ta­dor anfitrião através da porta 8000, enquanto o servidor web Flask é executado na porta 5000. Por outro lado, a imagem do Redis é obtida di­re­ta­mente do re­po­si­tó­rio oficial do Docker Hub.

Passo 4. Executar a aplicação com o Compose

Inicie a aplicação a partir da pasta do seu projeto.

docker compose up
shell

Abra o seu navegador e aceda a http://localhost:8000 ou http://127.0.0.1:8000; ambas as opções servem.

Deve ver a seguinte mensagem:

Imagem: Aplicación Docker Compose: muestra en el navegador el número de veces que has visitado la página
Te muestra en el navegador el número de veces que has visitado la página.

Atualize a página. O número de visitas deverá aumentar de 1 em 1.

Imagem: Al volver a ejecutar la aplicación Docker Compose
Se ha in­cre­men­tado en 1 el número de veces que se ha visitado.

Encerre a aplicação com o seguinte comando:

$ docker compose down
shell

Também podes premir Ctrl + C no terminal onde iniciaste a aplicação.

Passo 5. Adicionar uma ligação de montagem

Se quiseres adicionar um Bind Mount ao serviço web, podes fazê-lo no ficheiro docker-compose.yml.

version: "3.9"
services:
    web:
        build: .
        ports:
            - "8000:5000"
        volumes:
            - .:/code
        environment:
            FLASK_DEBUG: "true"
    redis:
        image: "redis:alpine"
yaml

Na secção «volumes», es­pe­ci­fi­ca­mos que a pasta do projeto atual deve ser montada no diretório /code dentro do contentor. Isto permite-lhe modificar o código sem ne­ces­si­dade de re­com­pi­lar a imagem. A variável de ambiente FLASK_DEBUG garante que flask run seja executado em modo de depuração.

Passo 6. Recriar e executar a aplicação

Introduza o seguinte comando no terminal para re­cons­truir o ficheiro Compose:

docker compose up
shell

Passo 7. Atualizar a aplicação

Agora que está a utilizar um Bind Mount na sua aplicação, pode alterar o seu código e ver as al­te­ra­ções au­to­ma­ti­ca­mente, sem ter de re­com­pi­lar a imagem.

Adicione uma nova linha de saudação no ficheiro app.py.

return 'Hello from Docker! I was here {} times.\n'.format(count)
python

Atualize o navegador para verificar se as al­te­ra­ções foram aplicadas cor­re­ta­mente.

Imagem: Aplicación Docker Compose: texto de bienvenida modificado
Se ha mo­di­fi­cado el texto de bi­en­ve­nida de la apli­ca­ción Python.

Passo 8. Outros comandos

A opção --help apresenta uma lista dos comandos dis­po­ní­veis para o Docker Compose:

docker compose --help
shell

Podes adicionar o argumento -d para executar o Docker Compose em segundo plano:

docker compose up -d
shell

Com down, todos os con­ten­to­res são eli­mi­na­dos. A opção --volumes também elimina os volumes uti­li­za­dos pelo contentor Redis.

docker compose down --volumes
shell
Ir para o menu principal