Como usar o comando docker compose push para enviar imagens de serviço

DockerBeginner
Pratique Agora

Introdução

Neste laboratório, você aprenderá como usar o comando docker compose push para enviar (push) as imagens de serviço definidas em um arquivo docker-compose.yaml para um registro (registry). Você começará preparando um arquivo docker-compose.yaml com imagens de serviço e, em seguida, construirá essas imagens. Finalmente, você praticará o envio (push) dessas imagens de serviço para um registro, incluindo como lidar com possíveis falhas durante o processo de envio (push).

Prepare um arquivo docker-compose.yaml com imagens de serviço

Nesta etapa, você aprenderá como criar um arquivo docker-compose.yaml para definir e gerenciar aplicações Docker de múltiplos contêineres. Docker Compose é uma ferramenta que permite definir e executar aplicações Docker de múltiplos contêineres. Com o Compose, você usa um arquivo YAML para configurar os serviços da sua aplicação. Em seguida, com um único comando, você cria e inicia todos os serviços a partir da sua configuração.

Primeiro, navegue para o diretório do projeto:

cd ~/project

Agora, vamos criar um arquivo docker-compose.yaml usando o editor nano. Este arquivo definirá dois serviços: um serviço web e um serviço de banco de dados.

nano docker-compose.yaml

Cole o seguinte conteúdo no arquivo docker-compose.yaml:

version: "3.8"
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
  db:
    image: postgres:latest
    environment:
      POSTGRES_PASSWORD: mysecretpassword

Vamos detalhar este arquivo:

  • version: '3.8' especifica a versão do formato do arquivo Docker Compose.
  • services: define os diferentes serviços que compõem sua aplicação.
  • web: define um serviço chamado web.
  • image: nginx:latest especifica que o serviço web usará a imagem Docker nginx:latest. Se a imagem não estiver disponível localmente, o Docker a puxará do Docker Hub.
  • ports: mapeia a porta 80 na máquina host para a porta 80 no contêiner.
  • db: define um serviço chamado db.
  • image: postgres:latest especifica que o serviço db usará a imagem Docker postgres:latest.
  • environment: define variáveis de ambiente dentro do contêiner. Aqui, definimos a POSTGRES_PASSWORD para o banco de dados PostgreSQL.

Salve o arquivo pressionando Ctrl + X, depois Y e Enter.

Você pode visualizar o conteúdo do arquivo criado usando o comando cat:

cat docker-compose.yaml

Este comando exibirá o conteúdo do arquivo docker-compose.yaml que você acabou de criar, permitindo que você verifique seu conteúdo.

Construir as imagens de serviço

Na etapa anterior, você definiu seus serviços usando imagens Docker existentes no arquivo docker-compose.yaml. Nesta etapa, você aprenderá como construir imagens Docker personalizadas para seus serviços usando Dockerfiles e, em seguida, integrá-las ao seu arquivo docker-compose.yaml.

Primeiro, vamos criar um diretório simples para nosso serviço web e um Dockerfile dentro dele. Navegue para o diretório do projeto, se você ainda não estiver lá:

cd ~/project

Crie um diretório chamado web e navegue para ele:

mkdir web
cd web

Agora, crie um Dockerfile chamado Dockerfile dentro do diretório web usando o editor nano:

nano Dockerfile

Cole o seguinte conteúdo no Dockerfile:

FROM ubuntu:latest
RUN apt-get update && apt-get install -y nginx
COPY index.html /var/www/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Este Dockerfile faz o seguinte:

  • FROM ubuntu:latest: Começa a partir da imagem base Ubuntu mais recente.
  • RUN apt-get update && apt-get install -y nginx: Atualiza a lista de pacotes e instala o Nginx.
  • COPY index.html /var/www/html/: Copia um arquivo index.html (que criaremos em seguida) para o diretório webroot do Nginx.
  • EXPOSE 80: Expõe a porta 80 no contêiner.
  • CMD ["nginx", "-g", "daemon off;"]: Especifica o comando a ser executado quando o contêiner inicia, que é iniciar o Nginx em primeiro plano.

Salve o Dockerfile pressionando Ctrl + X, depois Y e Enter.

Agora, vamos criar o arquivo index.html que o Dockerfile copia. Permaneça no diretório ~/project/web e crie o arquivo:

nano index.html

Cole o seguinte conteúdo HTML simples em index.html:

<!doctype html>
<html>
  <head>
    <title>Hello from Docker!</title>
  </head>
  <body>
    <h1>Welcome to my Dockerized Nginx!</h1>
    <p>This page is served from a custom Docker image.</p>
  </body>
</html>

Salve o arquivo index.html pressionando Ctrl + X, depois Y e Enter.

Agora, navegue de volta para o diretório raiz do projeto onde seu arquivo docker-compose.yaml está localizado:

cd ~/project

Precisamos modificar o arquivo docker-compose.yaml para construir o serviço web a partir do Dockerfile que acabamos de criar, em vez de usar uma imagem pré-construída. Abra o arquivo docker-compose.yaml para edição:

nano docker-compose.yaml

Modifique a definição do serviço web para usar a instrução build em vez de image:

version: "3.8"
services:
  web:
    build: ./web
    ports:
      - "80:80"
  db:
    image: postgres:latest
    environment:
      POSTGRES_PASSWORD: mysecretpassword

Aqui, build: ./web diz ao Docker Compose para construir a imagem para o serviço web usando o Dockerfile localizado no diretório ./web em relação ao arquivo docker-compose.yaml.

Salve o arquivo docker-compose.yaml modificado pressionando Ctrl + X, depois Y e Enter.

Agora, você pode construir as imagens definidas em seu arquivo docker-compose.yaml usando o comando docker-compose build. Como o Docker Compose não está pré-instalado, você precisa instalá-lo primeiro.

sudo apt-get update
sudo apt-get install docker-compose-plugin -y

Após instalar o plugin Docker Compose, você pode usar o comando docker compose (observe o espaço em vez de um hífen em versões mais recentes).

docker compose build

Este comando lerá seu arquivo docker-compose.yaml e construirá a imagem para o serviço web com base no Dockerfile no diretório ./web. Ele também puxará a imagem postgres:latest para o serviço db se ela ainda não estiver presente. Você verá a saída indicando o processo de construção para a imagem web.

Após a conclusão da construção, você pode listar as imagens Docker em seu sistema para ver a imagem recém-construída.

docker images

Você deve ver uma imagem com um nome relacionado ao diretório do seu projeto e ao nome do serviço (por exemplo, project-web) e a imagem postgres.

Enviar as imagens de serviço para um registry

Na etapa anterior, você construiu uma imagem Docker personalizada para seu serviço web. Agora, você aprenderá como enviar essas imagens para um registro Docker. Um registro Docker é um sistema de armazenamento e distribuição para imagens Docker. O Docker Hub é um registro público, e você também pode executar registros privados. Enviar imagens para um registro permite que você as compartilhe com outras pessoas ou as implante em diferentes máquinas.

Antes de enviar, você normalmente precisa marcar suas imagens com o endereço do registro, seu nome de usuário e o nome da imagem. Para este laboratório, simularemos o envio para um registro local ou um registro onde a autenticação não é necessária, para simplificar. Em um cenário real, você faria login no registro usando docker login.

Primeiro, vamos listar as imagens que você tem para identificar a imagem que você construiu para o serviço web. Navegue para o diretório do projeto, se você ainda não estiver lá:

cd ~/project

Liste as imagens Docker:

docker images

Você deve ver uma imagem com um nome como project-web. O nome exato pode variar ligeiramente dependendo do nome do seu diretório do projeto.

Agora, vamos marcar a imagem project-web para que ela possa ser enviada para um registro. Usaremos um endereço de registro hipotético your-registry.example.com. Substitua your-registry.example.com pelo endereço real do registro se você estivesse enviando para um registro real. Para este exercício, usaremos localhost:5000 para simular um registro local.

docker tag project-web localhost:5000/my-web-app:latest

Este comando marca a imagem project-web com o nome localhost:5000/my-web-app:latest. localhost:5000 é o endereço do registro, my-web-app é o nome do repositório e latest é a tag.

Você pode verificar a nova tag listando as imagens novamente:

docker images

Você deve agora ver a imagem project-web listada com duas tags: a original e localhost:5000/my-web-app:latest.

Agora, vamos enviar a imagem marcada para o registro local simulado.

docker push localhost:5000/my-web-app:latest

Como estamos simulando um registro local que não está realmente em execução, este comando provavelmente falhará com um erro de conexão. Isso é esperado nesta etapa, pois estamos focando no próprio comando docker push. Na próxima etapa, exploraremos como lidar com essas falhas.

Em um cenário real com um registro em execução, este comando carregaria as camadas da imagem para o registro.

Enviar as imagens de serviço ignorando falhas

Na etapa anterior, você tentou enviar sua imagem de serviço web personalizada para um registro simulado, o que provavelmente falhou porque o registro não estava em execução. Em alguns cenários, você pode querer tentar enviar várias imagens e continuar mesmo que um dos envios falhe. Isso pode ser útil em scripts de automação ou ao enviar para vários registros.

O Docker Compose fornece uma maneira de enviar todas as imagens de serviço definidas em seu arquivo docker-compose.yaml. Por padrão, se o envio de uma imagem falhar, todo o comando será interrompido. No entanto, você pode usar a flag --ignore-pull-failures com o comando docker compose push. Embora o nome sugira ignorar falhas de pull, no contexto de docker compose push, ele também afeta como as falhas de push são tratadas, dependendo da versão e do contexto do Compose. Uma maneira mais direta de lidar com falhas de push individuais em um script é iterar pelos serviços e tentar enviar cada um, tratando os erros para cada envio.

Vamos primeiro listar os serviços definidos em seu arquivo docker-compose.yaml. Navegue para o diretório do projeto, se você ainda não estiver lá:

cd ~/project

Você pode ver os nomes dos serviços (web e db) em seu arquivo docker-compose.yaml.

cat docker-compose.yaml

Agora, vamos tentar enviar todos os serviços definidos no arquivo docker-compose.yaml. Lembre-se de que o serviço db usa a imagem postgres:latest do Docker Hub, e o serviço web é construído localmente e marcado para localhost:5000.

docker compose push

Este comando tentará enviar a imagem web (para localhost:5000) e a imagem postgres (para o Docker Hub). O envio para localhost:5000 provavelmente falhará como antes. O envio para o Docker Hub para postgres pode ter sucesso se você tiver acesso à internet e a imagem ainda não estiver presente no registro para o qual você está enviando (embora normalmente você não enviaria imagens oficiais como postgres para seu próprio registro). O comando provavelmente relatará uma falha devido à incapacidade de se conectar a localhost:5000.

Para demonstrar a ignorância de falhas, vamos considerar um cenário em que você pode ter vários serviços e deseja enviá-los independentemente, continuando mesmo que um falhe. Embora docker compose push não tenha uma flag direta "ignorar falhas de push" para todos os serviços de uma vez da mesma forma que lida com falhas de pull, você pode obter um comportamento semelhante em um script iterando pelos serviços e tentando enviar cada um.

Por exemplo, você pode escrever um script que tenta enviar cada serviço individualmente e continua em caso de erro. No entanto, para o propósito deste laboratório e para demonstrar o conceito de lidar com possíveis falhas durante as operações de envio, focaremos no resultado do comando docker compose push, que destacará a falha quando o registro de destino estiver inacessível.

A principal conclusão aqui é entender que enviar imagens é uma etapa crítica no pipeline de CI/CD, e lidar com possíveis falhas (como problemas de rede ou problemas de autenticação) é importante. Embora docker compose push possa parar no primeiro erro por padrão, em scripts ou cenários mais avançados, você implementaria a lógica para lidar com os resultados de envio individuais.

Vamos confirmar que o comando docker compose push foi executado.

grep "docker compose push" ~/.zsh_history

Isso confirma que você tentou enviar as imagens usando o Docker Compose. A saída do próprio comando mostraria a falha para o envio do serviço web.

Resumo

Neste laboratório, você aprendeu como preparar um arquivo docker-compose.yaml para definir aplicações Docker de múltiplos contêineres, especificamente configurando serviços como um servidor web (nginx) e um banco de dados (PostgreSQL) com suas respectivas imagens, portas e variáveis de ambiente. Em seguida, você praticou a construção dessas imagens de serviço com base nas definições no arquivo docker-compose.yaml.

Além disso, você explorou como enviar essas imagens de serviço construídas para um registro Docker usando o comando docker compose push. Você também aprendeu como lidar com possíveis falhas durante o processo de envio usando a flag --ignore-push-failures, permitindo que a operação de envio continue mesmo que algumas imagens não consigam ser carregadas.