Executar um comando sem iniciar serviços vinculados
Nesta etapa, aprenderemos como executar um comando em um contêiner Docker que faz parte de uma aplicação multi-contêiner, sem iniciar os outros serviços vinculados. Isso é particularmente útil para executar migrações de banco de dados, scripts de configuração ou comandos de depuração em um serviço sem a necessidade de levantar toda a pilha da aplicação.
Embora o Docker Compose seja a ferramenta padrão para gerenciar aplicações multi-contêiner e tenha recursos para executar comandos únicos em serviços específicos, demonstraremos os conceitos subjacentes do Docker aqui. Como o Docker Compose não está pré-instalado neste ambiente, focaremos em usar o comando docker run com rede.
Vamos simular um cenário simples com dois contêineres: uma aplicação web e um banco de dados. Usaremos uma imagem ubuntu genérica para representar nossa aplicação web e uma imagem postgres para o banco de dados.
Primeiro, baixe a imagem postgres:
docker pull postgres:latest
Você deve ver a saída indicando que a imagem está sendo baixada.
Using default tag: latest
latest: Pulling from library/postgres
...
Status: Downloaded newer image for postgres:latest
docker.io/library/postgres:latest
Agora, vamos criar uma rede Docker para que nossos contêineres possam se comunicar entre si por nome.
docker network create my-app-network
Você deve ver o ID da rede impresso.
<network_id>
Em seguida, vamos executar o contêiner postgres e conectá-lo à nossa rede. Também definiremos uma senha para o usuário PostgreSQL.
docker run -d --network my-app-network --name my-database -e POSTGRES_PASSWORD=mypassword postgres
Você deve ver o ID do contêiner impresso, indicando que o contêiner do banco de dados está em execução em segundo plano.
<container_id>
Agora, imagine que nosso contêiner de "aplicação web" precisa executar um comando que interaja com o banco de dados, como um script de migração de banco de dados. Normalmente, se estivéssemos usando o Docker Compose, poderíamos executar um comando no serviço web e o Docker Compose cuidaria da configuração da rede e da vinculação.
Usando apenas docker run, se executássemos o contêiner da aplicação web e ele tentasse se conectar a my-database, ele normalmente precisaria estar na mesma rede.
Vamos executar um comando em um contêiner ubuntu conectado à mesma rede, simulando um comando que pode interagir com o banco de dados. Apenas tentaremos pingar o contêiner do banco de dados por seu nome (my-database).
docker run --network my-app-network ubuntu ping -c 4 my-database
Este comando irá:
- Criar um novo contêiner a partir da imagem
ubuntu.
- Conectá-lo ao
my-app-network.
- Executar o comando
ping -c 4 my-database dentro do contêiner.
Como o contêiner ubuntu está na mesma rede que o contêiner my-database, ele pode resolver o nome my-database para o endereço IP do contêiner do banco de dados e pingá-lo.
Você deve ver a saída mostrando as solicitações e respostas de ping:
PING my-database (172.18.0.2) 56(84) bytes of data.
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=1 ttl=64 time=0.050 ms
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=3 ttl=64 time=0.054 ms
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=4 ttl=64 time=0.054 ms
--- my-database ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3060ms
rtt min/avg/max/mdev = 0.050/0.053/0.054/0.001 ms
Isso demonstra que você pode executar um comando único em um contêiner e fazê-lo interagir com outros contêineres na mesma rede, sem a necessidade de iniciar o serviço padrão do contêiner que executa o comando (neste caso, o contêiner ubuntu não tem um "serviço" típico). A chave é conectar o contêiner que executa o comando à mesma rede dos serviços com os quais ele precisa interagir.
Finalmente, vamos limpar o contêiner do banco de dados em execução e a rede.
docker stop my-database
my-database
docker rm my-database
my-database
docker network rm my-app-network
my-app-network