Como funcionam os contêineres do Docker
Anteriormente, você descobriu que o contêiner se torna a unidade que você usará para distribuir seus aplicativos. Você também aprendeu que o contêiner está em um formato padronizado utilizado pelas equipes de desenvolvimento e operação.
No seu exemplo, você está desenvolvendo um portal de rastreamento de pedidos que os vários pontos de venda da sua empresa usarão. Com a imagem do Docker criada, sua equipe de operações agora é responsável por implantar, distribuir atualizações e gerenciar o portal de rastreamento de pedidos.
Na unidade anterior, você viu como é criada uma imagem do Docker. Aqui, você examinará brevemente o ciclo de vida de um contêiner do Docker e como gerenciar contêineres. Você também examinará como configurar o armazenamento de dados e as opções de rede de seus contêineres.
Como gerenciar contêineres do Docker
Um contêiner do Docker tem um ciclo de vida que você pode utilizar para gerenciar e rastrear o estado do contêiner.
Para colocar um contêiner em estado de execução, utilize o comando run. Também é possível reiniciar um contêiner que já esteja em execução. Ao reiniciar um contêiner, ele recebe um sinal de encerramento para habilitar qualquer processo em execução a ser desligado suavemente antes do encerramento do kernel do contêiner.
Um contêiner será considerado em estado de execução até que seja pausado, interrompido ou encerrado. Um contêiner, entretanto, também pode sair do estado de execução por si mesmo. Um contêiner pode ser encerrado de modo automático quando o processo em execução for concluído ou caso ele entre em um estado de falha.
Para pausar um contêiner em execução, utilize o comando pause. Esse comando suspende todos os processos no contêiner.
Para interromper um contêiner em execução, utilize o comando stop. O comando stop permite desligar o processo de trabalho normalmente, enviando um sinal de encerramento à ele. O kernel do contêiner será encerrado após o desligamento do processo.
Se você precisar encerrar o contêiner, utilize o comando kill para enviar um sinal de encerramento. O kernel do contêiner captura o sinal de encerramento, mas o processo em execução não. Esse comando encerra de maneira forçada o processo de trabalho no contêiner.
Por fim, para remover os contêineres que estejam em um estado interrompido, utilize o comando remove. Após remover um contêiner, todos os dados armazenados nele serão destruídos.
Como exibir os contêineres disponíveis
Execute o comando docker ps
para listar contêineres em execução. Passe o argumento -a
para conferir contêineres em todos os estados.
Aqui está um exemplo:
docker ps -a
Aqui está a saída desse comando:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d93d40cc1ce9 tmp-ubuntu:latest "dotnet website.dll …" 6 seconds ago Up 5 seconds 8080/tcp happy_wilbur
33a6cf71f7c1 tmp-ubuntu:latest "dotnet website.dll …" 2 hours ago Exited (0) 9 seconds ago adoring_borg
Existem três itens que devem ser analisados na saída anterior:
O nome da imagem listado na coluna IMAGEM; neste exemplo, tmp-ubuntu: latest. Observe como é permitido criar mais de um contêiner da mesma imagem. Esse é um poderoso recurso de gerenciamento que você pode utilizar para habilitar a colocação em escala em suas soluções.
O status do contêiner listado na coluna STATUS. Neste exemplo, você tem um contêiner em execução e um contêiner encerrado. O status do contêiner é geralmente o primeiro indicador da integridade do contêiner.
O nome do contêiner listado na coluna NOMES. Além da ID do contêiner na primeira coluna, os contêineres também recebem um nome. Neste exemplo, você não forneceu de modo explícito um nome para cada contêiner. Como resultado, o Docker deu um nome aleatório para o contêiner. Para dar um nome explícito a um contêiner usando o sinalizador
--name
, utilize o comandorun
.
Por que os contêineres recebem um nome?
Esse recurso permite executar várias instâncias de contêiner da mesma imagem. Os nomes dos contêineres são exclusivos, o que significa que, se você especificar um nome, não poderá reutilizá-lo para criar um novo contêiner. A única maneira de reutilizar um nome específico é remover o contêiner anterior.
Como executar um contêiner
Para iniciar um contêiner, utilize o comando docker run
. Somente será necessário especificar a imagem a ser executada usando seus respectivos nomes ou IDs para iniciar o contêiner por meio dela. Um contêiner iniciado desse modo fornecerá uma experiência interativa.
Nesse momento, adicione o sinalizador -d
para executar o contêiner com nosso site em segundo plano.
docker run -d tmp-ubuntu
O comando, nesse caso, retorna apenas a ID do novo contêiner.
Após você especificar uma imagem a ser executada, o Docker encontra a imagem, carrega o contêiner a partir da imagem e executa o comando especificado como ponto de entrada. É nesse ponto que o contêiner fica disponível para gerenciamento.
Como pausar um contêiner
Execute o comando docker pause
a fim de pausar um contêiner. Aqui está um exemplo:
docker pause happy_wilbur
A pausa de um contêiner suspende todos os processos. Esse comando permitirá que o contêiner continue executando os processos em uma fase posterior. O comando docker unpause
cancela a suspensão de todos os processos nos contêineres especificados.
Como reiniciar um contêiner
Execute o comando docker restart
para reiniciar contêineres. Aqui está um exemplo:
docker restart happy_wilbur
O contêiner recebe um comando parar seguido de um comando iniciar. Se o contêiner não responder ao comando stop, um sinal de encerramento será enviado.
Como interromper um contêiner
Execute o comando docker stop
para interromper um contêiner em execução. Aqui está um exemplo:
docker stop happy_wilbur
O comando parar envia um sinal de encerramento para o contêiner e para os processos em execução no contêiner.
Como remover um contêiner
Execute o comando docker rm
para remover um contêiner. Aqui está um exemplo:
docker rm happy_wilbur
Depois de remover o contêiner, todos os dados presentes nele serão destruídos. É essencial sempre considerar os contêineres como temporários ao pensar no armazenamento de dados.
Configuração de armazenamento de contêiner do Docker
Como descrevemos anteriormente, sempre considere os contêineres como temporários quando o aplicativo em um contêiner precisar armazenar dados.
Vamos supor que o seu portal de rastreamento crie um arquivo de log em uma subpasta na raiz do aplicativo, ou seja, diretamente no sistema de arquivos do contêiner. Quando o aplicativo gravar dados no arquivo de log, o sistema os gravará na camada de contêiner gravável.
Embora essa abordagem funcione, infelizmente ela tem várias desvantagens.
O armazenamento do contêiner é temporário.
O arquivo de log não persistirá entre instâncias de contêiner. Por exemplo, vamos supor que você interrompa e remova o contêiner. Ao iniciar uma nova instância de contêiner, a nova instância se baseia na imagem especificada, e todos os dados anteriores estarão ausentes. Lembre-se de que todos os dados de um contêiner serão destruídos com ele durante a remoção.
O armazenamento em contêiner está acoplado ao computador host subjacente.
É difícil acessar ou mover o arquivo de log do contêiner, pois o contêiner está acoplado ao computador host subjacente. Você tem que se conectar à instância do contêiner para acessar o arquivo.
As unidades de armazenamento do contêiner são menos eficientes.
Os contêineres implementam um driver de armazenamento para permitir que seus aplicativos gravem dados. Esse driver apresenta uma abstração extra para se comunicar com o kernel do SO do host e tem desempenho menor que a gravação direta em um sistema de arquivos do host.
Os contêineres podem fazer uso de duas opções para persistir os dados. A primeira opção é fazer uso de volumes e a segunda são montagens de associação.
O que é um volume?
Um volume é armazenado no sistema de arquivos do host em uma localização de pasta específica. Escolha uma pasta em que você saiba que os dados não serão modificados por processos que não sejam do Docker.
O Docker criará e gerenciará o novo volume executando o comando docker volume create
. Esse comando pode fazer parte da definição do nosso Dockerfile, o que significa que você pode criar volumes como parte do processo de criação do contêiner. O Docker criará o volume, caso ele não exista, quando você tentar montar o volume em um contêiner pela primeira vez.
Os volumes são armazenados em diretórios no sistema de arquivos do host. O Docker montará e gerenciará os volumes no contêiner. Após a montagem, esses volumes serão isolados do computador host.
Vários contêineres podem usar simultaneamente os mesmos volumes. Os volumes também não são removidos automaticamente quando um contêiner para de usar o volume.
Neste exemplo, você pode criar um diretório no host do contêiner e montar esse volume no contêiner quando criar o contêiner do portal de rastreamento. Quando o portal de acompanhamento registrar dados, será possível acessar essas informações por meio do sistema de arquivos do host de contêiner. Você terá acesso a esse arquivo de log, mesmo se o contêiner for removido.
O Docker também fornece uma forma para empresas de terceiros criarem complementos para que sejam usados como volumes. Por exemplo, o Armazenamento do Azure fornece um plug-in para montar o Armazenamento do Azure como volumes em contêineres do Docker.
O que é uma montagem de associação?
Uma montagem de associação é conceitualmente igual a um volume; entretanto, em vez de utilizar uma pasta específica, você pode montar qualquer arquivo ou pasta no host. Você também espera que o host possa alterar o conteúdo dessas montagens. Assim como os volumes, a montagem de associação será criada se você a montar e ela ainda não existir no host.
As montagens de associação têm funcionalidade limitada comparado aos volumes e, embora tenham um melhor desempenho, elas dependem do host ter uma estrutura de pastas específica em vigor.
Os volumes são considerados a estratégia preferida de armazenamento de dados a ser utilizada com contêineres.
Para os contêineres do Windows, há outra opção disponível: você pode montar um caminho SMB como um volume e apresentá-lo a contêineres. Isso permite que contêineres em hosts diferentes usem o mesmo armazenamento persistente.
Configuração de rede de contêiner do Docker
A configuração de rede padrão do Docker permite isolar os contêineres no host do Docker. Esse recurso permite criar e configurar aplicativos que possam se comunicar com segurança entre si.
O Docker fornece configurações de rede diferentes para o Linux e o Windows.
No Linux, existem seis opções de rede pré-configuradas:
- Ponte
- Host
- Sobreposição
- IPvLan
- MACvLan
- Nenhum
No Windows, existem seis opções de rede pré-configuradas:
- NAT (conversão de endereços de rede)
- Transparente
- Sobreposição
- L2Bridge
- L2Tunnel
- Nenhum
Você pode escolher qual dessas configurações de rede aplicar ao seu contêiner, dependendo dos requisitos de rede dele.
O que é a rede de ponte?
A rede de ponte é a configuração padrão aplicada aos contêineres quando iniciada sem especificar nenhuma outra configuração de rede. Essa rede é uma rede interna e privada utilizada pelo contêiner e isola a rede do contêiner da rede do host do Docker.
Cada contêiner na ponte de rede é atribuído a um endereço IP e a uma máscara de sub-rede, com o nome do host padrão para o nome do contêiner. Os contêineres conectados à ponte de rede padrão têm permissão para acessar outros contêineres conectados à ponte pelo endereço IP. A rede de ponte não permite a comunicação entre contêineres usando nomes do host.
Por padrão, o Docker não publica nenhuma porta de contêiner. Use o sinalizador --publish
da porta do Docker para habilitar o mapeamento de portas entre as portas do contêiner e as portas host do Docker.
O sinalizador de publicação configura efetivamente uma regra de firewall que mapeia as portas.
Neste exemplo, o portal de acompanhamento estará acessível para clientes que navegam usando a porta 80. Será necessário mapear a porta 80 do contêiner para obter uma porta disponível no host. Você deve ter a porta 8080 aberta no host, o que o habilita a definir o sinalizador desta forma:
--publish 8080:80
Qualquer cliente que navega até o IP do host do Docker e a porta 8080 pode acessar o portal de acompanhamento.
Além das configurações específicas do Linux, a rede NAT nos hosts do Windows tem a mesma função de uma ponte de rede. Além disso, a NAT é a rede padrão no Windows, e todos os contêineres se conectarão a ela, a menos que seja especificado de outra forma.
O que é a rede do host?
A rede do host permite executar o contêiner diretamente nela. Essa configuração remove efetivamente o isolamento entre o host e o contêiner em um nível de rede.
Neste exemplo, vamos supor que você decida alterar a configuração de rede para a opção de rede do host. O portal de acompanhamento ainda poderá ser acessado usando o IP do host. Agora você pode utilizar a conhecida porta 80 em vez de uma porta mapeada.
Lembre-se de que o contêiner pode utilizar apenas portas que o host ainda não esteja usando.
No Windows, a rede do host não está disponível. Nos hosts Windows, não existe a opção de compartilhar o mesmo endereço IP (pilha de rede) entre o host e o contêiner. A rede NAT funciona como uma ponte de rede, e a opção Sobreposição fornece um endereço IP ao contêiner da mesma rede que o host, mas não o mesmo endereço IP.
Sobreposição e outras opções de rede
Para cenários mais avançados, o Linux e o Windows fornecem outras opções de rede. Por exemplo, a opção de sobreposição cria uma alternância virtual da rede do host, de modo que os contêineres nessa rede podem obter endereços IP de servidores DHCP ou operar com endereços IP desse segmento de rede. Além disso, o Docker permite que fornecedores de terceiros criem plug-ins de rede.
O que é a rede nenhuma?
Para desabilitar a rede para contêineres, utilize a opção de rede none. Isso pode ser útil se você tiver um aplicativo que não utiliza a rede ou se desejar apenas validar se um aplicativo é executado conforme esperado em um contêiner.
Considerações sobre o sistema operacional
Lembre-se de que existem diferenças entre os sistemas operacionais de desktop para as opções de configuração de rede do Docker. Por exemplo, a interface de rede Docker0 não está disponível no macOS quando se usa a rede em ponte, e o uso da configuração de rede de host não tem suporte para desktops Windows e macOS.
Essas diferenças podem afetar a maneira como os desenvolvedores configuram o fluxo de trabalho para gerenciar o desenvolvimento de contêineres. Além disso, os orquestradores de contêineres também podem fornecer outras configurações de rede além da configuração do Docker.