Pesquisa de sites

Como Instalar e Usar o Docker Compose no Ubuntu


Introdução

O Docker simplifica o processo de gestão de processos de aplicações em contentores. Embora os contentores sejam semelhantes às máquinas virtuais em certos aspetos, são mais leves e eficientes em termos de recursos. Isto permite aos programadores dividir um ambiente de aplicação em vários serviços isolados.

Para aplicações que dependem de vários serviços, orquestrar todos os contêineres para arrancar, comunicar e desligar em conjunto pode tornar-se rapidamente complicado. O Docker Compose é uma ferramenta que permite executar ambientes de aplicação com múltiplos contêineres com base em definições estabelecidas num ficheiro YAML. Utiliza definições de serviços para criar ambientes totalmente personalizáveis com múltiplos contêineres que podem partilhar redes e volumes de dados.

Este guia irá acompanhá-lo na instalação do Docker Compose num servidor Ubuntu e na execução de um contentor simples. A partir daí, aprenderá a criar um ambiente multi-serviço usando uma aplicação WordPress e uma base de dados MySQL. Também abordaremos tópicos mais avançados, incluindo dimensionamento de serviços, definição de redes personalizadas e utilização de diretivas modulares de inclusão. Finalmente, este artigo fornece um guia de migração do antigo docker-compose (v1) para o moderno docker compose (v2) e uma secção detalhada sobre a resolução de problemas comuns, como conflitos de portas e erros de permissões.

Pontos principais:

  • O Docker Compose é uma ferramenta para definir e executar aplicações com múltiplos containers, usando um único ficheiro YAML para configurar serviços, redes e volumes.
  • O Docker Compose está instalado no Ubuntu adicionando o repositório oficial do Docker e usando o apt para instalar o pacote docker-compose-plugin.
  • O comando moderno é docker compose (com um espaço). Este substitui a ferramenta v1 descontinuada docker-compose (com um hífen).
  • Use docker compose up -d para iniciar uma aplicação em modo destacado e docker compose down para parar e remover todos os seus contentores e redes.
  • A diretiva depends_on ajuda a controlar a ordem de arranque dos serviços, como garantir que um contêiner de base de dados arranca antes de um contêiner de aplicação web.
  • Os problemas mais frequentes são "Permissão Negada" (resolvido ao adicionar o seu utilizador ao grupo docker), conflitos de portas (resolvidos ao alterar a porta do host no ficheiro YAML) e erros de sintaxe em YAML (resolvidos ao corrigir a indentação).
  • Pode executar várias instâncias de um serviço usando o comando docker compose up --scale <service_name>=<number>.
  • A diretiva include permite dividir um grande ficheiro docker-compose.yml em ficheiros de configuração menores e mais fáceis de gerir.

Pré-requisitos

Para seguir este artigo, você precisará de:

  • Acesso a uma máquina local Ubuntu ou servidor de desenvolvimento como utilizador não-root com privilégios sudo. Se estiver a utilizar um servidor remoto, é aconselhável ter um firewall ativo instalado. Para configurar isto, consulte o nosso Guia de Configuração Inicial de Servidor para Ubuntu.
  • Docker instalado no seu servidor ou máquina local, seguindo Passos 1 e 2 de Como Instalar o Docker no Ubuntu – Guia Passo a Passo.

Nota: A partir do Docker Compose v2, a Docker passou a utilizar o comando do plugin CLI compose, afastando-se do original docker-compose, conforme documentado no nosso Guia Passo a Passo de Como Instalar o Docker Compose no Ubuntu. Embora a instalação seja diferente, em geral o uso prático envolve remover o hífen das chamadas docker-compose para passar a usar docker compose. Para detalhes completos de compatibilidade, consulte a documentação oficial da Docker sobre a compatibilidade de comandos entre o novo compose e o antigo docker-compose.

Passo 1 — Instalar o Docker Compose

Existem duas formas de instalar o Docker Compose no Ubuntu:

  • Instalar usando o repositório
  • Instalar manualmente

Vamos discutir ambos os modos nesta secção.

Instalar o Docker Compose utilizando o repositório apt

Primeiro, vamos configurar o repositório Docker apt.

# Add Docker's official GPG key:

sudo apt-get update

sudo apt-get install ca-certificates curl

sudo install -m 0755 -d /etc/apt/keyrings

sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc

sudo chmod a+r /etc/apt/keyrings/docker.asc



# Add the repository to Apt sources:

echo \

  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \

  $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \

  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update

Agora, pode instalar o Docker Compose usando o seguinte comando:

sudo apt install docker-compose-plugin

O Docker Compose está agora instalado com sucesso no seu sistema. Para verificar se a instalação foi bem-sucedida, pode executar:

docker compose version

Vais ver uma saída semelhante a esta:

Docker Compose version v2.3.3

Instalar o Docker Compose manualmente

Para garantir que obtenha a versão estável mais atualizada do Docker Compose, deverá descarregar este software a partir do seu repositório oficial no Github.

Primeiro, confirme a versão mais recente disponível na página de lançamentos deles. No momento em que este texto foi escrito, a versão estável mais atual é v2.40.2.

Utilize o seguinte comando para transferir:

mkdir -p ~/.docker/cli-plugins/

curl -SL https://github.com/docker/compose/releases/download/v2.40.2/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose

De seguida, defina as permissões corretas para que o comando docker compose seja executável:

chmod +x ~/.docker/cli-plugins/docker-compose

Na secção seguinte, verá como configurar um ficheiro docker-compose.yml e colocar um ambiente conteinerizado a funcionar com esta ferramenta.

Passo 2 — Configurar um ficheiro docker-compose.yml

Para demonstrar como configurar um ficheiro docker-compose.yml e trabalhar com o Docker Compose, irá criar um ambiente de servidor web usando a imagem oficial do Nginx do Docker Hub, o repositório público de Docker. Este ambiente conteinerizado irá servir um único ficheiro HTML estático.

Comece por criar um novo diretório na sua pasta pessoal e, em seguida, entre nele:

mkdir ~/compose-demo

cd ~/compose-demo

Neste diretório, crie uma pasta de aplicação para servir como a raiz de documentos do seu ambiente Nginx:

mkdir app

Usando o seu editor de texto preferido, crie um novo ficheiro index.html dentro da pasta app:

nano app/index.html

Coloque o seguinte conteúdo neste ficheiro:

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Docker Compose Demo</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/kognise/water.css@latest/dist/dark.min.css">
</head>
<body>

    <h1>This is a Docker Compose Demo Page.</h1>
    <p>This content is being served by an Nginx container.</p>

</body>
</html>

Guarde e feche o ficheiro quando terminar. Se estiver a usar o nano, pode fazê-lo ao pressionar CTRL+X, depois Y e ENTER para confirmar.

De seguida, crie o ficheiro docker-compose.yml:

nano docker-compose.yml

Insira o seguinte conteúdo no seu ficheiro docker-compose.yml:

services:
  web:
    image: nginx:alpine
    ports:
      - "8000:80"
    volumes:
      - ./app:/usr/share/nginx/html

No Docker Compose moderno, o campo version é opcional e muitas vezes omitido, uma vez que o Compose pode detetar automaticamente a versão da configuração. O exemplo acima não inclui um campo version, que é a abordagem recomendada para a maioria dos projetos novos. Só precisa de especificar version para compatibilidade com versões antigas.

De seguida, tens o bloco services, onde configuras os serviços que fazem parte deste ambiente. No teu caso, tens um único serviço chamado web. Este serviço utiliza a imagem nginx:alpine e configura um redirecionamento de portas com a diretiva ports. Todos os pedidos na porta 8000 da máquina host (o sistema a partir do qual estás a executar o Docker Compose) serão redirecionados para o contêiner web na porta 80, onde o Nginx estará a correr.

A diretiva volumes irá criar um volume partilhado entre a máquina anfitriã e o contêiner. Isto irá partilhar a pasta local app com o contêiner, e o volume será localizado em /usr/share/nginx/html dentro do contêiner, o que irá sobrescrever o root de documentos padrão do Nginx.

Guardar e fechar o ficheiro.

Você configurou uma página de demonstração e um ficheiro docker-compose.yml para criar um ambiente de servidor web em containers que a servirá. No próximo passo, irá levantar este ambiente com o Docker Compose.

Passo 3 — Executar o Docker Compose

Com o ficheiro docker-compose.yml no lugar, pode agora executar o Docker Compose para iniciar o seu ambiente. O seguinte comando irá descarregar as imagens Docker necessárias, criar um contentor para o serviço web e executar o ambiente em contentor em modo de segundo plano:

docker compose up -d

O Docker Compose irá primeiro procurar pela imagem definida no seu sistema local e, se não conseguir localizar a imagem, irá transferi-la do Docker Hub. Verá uma saída semelhante a esta:

Creating network "compose-demo_default" with the default driver
Pulling web (nginx:alpine)...
alpine: Pulling from library/nginx
cbdbe7a5bc2a: Pull complete
10c113fb0c77: Pull complete
9ba64393807b: Pull complete
c829a9c40ab2: Pull complete
61d685417b2f: Pull complete
Digest: sha256:57254039c6313fe8c53f1acbf15657ec9616a813397b74b063e32443427c5502
Status: Downloaded newer image for nginx:alpine
Creating compose-demo_web_1 ... done

Nota: Se encontrar um erro de “permissão negada” ao executar docker compose up, isso normalmente significa que o seu utilizador não root não tem permissão para aceder ao socket do daemon do Docker.

Por padrão, o daemon do Docker liga-se a um socket Unix (/var/run/docker.sock) que é propriedade do utilizador root. Para resolver isto, deve adicionar o seu utilizador não-root ao grupo docker, que é criado durante a instalação do Docker.

Execute o seguinte comando para adicionar o seu utilizador ao grupo docker:

sudo usermod -aG docker ${USER}

Após executar este comando, será necessário sair e voltar a entrar para que as alterações de grupo tenham efeito. Também pode ativar as alterações na sessão atual do terminal digitando:

newgrp docker

Este comando deverá resolver quaisquer erros de permissão relacionados com o socket do Docker. Para um guia completo, consulte o Passo 2 de Como Instalar o Docker no Ubuntu – Guia Passo a Passo.

O seu ambiente está agora ativo em segundo plano. Para verificar se o contentor está em funcionamento, pode executar:

docker compose ps

Este comando mostrará informações sobre os contêineres em execução e o seu estado, bem como quaisquer redirecionamentos de portas atualmente em vigor:

       Name                     Command               State          Ports        
----------------------------------------------------------------------------------
compose-demo_web_1   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:8000->80/tcp

Agora pode aceder à aplicação de demonstração apontando o seu navegador para localhost:8000 se estiver a executar esta demonstração na sua máquina local, ou seu_domínio_ou_IP_do_servidor:8000 se estiver a executar esta demonstração num servidor remoto.

Vais ver uma página como esta:

O volume partilhado que configurou no ficheiro docker-compose.yml mantém os ficheiros da pasta app sincronizados com a raiz de documentos do contêiner. Se fizer alguma alteração no ficheiro index.html, esta será automaticamente detectada pelo contêiner e, assim, refletida no seu navegador quando recarregar a página.

No próximo passo, verá como gerir o seu ambiente conteinerizado com comandos do Docker Compose.

Passo 4 — Familiarizar-se com os comandos do Docker Compose

Você viu como configurar um ficheiro docker-compose.yml e iniciar o seu ambiente com docker compose up. Agora irá ver como usar os comandos do Docker Compose para gerir e interagir com o seu ambiente em contentores.

Para verificar os registos produzidos pelo seu contentor Nginx, pode usar o comando logs:

docker compose logs

Vais ver uma saída semelhante a esta:

Attaching to compose-demo_web_1
web_1  | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
web_1  | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
web_1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
web_1  | 10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf
web_1  | 10-listen-on-ipv6-by-default.sh: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
web_1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
web_1  | /docker-entrypoint.sh: Configuration complete; ready for start up
web_1  | 172.22.0.1 - - [02/Jun/2020:10:47:13 +0000] "GET / HTTP/1.1" 200 353 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36" "-"

Se quiser pausar a execução do ambiente sem alterar o estado atual dos seus containers, pode usar:

docker compose pause
Pausing compose-demo_web_1 ... done

Para retomar a execução após emitir uma pausa:

docker compose unpause
Unpausing compose-demo_web_1 ... done

O comando stop irá terminar a execução do contêiner, mas não irá destruir nenhum dado associado aos seus contêineres:

docker compose stop
Stopping compose-demo_web_1 ... done

Se quiser remover os contentores, redes e volumes associados a este ambiente conteinerizado, utilize o comando down:

docker compose down
Removing compose-demo_web_1 ... done
Removing network compose-demo_default

Note que isto não irá remover a imagem base utilizada pelo Docker Compose para iniciar o seu ambiente (no seu caso, nginx:alpine). Desta forma, sempre que voltar a levantar o seu ambiente com um docker compose up, o processo será muito mais rápido, uma vez que a imagem já se encontra no seu sistema.

Caso queira também remover a imagem base do seu sistema, pode usar:

docker image rm nginx:alpine
Untagged: nginx:alpine
Untagged: nginx@sha256:b89a6ccbda39576ad23fd079978c967cecc6b170db6e7ff8a769bf2259a71912
Deleted: sha256:7d0cdcc60a96a5124763fddf5d534d058ad7d0d8d4c3b8be2aefedf4267d0270
Deleted: sha256:05a0eaca15d731e0029a7604ef54f0dda3b736d4e987e6ac87b91ac7aac03ab1
Deleted: sha256:c6bbc4bdac396583641cb44cd35126b2c195be8fe1ac5e6c577c14752bbe9157
Deleted: sha256:35789b1e1a362b0da8392ca7d5759ef08b9a6b7141cc1521570f984dc7905eb6
Deleted: sha256:a3efaa65ec344c882fe5d543a392a54c4ceacd1efd91662d06964211b1be4c08
Deleted: sha256:3e207b409db364b595ba862cdc12be96dcdad8e36c59a03b7b3b61c946a5741a

Nota: Por favor, consulte o nosso guia Como Instalar o Docker no Ubuntu – Guia Passo a Passo para uma referência mais detalhada sobre os comandos do Docker.

Passo 5 — Construir uma Aplicação Multi-Serviço

O verdadeiro poder do Docker Compose está em gerir múltiplos serviços que trabalham em conjunto. O exemplo do Nginx era um serviço único. Vamos criar uma aplicação mais prática, com múltiplos serviços: um site WordPress ligado a uma base de dados MySQL.

Esta configuração envolve dois serviços: wordpress (a executar a aplicação) e db (a executar a base de dados). Também vamos usar volumes do Docker para garantir que os dados da base de dados persistem mesmo que o contêiner seja removido.

Vamos criar um novo diretório para esta aplicação:

mkdir -p ~/compose-demo/wordpressapp

cd ~/compose-demo/wordpressapp

Para este exemplo, não precisamos de ficheiros locais, pois as imagens conterão todo o software necessário.

Crie um novo ficheiro docker-compose.yml:

nano docker-compose.yml

Cole a seguinte configuração. Este ficheiro é mais complexo, por isso vamos examinar cada parte.

services:
  db:
    image: mysql:8.0
    container_name: mysql_db
    volumes:
      - db_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: <^your_root_password_here<^>
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress_user
      MYSQL_PASSWORD: <^your_wordpress_password_here<^>
    restart: unless-stopped

  wordpress:
    image: wordpress:latest
    container_name: wordpress_app
    ports:
      - "8001:80"
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress_user
      WORDPRESS_DB_PASSWORD: <^your_wordpress_password_here<^>
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - ./wp_content:/var/www/html/wp-content
    depends_on:
      - db
    restart: unless-stopped

volumes:
  db_data:

Nota: Nós inserimos os valores da palavra-passe diretamente aqui apenas para fins ilustrativos. Ao utilizar num ambiente real, certifique-se de usar variáveis de ambiente no ficheiro .env para evitar expor as suas credenciais.

Guarde e feche o ficheiro. Lembre-se de substituir os espaços reservados <^...^> por palavras-passe fortes e seguras.

Vamos analisar as novas diretivas deste ficheiro:

  • services: Este bloco ainda define os nossos contentores. Agora temos dois: db e wordpress.
  • image: Estamos a usar mysql:8.0 para a base de dados e a imagem wordpress:latest para a aplicação.
  • container_name: Isto define um nome específico e legível para o ser humano para o contentor, que é mais fácil de referenciar do que os gerados automaticamente.
  • environment: Esta é uma lista de variáveis de ambiente passadas para o container. A imagem mysql usa-as para definir a password de root e criar uma base de dados e um utilizador inicial. A imagem wordpress usa-as para saber como se ligar à sua base de dados.
  • volumes (nível de serviço):

    • Para o serviço db, db_data:/var/lib/mysql mapeia um volume gerido pelo Docker chamado db_data para o diretório de dados do MySQL dentro do contêiner. Isto mantém os seus dados seguros.
    • Para o serviço wordpress, ./wp_content:/var/www/html/wp-content mapeia um diretório local (wp_content) para o diretório de conteúdo do WordPress. Isto permite que edite diretamente temas e plugins a partir da sua máquina anfitriã.
  • depends_on: Isto indica ao Compose para iniciar o serviço db antes de iniciar o serviço wordpress. Isto é importante, pois o WordPress falhará se não conseguir encontrar a sua base de dados ao arrancar.
  • volumes (top-level): Este bloco define os volumes nomeados. db_data: cria um volume gerido pelo Docker, que é a forma preferida de lidar com dados persistentes.

Agora, inicie esta aplicação multi-serviços:

docker compose up -d

O Compose irá buscar as imagens mysql e wordpress e, em seguida, criar os contêineres, iniciando primeiro o serviço db.

Creating network "compose-demo_default" with the default driver
Creating volume "compose-demo_db_data" with default driver
Pulling db (mysql:8.0)...
...
Pulling wordpress (wordpress:latest)...
...
Creating mysql_db        ... done
Creating wordpress_app ... done

Agora pode aceder ao seu novo site WordPress navegando para localhost:8001 ou <^your_server_domain_or_IP<^>:8001 no seu navegador. Deve ver o ecrã de instalação do WordPress. Para um exemplo mais detalhado, consulte o nosso artigo sobre Como Instalar o WordPress com o Docker Compose

Passo 6 — Utilizar o Docker Compose para Desenvolvimento de IA/ML

Para além das aplicações web, o Docker Compose é uma ferramenta extremamente útil para criar ambientes de ciência de dados e de aprendizagem automática (IA/ML) reproduzíveis. Os projetos de IA/ML são conhecidos pelas suas dependências complexas, incluindo versões específicas do Python, bibliotecas como TensorFlow ou PyTorch, e drivers ao nível do sistema como o NVIDIA CUDA Toolkit. O Docker Compose captura todo este ambiente em ficheiros de configuração, resolvendo o problema do «funciona na minha máquina», que é crítico para a investigação reproduzível.

Neste exemplo, irá criar um ambiente de IA/ML com múltiplos serviços constituído por:

  • JupyterLab: Um ambiente para desenvolvimento interativo, construído a partir de um Dockerfile personalizado.
  • PostgreSQL: Um contentor de base de dados para armazenar resultados de experiências e metadados.
  • Acesso à GPU: O contêiner JupyterLab será configurado para aceder à GPU NVIDIA da máquina anfitriã, um requisito comum para o treino de modelos.

Pré-requisito: Este exemplo requer uma GPU NVIDIA na sua máquina anfitriã e que o NVIDIA Container Toolkit esteja instalado. Sem isso, o container não será iniciado ao solicitar recursos de GPU.

Estrutura de Ficheiros

Primeiro, crie um diretório para o seu projeto. Dentro dele, você irá criar um ficheiro docker-compose.yml, um diretório jupyter, um Dockerfile para o Jupyter e um ficheiro requirements.txt. A estrutura deverá ficar algo assim:

ai-project/
├── docker-compose.yml
└── jupyter/
    ├── Dockerfile
    └── requirements.txt

Criar os Ficheiros do Componente

1. O ficheiro requirements.txt

Este ficheiro lista os pacotes Python para o seu ambiente de ciência de dados.

nano jupyter/requirements.txt

Adicione os pacotes necessários. Para este exemplo, iremos incluir bibliotecas para manipulação de dados, ligação a bases de dados e um framework de aprendizagem profunda.

pandas
scikit-learn
tensorflow
jupyterlab
psycopg2-binary

Guardar e fechar o ficheiro.

2. O Dockerfile

Este ficheiro define o seu serviço personalizado do JupyterLab. Ele utiliza uma imagem oficial do Jupyter como base e instala os pacotes do requirements.txt.

nano jupyter/Dockerfile

Cole o seguinte conteúdo:

# Start from a base image that includes Jupyter and scientific libraries
FROM jupyter/scipy-notebook:latest

# Copy our local requirements file into the container
COPY requirements.txt /tmp/requirements.txt

# Install the Python packages
RUN pip install --no-cache-dir -r /tmp/requirements.txt

Este ficheiro instrui o Docker a usar jupyter/scipy-notebook como ponto de partida, copiar o seu requirements.txt para o contêiner e depois usar pip para instalar os pacotes.

Definir o Ambiente com docker-compose.yml

Agora, crie o ficheiro principal docker-compose.yml. Este ficheiro irá orquestrar tanto o serviço db como o seu serviço personalizado jupyter.

nano docker-compose.yml

Cole a seguinte configuração, substituindo os espaços reservados <^...^> pelas suas próprias credenciais seguras.

services:
  db:
    image: postgres:15-alpine
    container_name: ai_postgres_db
    environment:
      POSTGRES_USER: <^your_db_user^>
      POSTGRES_PASSWORD: <^your_db_pass^>
      POSTGRES_DB: experiments
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U <^your_db_user^> -d experiments"]
      interval: 10s
      timeout: 5s
      retries: 5
    volumes:
      - postgres_data:/var/lib/postgresql/data
    restart: unless-stopped
    networks:
      - ai_net

  jupyter:
    build: ./jupyter
    container_name: ai_jupyter_lab
    ports:
      - "8888:8888"
    volumes:
      - ./notebooks:/home/jovyan/work
    environment:
      - POSTGRES_HOST=db
      - POSTGRES_USER=<^your_db_user^>
      - POSTGRES_PASSWORD=<^your_db_pass^>
      - POSTGRES_DB=experiments
    restart: unless-stopped
    networks:
      - ai_net
    depends_on:
      db:
        condition: service_healthy
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]

volumes:
  postgres_data:
    name: ai_project_data

networks:
  ai_net:
    driver: bridge

Este ficheiro de configuração apresenta vários conceitos importantes:

  • build: ./jupyter: Isto diz ao Docker Compose para criar uma imagem personalizada para o serviço jupyter. Procura um Dockerfile dentro do diretório especificado ./jupyter.
  • volumes: - ./notebooks:/home/jovyan/work: Isto liga um diretório local chamado notebooks ao contêiner. Isto garante que todos os notebooks do Jupyter que criar são salvos diretamente na sua máquina anfitriã, persistindo mesmo depois de o contêiner ser removido.
  • healthcheck: Como visto na secção de resolução de problemas, esta verificação valida que o serviço db não está apenas a correr, mas está pronto para aceitar ligações antes de outros serviços iniciarem.
  • depends_on: ... condition: service_healthy: Isto indica ao serviço jupyter para esperar até que o healthcheck do db seja bem-sucedido antes de iniciar.
  • deploy.resources.reservations.devices: Este é o bloco que solicita acesso à GPU.

    • driver: nvidia: Especifica o driver do anfitrião a utilizar.
    • count: 1: Solicita uma GPU.
    • capabilities: [gpu]: Garante que o contentor possui as capacidades necessárias para utilizar a GPU.

Executar o Ambiente de IA/ML

Com os seus ficheiros no lugar, está pronto para construir e executar os serviços.

  1. A partir do seu diretório ai-project, execute o comando docker compose up. Deve adicionar a opção --build na primeira vez para indicar ao Compose que construa a sua imagem personalizada jupyter.

    docker compose up -d --build
  2. O Compose irá primeiro construir a imagem jupyter (o que pode demorar alguns minutos enquanto faz o download do TensorFlow), depois irá puxar a imagem postgres e, finalmente, iniciar ambos os contêineres.

    [+] Building 5.8s (9/9) FINISHED
     => [internal] load build definition from Dockerfile
    ...
    [+] Running 3/3
     ✔ Network ai-project_ai_net        Created
     ✔ Container ai_postgres_db         Started
     ✔ Container ai_jupyter_lab         Started
  3. Agora pode aceder à interface do JupyterLab navegando para http://localhost:8888 (ou <^seu_ip_do_servidor^>:8888) no seu navegador. Será solicitado um token, que pode obter nos registos do container:

    docker compose logs jupyter

    Procure uma linha semelhante a http://127.0.0.1:8888/lab?token=a1b2c3d4e5f6...

  4. Dentro de um notebook Jupyter, você pode agora ligar-se à sua base de dados usando o nome do anfitrião db e as credenciais que forneceu. O seu ambiente também tem acesso à GPU do anfitrião para treino de modelos.

Dimensionamento de Serviços e Utilização de Redes Personalizadas

O Docker Compose inclui funcionalidades para escalar serviços e gerir as redes nas quais comunicam.

Escalamento de Serviço com Réplicas

Imagine que o seu servidor web Nginx do Passo 2 está a receber demasiado tráfego. Pode escalar o serviço web para executar várias instâncias de containers. O Docker Compose pode gerir isto automaticamente.

Existem duas formas principais de expandir um serviço.

1. Utilizando a chave replicas (Preferido na v2)

Pode definir o número desejado de instâncias diretamente no seu ficheiro docker-compose.yml usando as chaves deploy e replicas. Esta funcionalidade fazia originalmente parte do Docker Swarm mas agora está disponível para implementações standard do Compose.

Modifique o seu docker-compose.yml do Nginx do Passo 2:

services:
  web:
    image: nginx:alpine
    ports:
      - "8000:80"
    volumes:
      - ./app:/usr/share/nginx/html
    deploy:
      replicas: 3

Quando executa docker compose up -d, o Compose irá criar três contêineres web. No entanto, terá um problema: todos os três irão tentar ligar-se à porta 8000 do host. Isto causará um erro de “port is already allocated” para o segundo e terceiro contêineres. Para resolver isto num ambiente de produção, você removeria o mapeamento de ports do serviço web. Desta forma, os contêineres web são acessíveis apenas dentro da rede Docker. Um serviço separado de balanceamento de carga seria o único com uma porta pública. Este, então, distribuiria o tráfego para as três réplicas web.

Um exemplo de configuração seria este (este é um exemplo avançado):

services:
  web:
    image: nginx:alpine
    # No 'ports' mapping here.
    # The service is only accessible inside the 'web-net' network.
    volumes:
      - ./app:/usr/share/nginx/html
    deploy:
      replicas: 3
    networks:
      - web-net

  load_balancer:
    image: nginx:latest
    ports:
      - "80:80" # The load_balancer is the only service with a public port.
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf # A config file that load balances to 'web'.
    networks:
      - web-net
    depends_on:
      - web

networks:
  web-net:

Nesta configuração, o load_balancer escuta na porta 80 e encaminha as solicitações internamente para web_1, web_2 e web_3.

Esta chave replicas é mais útil quando utilizada com um proxy inverso (como Traefik ou outra instância Nginx) que consiga distribuir a carga das requisições entre as réplicas dentro da rede Docker, sem que cada réplica precise de expor uma porta no host.

2. Usar a flag --scale

Um método comum para escalonar é o parâmetro --scale, uma herança do Compose v1. Este parâmetro é aplicado em tempo de execução e substitui qualquer chave replicas.

No entanto, deve ter cuidado com as definições de portas. Se o seu serviço definir um mapeamento de porta fixa do host (por exemplo, "8000:80"), executar docker compose up --scale causará um erro nos segundo e terceiro contêineres, uma vez que todos tentarão ligar-se à mesma porta do host.

Para usar --scale em serviços que expõem portas, não deve usar um mapeamento de porta fixa no host.

  • Opção 1: Mapear para Portas Aleatórias do Host (Bom para Desenvolvimento)

    Pode modificar o seu docker-compose.yml para especificar apenas a porta do contêiner. Isto indica ao Docker para mapear a porta 80 de cada contêiner para uma porta aleatória disponível na sua máquina anfitriã.

    services:
      web:
        image: nginx:alpine
        ports:
          - "80" # No fixed host port
        volumes:
          - ./app:/usr/share/nginx/html

    Agora, quando executar o comando de escala:

    docker compose up -d --scale web=3

    Execute docker compose ps para ver o resultado. Cada contêiner estará a correr numa porta de host diferente, atribuída aleatoriamente:

          Name                     Command               State          Ports        
    ----------------------------------------------------------------------------------
    compose-demo_web_1   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:49154->80/tcp
    compose-demo-web_2   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:49155->80/tcp
    compose-demo-web_3   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:49156->80/tcp
  • docker-compose.yml - Correto para --scale

  • Opção 2: Usar um Proxy Reverso (Bom para Produção)

    A outra solução, como mencionado na secção replicas, é remover completamente a directiva ports do serviço web. De seguida, usaria um contentor de balanceamento de carga separado (que possui a única porta pública) para gerir e distribuir o tráfego para as réplicas escaladas dentro da rede Docker.

    Para parar e remover os três contentores, o comando mantém-se o mesmo:

    docker compose down

Configuração Personalizada de Rede

Por defeito, o Docker Compose cria uma única rede bridge para a sua aplicação. Cada serviço no ficheiro está ligado a esta rede, que é como o contentor wordpress conseguiu encontrar o contentor db apenas usando o nome do serviço (db).

No entanto, pode definir as suas próprias redes personalizadas para melhor isolamento e controlo.

Vamos modificar o exemplo do WordPress para usar uma rede bridge personalizada.

services:
  db:
    image: mysql:8.0
    ...
    networks:
      - app_net

  wordpress:
    image: wordpress:latest
    ...
    ports:
      - "8001:80"
    depends_on:
      - db
    networks:
      - app_net

volumes:
  db_data:

networks:
  app_net:
    driver: bridge

Isto é o que acrescentámos:

  • networks (nível superior): Isto define uma nova rede chamada app_net e especifica que deve usar o driver padrão bridge.
  • networks (a nível de serviço): Sob tanto db como wordpress, esta chave liga-os à nossa rede app_net.

Se tivesse um terceiro serviço (como uma ferramenta de análise) que não ligasse ao app_net, ele estaria completamente isolado e incapaz de comunicar com os conteúdos db ou wordpress.

Para clusterização multi-host com o Docker Swarm, você alteraria o driver de bridge para overlay. O driver bridge destina-se à comunicação entre contêineres num único host, que é o padrão para a maioria dos casos de uso do Docker Compose.

Usar Ficheiros de Configuração Modulares

À medida que as suas aplicações crescem, o seu ficheiro docker-compose.yml pode tornar-se grande e difícil de gerir. O Docker Compose suporta uma diretiva include, permitindo-lhe dividir a sua configuração por vários ficheiros.

Imagine que quer separar as definições do WordPress e da base de dados, e talvez ter um docker-compose.override.yml comum para configurações específicas de desenvolvimento (como ligar uma porta na base de dados).

A estrutura do seu diretório pode parecer assim:

compose-demo/
├── docker-compose.yml
├── docker-compose.db.yml
├── docker-compose.web.yml

Este ficheiro irá apenas definir o serviço db.

services:
  db:
    image: mysql:8.0
    container_name: mysql_db
    volumes:
      - db_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: <^your_root_password_here<^>
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress_user
      MYSQL_PASSWORD: <^your_wordpress_password_here<^>
    restart: unless-stopped

volumes:
  db_data:

Este ficheiro irá apenas definir o serviço wordpress.

services:
  wordpress:
    image: wordpress:latest
    container_name: wordpress_app
    ports:
      - "8001:80"
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress_user
      WORDPRESS_DB_PASSWORD: <^your_wordpress_password_here<^>
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - ./wp_content:/var/www/html/wp-content
    depends_on:
      - db
    restart: unless-stopped

Agora, o seu ficheiro principal docker-compose.yml torna-se muito simples. Ele apenas usa include para incluir os outros ficheiros.

include:
  - docker-compose.db.yml
  - docker-compose.web.yml

Quando executa docker compose up -d, o Compose irá ler os três ficheiros, fundir as configurações e iniciar os serviços db e wordpress exatamente como se estivessem definidos num único ficheiro. Esta abordagem torna a sua configuração muito mais modular e reutilizável.

Nota: A diretiva include: requer o Docker Compose v2.20 ou superior. Se o seu sistema utilizar uma versão mais antiga, pode combinar ficheiros usando docker compose -f docker-compose.db.yml -f docker-compose.web.yml up.

Migrar de docker-compose (v1) para docker compose (v2)

O comando docker compose que instalou no Passo 1 é a “Compose v2.” É um plugin baseado em Go incorporado diretamente na CLI do Docker.

A versão original, "Compose v1", era uma ferramenta Python separada invocada com docker-compose (com hífen). A partir de julho de 2023, o Compose v1 deixou de ser suportado e foi descontinuado.

Principais Alterações e Compatibilidade Retroativa

  • O Comando: A mudança mais óbvia é o comando. O hífen (docker-compose) passou a ser um espaço (docker compose).
  • Instalação: a v1 foi instalada com pip. A v2 está incluída no Docker Desktop ou instalada como um plugin de CLI, tal como fez no Passo 1.
  • Ficheiros YAML: Os seus ficheiros docker-compose.yml são quase 100% compatíveis com versões anteriores. O Compose v2 suporta totalmente as versões de ficheiro 3.x. Não é necessário alterar os seus ficheiros YAML para a migração, apenas os seus comandos.
  • --project-name flag: A flag -p ainda funciona, mas a flag completa agora é --project-name em vez de --project_name.

Guia de Migração de Comandos

A maioria dos comandos é idêntica, apenas com o hífen removido. Aqui está uma tabela comparando os comandos comuns da versão v1 com os seus equivalentes na v2.

Comando docker-compose (v1)Comando docker compose (v2)Notas
docker-compose up -d
docker compose up -d
Nenhuma alteração na sintaxe.
docker-compose down
docker compose down
Nenhuma alteração na sintaxe.
docker-compose ps
docker compose ps
Nenhuma alteração na sintaxe.
docker-compose logs
docker compose logs
Nenhuma alteração na sintaxe.
docker-compose stop
docker compose stop
Nenhuma alteração na sintaxe.
docker-compose build
docker compose build
Nenhuma alteração na sintaxe.
docker-compose exec web bash
docker compose exec web bash
Nenhuma alteração na sintaxe.
docker-compose run web bash
docker compose run web bash
run cria um novo contêiner. exec executa num já existente.
docker-compose up --scale web=3
docker compose up --scale web=3
O flag --scale ainda é suportado na v2.

Como pode ver, para a maioria dos usos do dia a dia, a única alteração é docker-compose -> docker compose. Se utilizar scripts, pode atualizá-los simplesmente removendo o hífen.

Se ainda tiver a versão antiga do docker-compose v1 instalada, pode removê-la para evitar confusões:

sudo pip3 uninstall docker-compose

Ou, se foi instalado através do apt:

sudo apt remove docker-compose

Resolução de Problemas Comuns do Docker Compose

Quando trabalha com o Docker Compose, pode encontrar problemas relacionados com a sintaxe de ficheiros, permissões ou conflitos no tempo de execução dos conteúdos. A maioria dos problemas pode ser diagnosticada e resolvida verificando meticulosamente a sua configuração, permissões e registos dos conteúdos.

Vamos ver alguns dos erros mais comuns e as suas soluções.

Permissão Negada (Socket do Docker)

Este é um dos erros mais comuns para novos utilizadores do Docker. Executa docker compose up e vê uma mensagem de erro sobre o socket do daemon do Docker.

permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock
  • Problema: O seu utilizador não root não tem permissão para comunicar com o daemon do Docker, que é executado como root.

  • Solução: Deve adicionar o seu utilizador ao grupo docker, que foi criado durante a instalação do Docker.

    1. Adicione o seu utilizador ao grupo docker:

      sudo usermod -aG docker ${USER}
    2. Para que a nova associação ao grupo entre em vigor, deve sair e voltar a iniciar sessão.

    3. Alternativamente, pode ativar as alterações de grupo para a sua sessão de terminal atual digitando:

      newgrp docker

    Isto deve resolver quaisquer erros de permissão relacionados com o socket do Docker.

Erros de Sintaxe e Indentação em YAML

O Docker Compose não consegue correr e indica que o seu ficheiro docker-compose.yml é inválido.

ERROR: The Compose file './docker-compose.yml' is invalid because:
services.web.ports contains an invalid type, it should be a list

Ou :

mapping values are not allowed in this context at line 5
  • Problema: O ficheiro docker-compose.yml depende de uma sintaxe YAML rigorosa. O erro mais comum é a identação incorreta. O YAML utiliza espaços, e não tabs, para definir a estrutura.
  • Solução: Verifique cuidadosamente a indentação do seu ficheiro docker-compose.yml.

    • O padrão é dois espaços para cada nível de indentação.
    • Certifique-se de que todas as chaves ao mesmo nível (como version, services, volumes) começam na mesma coluna.
    • Certifique-se de que todas as subchaves (como image, ports, volumes debaixo de um serviço) estão recuadas duas espaços a mais do que o serviço pai (por exemplo, web).
    • Use um editor de código com um verificador de sintaxe YAML para assinalar automaticamente os erros de sintaxe.

Conflitos Portuários

Tenta iniciar o seu ambiente, mas o comando falha com uma mensagem de erro a indicar que o endereço já está em uso.

Error starting userland proxy: listen tcp 0.0.0.0:8000: bind: address already in use
  • Problema: Outro processo na sua máquina anfitriã já está a ouvir na porta que está a tentar mapear (neste caso, a porta 8000). Isto é frequentemente outro contêiner Docker ou um servidor de desenvolvimento local.

  • Solução: Tem duas opções:

    1. Pare o outro processo. Pode encontrar o processo que está a usar a porta com este comando:

      sudo lsof -i :8000

      Se for outro contêiner Docker, pare-o com docker stop <container_id>.

    2. Altere a porta do host no seu ficheiro docker-compose.yml. Esta é frequentemente a solução mais simples. Altere o mapeamento de ports de "8000:80" para uma porta diferente, como "8001:80".

      ...
      ports:
        - "8001:80" # Changed from 8000
      ...
    3. docker-compose.yml

O serviço falha com Conexão Recusada (depends_on)

Numa aplicação multi-serviço (como o exemplo do WordPress e MySQL), o contentor wordpress inicia, mas os seus registos mostram Connection refused ou MySQL server has gone away ao tentar ligar-se ao serviço db.

  • Problema: Você usou depends_on, mas esta diretiva apenas espera que o contêiner db inicie. Não espera que a aplicação MySQL dentro do contêiner esteja totalmente inicializada e pronta para aceitar conexões.

  • Solução: A aplicação (neste caso, o WordPress) deve ser configurada para tentar novamente a ligação. A maioria das imagens modernas já tem essa lógica de tentativas incorporada. Para imagens que não a possuem, deve implementar um verificador de estado (healthcheck).

    Pode adicionar um healthcheck ao seu serviço db. O depends_on do serviço wordpress pode então ser configurado para esperar que a base de dados esteja "saudável", e não apenas "iniciada".

Exemplo de Verificação de Saúde para MySQL:

services:
  db:
    image: mysql:8.0
    ...
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p<^your_root_password_here<^>"]
      interval: 10s
      timeout: 5s
      retries: 5

  wordpress:
    image: wordpress:latest
    ...
    depends_on:
      db:
        condition: service_healthy # This now waits for the healthcheck
    ...

Erros com Volumes e Montagens Bind

Pode encontrar erros de permissões nos registos do seu recipiente ou descobrir que o diretório de dados do seu recipiente está vazio.

Permissões de Ficheiro/Diretório

  • Problema: O contentor é executado como um utilizador específico (por exemplo, www-data com ID de utilizador 33), mas o diretório do host que montou é propriedade do seu utilizador (por exemplo, ubuntu com ID de utilizador 1000). O utilizador do contentor não tem permissão para escrever no diretório do host.

  • Solução: Altere a propriedade do diretório do host para corresponder ao ID de utilizador dentro do contêiner. Pode encontrar o ID de utilizador do contêiner executando docker compose exec <service_name> id. Por exemplo, se o ID for 33 (comum para www-data):

    sudo chown -R 33:33 ./wp_content

Problemas com Caminho Relativo

  • Problema: O seu docker-compose.yml usa um caminho relativo como ./app, mas o seu ficheiro index.html não está a ser servido.

  • Solução: O Docker Compose interpreta caminhos relativos a partir do diretório onde executa o comando docker compose up. Execute sempre os comandos do Compose a partir do mesmo diretório que contém o seu ficheiro docker-compose.yml.

Rede e Descoberta de Serviços

Os registos do recipiente da sua aplicação mostram Host não encontrado ou Não foi possível resolver o host: db.

  • Problema: O seu contentor wordpress não consegue encontrar o contentor db na rede.
  • Solução: Por defeito, o Docker Compose cria uma rede e liga todos os serviços a ela. Os serviços podem encontrar-se entre si usando os seus nomes de serviço.

    1. Verificar Nomes de Serviços: Certifique-se de que o nome do host na configuração da sua aplicação (por exemplo, a variável de ambiente WORDPRESS_DB_HOST) é exatamente o mesmo que o nome do serviço no seu docker-compose.yml (por exemplo, db).

    2. Inspecionar a Rede: Use docker compose ps para encontrar o nome do seu projeto (por exemplo, compose-demo). Depois, inspecione a rede predefinida:

      docker network inspect compose-demo_default

      A saída JSON listará todos os contêineres ligados a esta rede. Se algum dos seus serviços estiver em falta, verifique o seu docker-compose.yml para qualquer configuração personalizada de networks que possa estar a isolá-lo.

Incompatibilidade de Comandos (v1 vs. v2)

Você digita docker-compose up (com hífen) e vê um erro de “comando não encontrado”.

docker-compose: command not found
  • Problema: Está a tentar usar o comando para o Compose v1, que é uma ferramenta Python obsoleta. Este guia instala o Compose v2, que é um plugin integrado diretamente na CLI do Docker.
  • Solução: Use o comando correto substituindo o hífen (-) por um espaço.
docker-compose (v1)docker compose (v2)
docker-compose updocker compose up
docker-compose downdocker compose down
docker-compose psdocker compose ps
docker-compose logsdocker compose logs

Use sempre docker compose (espaço) ao seguir este guia.

Perguntas Frequentes

1. Para que é utilizado o Docker Compose?

O Docker Compose é uma ferramenta para definir e executar aplicações Docker com múltiplos contentores.

Utiliza um único ficheiro YAML (por defeito, docker-compose.yml) para configurar todos os componentes da sua aplicação, que são chamados de serviços. Este ficheiro também define as redes que permitem que os serviços comuniquem entre si e os volumes utilizados para dados persistentes.

Com este único ficheiro, pode gerir toda a sua stack de aplicações com comandos simples:

  • docker compose up inicia e executa toda a sua aplicação, incluindo todos os containers, redes e volumes especificados.
  • docker compose down para e remove todos os contentores, redes e volumes criados pela sua aplicação.

É mais útil para gerir aplicações que requerem múltiplos componentes, como um site que necessita de um servidor web (como o Nginx), um backend de aplicação (como o WordPress) e uma base de dados (como o MySQL).

2. Como instalo o Docker Compose no Ubuntu?

O método recomendado é instalar o Docker Compose como um plugin para a CLI do Docker. Isto é feito instalando o pacote docker-compose-plugin a partir do repositório apt oficial da Docker.

  1. Primeiro, certifique-se de que seguiu a documentação oficial do Docker para configurar o repositório apt do Docker no seu sistema Ubuntu.

  2. Atualize a lista de pacotes:

    sudo apt update
  3. Instale o plugin Docker Compose:

    sudo apt install docker-compose-plugin
  4. Verifique a instalação verificando a versão. O comando usa um espaço, não um hífen.

    docker compose version

3. Como posso atualizar o Docker Compose para a versão mais recente?

Como o Docker Compose (v2) está instalado como um pacote do sistema usando apt, pode atualizá-lo utilizando o processo padrão de atualização de software do Ubuntu.

  1. Atualize o índice de pacotes local:

    sudo apt update
  2. Execute uma atualização de todo o sistema, que incluirá o plugin Compose:

    sudo apt upgrade

    Alternativamente, se apenas quiser atualizar o plugin em si, pode executar:

    sudo apt install --only-upgrade docker-compose-plugin

4. O Docker Compose pode ser utilizado em ambientes de produção?

Sim, o Docker Compose é frequentemente usado em produção, especialmente para aplicações que correm num único host.

Fornece uma forma simples de definir, implementar e gerir o ciclo de vida dos serviços, redes e volumes da sua aplicação. Para uma implementação num único servidor, é uma solução muito eficaz e fácil de gerir.

Para cenários mais complexos que exigem a coordenação de containers em múltiplos hosts (um cluster), outras ferramentas são mais comuns. Estas incluem o Docker Swarm (que utiliza uma sintaxe de ficheiro Compose semelhante) e o Kubernetes (que é o padrão da indústria para a orquestração de containers em grande escala).

5. Qual é a diferença entre Docker e Docker Compose?

Esta tabela descreve as principais diferenças entre a CLI do Docker e a CLI do Docker Compose.

Funcionalidadedocker (Motor Docker)docker compose (Plugin Compose)
ÂmbitoGerencia objetos individuais do Docker.Gerencia uma aplicação completa com vários contentores como uma única unidade.
Uso PrincipalConstrução de imagens (docker build), execução de contêineres individuais (docker run), gestão de contêineres (docker ps), imagens, volumes e redes.Orquestrando múltiplos serviços definidos num ficheiro docker-compose.yml.
ComandosComandos de baixo nível focados em um único objeto. Exemplo: docker run -d -p 80:80 -v ./:/app nginxComandos de alto nível para toda a aplicação. Exemplo: docker compose up
AnalogiaUm bloco de construção (um único contentor).O plano e o gestor de construção de todo o edifício (a aplicação).

Em resumo, você usa docker para interagir com um único contêiner. Você usa docker compose para gerir toda a sua stack de aplicações (por exemplo, web, app, db) de uma só vez.

6. Como posso executar vários contêineres com o Docker Compose?

Pode executar vários containers definindo-os como serviços no seu ficheiro docker-compose.yml.

  1. Crie um ficheiro chamado docker-compose.yml.

  2. Dentro deste ficheiro, utilize a chave services: para definir cada contentor que pretende executar.

    Aqui está um exemplo prático que define e executa dois containers: um site WordPress e uma base de dados MySQL.

    services:
      db:
        # This is the first service (container)
        image: mysql:8.0
        environment:
          MYSQL_ROOT_PASSWORD: <^your_password_here<^>
          MYSQL_DATABASE: wordpress
        volumes:
          - db_data:/var/lib/mysql
    
      wordpress:
        # This is the second service (container)
        image: wordpress:latest
        ports:
          - "8001:80"
        environment:
          WORDPRESS_DB_HOST: db
          WORDPRESS_DB_PASSWORD: <^your_password_here<^>
        depends_on:
          - db
    
    volumes:
      db_data:
  3. docker-compose.yml

  4. Guarde o ficheiro e abra um terminal no mesmo diretório.

  5. Execute um único comando para iniciar ambos os contêineres:

    docker compose up -d

O Docker Compose irá ler o ficheiro, criar uma rede partilhada para os serviços, transferir as imagens mysql e wordpress, e iniciar um contentor para cada serviço.

7. Por que utilizar o Docker Compose para desenvolvimento?

O Docker Compose é uma ferramenta padrão para ambientes de desenvolvimento porque resolve vários problemas comuns.

  • Ambientes Consistentes: Garante que cada programador da equipa execute exatamente os mesmos serviços (base de dados, cache, servidor web) com as mesmas versões e configurações. Isto é definido no ficheiro docker-compose.yml, que é guardado no controlo de versões. Isto elimina o problema do “funciona na minha máquina”.

  • Simplicidade: Substitui scripts de configuração complexos e longos comandos docker run. Um programador só precisa executar docker compose up para iniciar toda a stack da aplicação e docker compose down para a parar.

  • Isolamento de Serviços: Os programadores podem trabalhar em vários projetos na mesma máquina sem conflitos de dependências. O Projeto A pode usar PostgreSQL 9.6 e o Projeto B pode usar PostgreSQL 14, uma vez que cada base de dados corre num contêiner isolado gerido pelo seu próprio ficheiro Compose.

  • Testes de Integração Fáceis: Como o Compose inicia todas as dependências de uma aplicação em conjunto, ele cria um ambiente local perfeito para executar testes de integração que verificam como os serviços interagem entre si.

Conclusão

Neste guia, instalou o Docker Compose e configurou uma aplicação completa com múltiplos contentores. Começou com um ficheiro básico docker-compose.yml para um servidor web Nginx e avançou para uma stack mais complexa e realista, envolvendo uma aplicação WordPress e uma base de dados MySQL. Aprendeu a gerir todo o ciclo de vida da aplicação, desde a construção e execução dos serviços até à sua paragem e remoção.

Agora está familiarizado com os conceitos-chave para gerir aplicações de forma eficaz, incluindo a escalabilidade de serviços, definições de rede personalizadas e a divisão da sua configuração em ficheiros modulares usando a diretiva include. Seguindo o guia de migração e os passos de resolução de problemas, também poderá resolver problemas comuns como conflitos de porta, erros de “Permissão negada” e erros de sintaxe YAML. As competências aqui abordadas permitir-lhe-ão construir ambientes de desenvolvimento consistentes e reprodutíveis e implementar aplicações de host único com confiança.

Para uma referência completa de todos os comandos docker compose disponíveis, consulte a documentação oficial.

Para mais tutoriais relacionados com Docker, consulte os seguintes artigos:

  • Como Instalar o Docker no Ubuntu – Guia Passo a Passo
  • Como Instalar o WordPress com Docker Compose

Obrigado por aprender com a comunidade Linux-Console.net.