Componentes do Docker

Olá, e obrigado pela sua visita. Felizmente, o primeiro post alcançou um público bem amplo e muita gente me perguntou/pediu quando a série continuaria. Pois bem, aqui está o segundo capítulo da nossa jornada pelo maravilhoso mundo do Docker.  Neste capítulo 2, vamos ver como o produto funciona em ambientes que não são Linux e a relação entre seus componentes.

Você já sabe que o Docker pode trabalhar com ou sem soluções de virtualização de servidores, como VMware ESXi uo Microsoft Hyper-V.  A evidência maior disso é que você mesmo pode baixar e usar no seu computador de casa (veremos isso mais adiante).  Vamos aos demais componentes.

*** Como este post é um pouco extenso, você pode ter uma melhor experiência de leitura a partir do computador. ***

 

Docker Engine

O primeiro post citou o mais importante, chamado de Docker Engine. Ele é responsável por todas as tarefas de gerenciamento de memória, acesso a disco, comunicação com rede, compartilhamento de kernel e de isolamento do container dentro do host onde ele está sendo executado. O Engine, entretanto, é composto por dois softwares separados, que nós poderíamos chamar de “Docker Client” e o “Docker Server”.

Figura 1: logo do Docker Engine

Como assim “poderíamos”? A separação entre cliente e servidor é apenas para fins didáticos, pois os softwares fazem parte da mesma porção (Docker Engine).  O servidor é a parte que fica carregada em memória na forma de um daemon (em sistemas Linux) ou serviço (em Windows ou macOS). O cliente é implementado pelo comando “docker”, que permite realizar todas as operações de criação, ativação, desativação e remoção dos containers, imagens e outros artefatos do ambiente.  Assim, o cliente (comando “docker”) conversa com o daemon/serviço (dockerd) através de uma API REST que fica escutando na porta 2376 (por padrão). A porta pode ser alterada, caso necessário.

Então, se o container é proveniente de uma imagem Linux, como será possível rodar no Windows, que possui um kernel completamente diferente?

A próxima figura ilustra sucintamente como funciona a arquitetura de comunicação entre a parte cliente e a parte servidora do Docker Engine.  Observe alguns nomes de itens que iremos explorar mais adiante.

Figura 2: Docker Engine – crédito da imagem: documentação oficial

Como você já sabe, o Docker Engine expõe o kernel do sistema operacional do host onde ele está sendo executado para que diversos containers possam funcionar. Então, se o container é proveniente de uma imagem Linux, como será possível rodar no Windows, que possui um kernel completamente diferente? Apresento a você o Docker Machine!

 

Docker Machine

Desde as primeiras versões do Docker, e até as mais modernas, este software continua disponível e ainda é bastante usado. O papel do Docker Machine é fazer a “mágica” que citei no post anterior de permitir a execução de um container de um sistema operacional em outro sistema operacional. Ele também faz parte do Docker Toolbox (atualmente obsoleto). Ok, mas, como funciona?

Figura 3: logo do Docker Machine

Simples. O Docker Machine usa algum virtualizador de nível 2 (veja o post anterior caso não saiba/lembre do que se trata) para executar uma máquina virtual Linux. Cada virtualizador é implementado através de um driver. O virtualizador padrão é o Virtualbox, mas também pode ser usado o Hyper-V, xhyve ou Parallels. O Virtualbox é escolhido como padrão, até porque está disponível para os três sistemas operacionais (Windows, Linux e macOS). O processo funciona mais ou menos assim:

  1. Baixe e instale o virtualizador de sua escolha no host;
  2. Baixa e instale o Docker Machine no host;
  3. Com o Docker Machine, crie uma máquina virtual simples, com um disco rígido pequeno (algo em torno de 5 GB);
  4. Em seguida, inicie essa máquina virtual a partir do Docker Machine;
  5. Comece a usar o Docker Engine.

A interação entre o Docker Cliente e Docker Daemon é controlada através de variáveis de ambiente.

Ao executar o passo 3 acima, o Docker Machine cria uma VM Linux de tamanho suficiente apenas para permitir expor o kernel da mesma aos containers Linux que você criará posteriormente. Esta VM também roda o Docker Daemon (porção servidora do Docker Engine), bem como a API REST. O nome do projeto que deu origem a essa VM é boot2docker. Após isso, você precisa iniciar a VM para que o kernel dela fique acessível.

O ambiente está quase preparado para o uso do cliente Docker (o comando “docker”). Você só precisa informar a ele que é preciso se conectar com a VM do Docker Machine, em vez de tentar o Docker Daemon no próprio computador. Isso é feito através de variáveis de ambiente. Veja como elas estão no meu computador, por exemplo:

DOCKER_TLS_VERIFY="1"
DOCKER_HOST="tcp://192.168.99.100:2376"
DOCKER_CERT_PATH="/Users/mauricio/.docker/machine/machines/kernel-docker"
DOCKER_MACHINE_NAME="kernel-docker"

A primeira variável (DOCKER_TLS_VERIFY) informa que será usado o protocolo TLS para comunicação entre o comado “docker” e a VM contendo o Docker Daemon. O certificado digital está localizado no diretório apontado pela terceira variável (DOCKER_CERT_PATH). Na verdade, todos os arquivos da VM estão no mesmo diretório (definições e disco virtual). A URL que aparece na segunda variável (DOCKER_HOST) corresponde ao endereço IP obtido pela VM dinamicamente através do serviço de DHCP do Virtualbox e também a porta padrão de comunicação. Por fim, a quarta variável (DOCKER_MACHINE_NAME) informa o nome da VM criada com o Docker Machine.

A figura abaixo apresenta de forma visual o processo de comunicação entre o cliente/comando docker e o Docker Machine:

Figura 4: funcionamento do Docker Machine – crédito da imagem: documentação oficial

Se você estiver acopanhando bem o artigo, vai lembrar que eu citei, logo no começo da explicação do Docker Machine que o Docker Toolbox está obsoleto. Esta suíte de ferramentas continha:  Docker Client, Docker Compose, Docker Machine e Kitematic. Veremos o Compose logo abaixo.  O Kitematic é uma interface gráfica para interagir com o comando docker e facilitar as tarefas de gerenciamento de containers.

O Docker for Windows inviabiliza o uso do Virtualbox.

O Docker Toolbox ainda precisa ser usado em hosts que não possuam os requisitos para suportar os novos substitutos:  Docker for Mac e Docker for Windows. Com a evolução dos sistemas operacionais Windows e macOS, incluindo suas capacidades de virtualizar outros sistemas operacionais, o Docker Machine basicamente perdeu sua utilidade.  Assim, em vez de empregar este componente (que é mais uma porção de software) e um virtualizador de terceiros (como o Virtualbox), faz mais sentido usar os próprios recursos do sistema operacional host.

No caso do Windows, o Docker faz uso do Hyper-V.  É importante observar que a ativação desta plataforma impossibilita o uso do Virtualbox. Isto é avisado pelo Docker for Windows no momento de instalação. Assim, se você possui outras máquinas virtuais funcionando neste programa, pondere o emprego do Docker for Windows. Você ainda pode usar o Docker Toolbox com o Docker Machine. Ou, pode começar a usar o Hyper-V para suas máquinas virtuais. Obviamente, isso requerirá conversão.

O macOS também possui um virtualizador tipo 2. Trata-se do xhyve. Este virtualizador é proveniente do bhyve, código originalmente criado para funcionar no FreeBSD. Isso se deve ao simples fato do próprio macOS (também conhecido pelo codinome Darwin) ser originado do FreeBSD. O código-fonte do kernel é disponibilizado publicamente pela Apple aqui. Assim, nada mais justo/fácil portar um código de virtualização já construído na própria referência, concorda? 😉

 

Docker Compose

E então chegamos ao Docker o Compose.  Este componente faz exatamente o que o nome indica: compõe um ambiente Docker. O papel dele é ler um arquivo texto com diversas definições, interpretá-las e construir um ambiente com containers de acordo como indicado. O Compose executa todas as tarefas assinaladas no arquivo texto, baixando imagens, construindo containers, criando redes, atribuindo volumes, entre outras coisas. Caso alguma tarefa se encontre no cache, ele será usado (mais disto num próximo post). A figura abaixo é indicativa do trabalho dele.

Figura 5: logo do Docker Compose

Este arquivo, por padrão, se chama “docker-compose.yml”, o que torna óbvio que seu formato precisa seguir a descrição YAML (YAML Ain’t Markup Language). De uma forma geral, o arquivo é organizado assim:

version: 'versão'
services:
  <nome serviço 1>:
      image: <nome da imagem 1>
      ports:
      - <portas a serem expostas>
      networks:
      <redes usadas pelo serviço 1>
     build: <diretório onde está o Dockerfile 1>
.
.
.
  <nome serviço N>:
      image: <nome da imagem N>
      ports:
      - <portas a serem expostas>
      networks:
      <redes usadas pelo serviço N>
     build: <diretório onde está o Dockerfile N>
volumes:
   - <diretório no container>:<diretório no host>

A versão comumente usada é a 3.  Os serviços correspondem a diversos tipos de containers que existirão e que trabalharão de forma organizada, frequentemente comunicando-se uns com os outros.  Por exemplo, numa aplicação web de três camadas (servidor web, servidor de aplicação e servidor de banco de dados), cada um dos servidores poderia ser representado por um serviço, que corresponderia a um ou mais containers. Cada serviço pode ter uma definição de réplicas. Assim, seria facilmente possível aumentar a escalabilidade individual de cada parte (aumentar a quantidade de containers para o servidor web, ou eliminar containers desnecessários no servidor de aplicação, para citar alguns exemplos).

Cada serviço descrito no docker-compose.yml pode ter uma definição de réplicas.

Dentro das definições dos serviços, vemos alguns dos parâmetros possíveis de se empregar. O “image” indica de qual imagem será instanciado. Esta imagem deve estar localmente presente no host. Caso não esteja, será baixada automaticamente de algum Docker Registry (logo em seguida). Nenhum container funciona sem sua respectiva imagem. O “ports” indica que portas deste container precisam ser acessíveis externamente. Por exemplo: num servidor web, a porta 80 (ou 443) precisa ser exposta para permitir o acesso.

A porção “networks” indica que redes serão usadas pelo container. Num próximo post, veremos como funciona a arquitetura de redes no Docker. O “build” aponta o diretório onde se encontra o “Dockerfile”, que se trata de um arquivo responsável por dizer como construir um container do zero.

Um instante! O docker-compose.yml serve para construir containers, certo? Então, pra que preciso do “Dockerfile”? Calma! O “Dockerfile” permite a construção de um único container seguindo as regras determinadas. Por sua vez, o “docker-compose.yml” possibilita a criação de serviços, cada um podendo ser constituído por um ou vários containers diferentes. Lembra as réplicas mais acima? Veremos mais sobre o Dockerfile num próximo post.

Por fim, a seção “volumes” indica que diretórios do sistema operacional host serão apresentados ao container/serviço para que ele possa ter acesso de leitura e/ou gravação. Como você já sabe, containers são elementos efêmeros que perdem seu armazenamento local tão logo sejam eliminados. Assim, como seria possível manter uma aplicação que precisa gravar num banco de dados? Com volumes! Assim, você mapeia um diretório do seu host onde a base de dados está localizada, e ela será atualizada e permanecerá íntegra, independente de quantos containers estejam em uso.

 

Docker Registry

Enfim, chegamos ao último componente deste post. Cansado? 🙂 Tenha paciência; estamos quase no final. O Docker Registry nada mais é que um repositório de imagens para containers. Imagens, como você já sabe, são sistemas operacionais customizados e otimizados para possuir apenas os recursos suficientes para instanciar containers respectivos.

Figura 6: logo do Docker Registry

Se você está começando a trabalhar com Docker e o mundo dos containers, naturalmente não possui nenhum repositório local. Assim, você precisará recorrer ao primeiro repositório que foi criado (o Docker Hub). Por muito tempo, ele foi o único disponível. Mas a Docker Inc., a empresa por trás de toda esta maravilha, criou um outro repositório de caráter mais comercial, para permitir o uso tanto por empresas parceiras que queiram desenvolver softwares auxiliares para o Docker, quanto para usuários que desejem pagar para ter acesso a suporte, bem como área personalizada. Disto nasceu o Docker Store.

Você pode começar usando qualquer um dos dois e depois, criar seu próprio Registry local. O processo de instalação e configuração de um Registry é documentado aqui (em Inglês). O Docker Hub é usado para armazenar as imagens criadas pela comunidade, empresas e por você mesmo (ou sua equipe). Para que você possa enviar suas imagens, é preciso criar uma conta e fazer login (via comando “docker”) no Docker Hub. Atenção para um detalhe: com a versão gratuita do Docker seu repositório é público; isto só pode ser alterado quando você paga pelo serviço, adquirindo a versão Enterprise.

A figura mostra uma visão geral da comunicação entre o Docker Engine e o Docker Registry (seja ele o Hub, o Store ou o seu local).

Figura 7: comunicação com o Docker Registry – crédito da imagem: O’Reilly

Observe que o Docker client conversa com o Docker daemon. Este, por sua vez, conversa tanto com o Host OS (como já explicado no primeiro post), como também com o Registry, para executar as tarefas indicadas no parágrafo anterior.

Ufa! E isto é tudo, pessoal. Ficou alguma dúvida? Gostaria de comentar algo que achou interessante? Deixe seu registro no formulário abaixo. Nós nos encontramos no próximo capítulo da nossa série. Até lá! 🙂

Compartilhe:

Maurício Harley

Olá! Meu nome é Maurício Harley. Tenho 30 anos de experiência em Tecnologia da Informação. Durante minha carreira, trabalhei em setores diversos, como suporte a usuário final, manutenção de hardware, instalação e suporte a redes de computadores, programação, projetos avançados em Data Center, Cloud Computing, Cyber Security e Redes, incluindo Service Providers.

2 comentários

José Carlos · 2019-05-01 às 12:25

Boa mestre. Seguinte, fiquei curioso: se uso um Docker gratuito, eu tenho como escolher se deixo os meus templates no host, ou se permito o compartilhamento com o reposítório público deles? Fiquei com esta dúvida, pois você menciona que ele fica exposto, quando uso o free, mas não mencionou como faço para bloquear este compartilhamento (vi o TLS na página em inglês, mas de qualquer forma eles teriam acesso aos meus templates), correto? Abs.

    Maurício Harley · 2019-05-01 às 17:07

    Olá, José Carlos!

    Para evitar que suas imagens fiquem expostas ao público, você pode escolher um dos planos no Docker Hub disponíveis aqui (https://hub.docker.com/pricing). Desde que escrevi o artigo, percebi que eles agora permitem ter um repositório privado gratuito para uso individual.

    Abraço!

Deixe um comentário

Avatar placeholder

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Translate

You cannot copy content of this page.