8

Conhecendo o Docker

#Docker
Gabriel Faraday
Gabriel Faraday

Muito se fala hoje em dia sobre containers, ainda mais em cenários onde a nuvem tem se tornado cada vez mais protagonista no dia a dia dos projetos de software. Outra buzzword que já está virando mandatório é Docker.


Mas o que afinal são containers e o que é Docker e qual a relação entre eles?


O que é um container?


Imagine uma aplicação, seja ela .NET, Java, Node, etc. Além de bibliotecas, binários, etc, ela também utiliza recursos do sistema operacional para rodar.


Agora imagine que você pega tudo isso que envolve sua aplicação, dependências, bibliotecas, etc, e transforma em um pacotinho, como um binário, e nesse pacote tem tudo que você precisa para rodar sua aplicação. Assim é um container, ele “empacota” sua aplicação e tudo que ela precisa!


Porém, esse pacote não tem o kernel do sistema operacional. Então como será feito o uso de recursos que o kernel disponibiliza (gestão de memória, processamento, etc)? A mágica é que o container irá utilizar o kernel (e outros recursos físicos) da máquina hospedeira, que chamamos de host, que no fim das contas é a máquina física.


Então em uma única máquina física você pode ter inúmeros containers rodando e se comunicando com o kernel deste host, até que se atinja o limite de recursos disponibilizados no host, obviamente.


De forma bem resumida, um container “aloca” um diretório no host e simula o filesystem de um dado sistema operacional, de forma isolada, como se ele estivesse numa máquina só para ele. Então de dentro do container, é como se você estivesse numa máquina isolada.


E o tal de Docker?


Em 2008 o americano Solomon Hykes criou uma empresa chamada dotCloud. A proposta da empresa era ser um Plataform as a Service (PaaS) que rodasse qualquer linguagem de programação.


Deu-se então o início do desenvolvimento de toda a infraestrutura da empresa, e eles tiveram bastante contato com containers LXC, pois criaram várias ferramentas para criar e administrar esses containers.


Segundo o Wikipedia: “LXC (Linux Containers) é um método de virtualização em nível de sistema operacional para executar vários sistemas Linux isolados (contêineres) em um host de controle usando um único kernel Linux. O kernel Linux fornece a funcionalidade cgroups que permite a limitação e priorização de recursos (CPU, memória, bloco I/O, rede, etc.) sem a necessidade de iniciar qualquer máquina virtual, e também a funcionalidade de isolamento de namespace que permite o isolamento completo de um aplicativo visão do ambiente operacional, incluindo árvores de processo, rede, IDs de usuário e sistemas de arquivos montados.” - https://en.wikipedia.org/wiki/LXC


Em 2013, a dotCloud pegou toda essa bagagem que eles adquiriram sobre administração de containers e subiu um projeto para o github, tornando tudo open source e passando a receber ajuda da comunidade internacional (https://github.com/docker).


Com isso a empresa passou a se chamar Docker, que era basicamente o nome do produto que eles tinham iniciado. Em poucos meses, com tamanha ajuda que eles receberam, o Docker estava pronto para produção.


Logo de cara, grandes empresas adotaram o uso do Docker, empresas como Google, Netflix, Spotify, Facebook, etc. E essas empresas foram responsáveis neste início por disseminar e evangelizar o uso da ferramenta.


Então podemos concluir aqui que o conceito de containers surgiu antes mesmo do Docker, na verdade é um conceito que vem sendo evoluído desde antes do começo dos anos 2000. O Docker só ajudou a popularizar o termo devido à tamanha facilidade que ele entrega na administração de containers.


Mas vale ressaltar que hoje existem outras ferramentas similares ao Docker.


E como o docker funciona?


Docker usa uma arquitetura do tipo client-server. O client Docker roda na sua máquina e você interage com ele através da linha de comando. Quando isso acontece, o client envia esses comandos ao daemon Docker (que seria o server), chamado de dockerd.


O dockerd é responsável por tarefas de construção, execução e distribuição dos containers. Ele faz isso gerenciando objetos como imagens, containers, redes e volumes.


O client Docker e o dockerd podem ser executados na mesma máquina ou em máquinas diferentes. O importante é entender que os containers serão criados e gerenciados na máquina onde estiver o dockerd. No dia a dia, para um ambiente de desenvolvimento, ambos estarão na mesma máquina.


Fonte: https://docs.docker.com/get-started/overview/


Podemos dizer que um container é a “virtualização” de sua aplicação, diferente de uma máquina virtual (VM) que “virtualiza” o sistema operacional como um todo.


Aí o céu é o limite, porque em qualquer lugar que você subir esse container você deverá ter o mesmo funcionamento da sua aplicação, sem se preocupar com versões de pacotes e outras dependências, porque você define tudo isso no momento de criação da estrutura de seu container. E a essa estrutura damos o nome de imagem.


O que é uma imagem?


Eu gosto de fazer a seguinte analogia: o container é como um objeto instanciado, rodando em memória. A imagem é como a classe que tem todas as definições para o objeto em questão. Mas isso é apenas uma analogia, não vai confundir as coisas :D


Numa definição mais direta, uma imagem é uma estrutura com instruções para criar um container.


Geralmente uma imagem tem como base uma outra imagem e aplica customizações necessárias em cima desta imagem base.


Para visualizarmos melhor isso, vamos entender sobre um artefato importantíssimo que é o Dockerfile. Com ele você define os passos necessários para criar uma imagem. Então no fundo, no fundo é no Dockerfile que definimos a estrutura empregada na criação de um container, pois o Dockerfile descreve os passos para geração da imagem, e ao rodar uma imagem subimos um container!


Fonte: https://medium.com/platformer-blog/practical-guide-on-writing-a-dockerfile-for-your-application-89376f88b3b5


Mão na massa!


Antes de “brincarmos” com Docker precisamos instalar ele em nossa máquina. Acesse https://www.docker.com/products/docker-desktop e instale conforme seu sistema operacional.


Crie uma pasta qualquer e dentro dela crie um arquivo Dockerfile (é assim mesmo, sem extensão).


Abra esse arquivo com o seu editor de texto preferido, eu costumo utilizar o Visual Code. Iremos ter neste arquivo o seguinte conteúdo:

 

FROM nginx:latest
 
COPY ./index.html /usr/share/nginx/html/index.html


Aqui estamos indicando que nossa imagem base é uma imagem nginx (que é um servidor web muito utilizado) na sua última versão (latest).


Depois iremos copiar um arquivo index.html, que iremos criar, para o caminho /usr/share/nginx/html/ dentro da imagem. Essa é a mágica! Quando eu subir um container dessa nova imagem que estamos definindo, ele terá todo um filesystem linux, que para ele será isolado, e conseguimos manipular o conteúdo desse filesystem no momento de criação da imagem.


Em resumo, nessa pasta listada acima é onde ficam os arquivos padrão do nginx e o index.html é a página web que ele vai nos mostrar ao abrir uma porta que iremos definir. Calma, chegaremos lá!


No mesmo nível de pasta do arquivo Dockerfile crie um arquivo index.html com o seguinte conteúdo:


<!doctype html>
<html lang="en">
<head>
 <meta charset="utf-8">
 <title>DIO - Docker</title>
</head>
<body>
 <h2>Aprendendo Docker com a DIO!!!</h2>
</body>
</html>


Agora via linha de comando, acesse a pasta onde você acabou de criar esses dois arquivos e execute o seguinte comando:


 docker build . -t docker-dio


Estamos aqui dizendo ao dockerd: construa uma imagem utilizando o Dockerfile da pasta atual (.) e insira o nome (-t) nela de “docker-dio”.


O resultado pode ser visto:


Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM nginx:latest
 ---> c39a868aad02
Step 2/2 : COPY ./index.html /usr/share/nginx/html/index.html
 ---> 08a785335211
Successfully built 08a785335211
Successfully tagged docker-dio:latest


Em resumo, ele executou os dois steps que definimos no Dockerfile.


Se agora executarmos o seguinte comando, podemos ver a nossa imagem criada localmente:


docker images

REPOSITORY               TAG               IMAGE ID    CREATED     SIZE
docker-dio               latest             08a785335211  4 minutes ago  133MB


Agora para finalizarmos nosso teste, precisamos subir um container desta imagem. Para fazermos isso, execute o seguinte comando:


docker run -d -p 8080:80 docker-dio


Aqui estamos dizendo ao dockerd: rode um container da imagem “docker-dio” e ligue a porta 80 do container à porta 8080 da máquina física. Olha outra mágica! Eu consigo da minha máquina física acessar a aplicação rodando dentro do container! No caso a porta 80 é a porta padrão que o nginx vai subir a aplicação lá dentro do container, mas quero acessar ela através da minha porta 8080. E para testar basta acessar no navegador da sua máquina física o endereço: http://localhost:8080/ e ver o resultado:



O “-d” que utilizamos é para ele subir o container “desatachado” (detached) da linha de comando.


Agora se executarmos o comando a seguir conseguiremos ver dados do container em execução:


docker ps

CONTAINER ID  IMAGE    COMMAND         CREATED     STATUS     PORTS         NAMES
3c53979af759  docker-dio  "/docker-entrypoint.…"  5 seconds ago  Up 3 seconds  0.0.0.0:8080->80/tcp  reverent_hugle


Para encerrar a execução do container, basta executar o seguinte comando, trocando <container_id> pelo CONTAINER ID obtido no comando anterior (docker ps):


docker stop <container_id>


Recapitulando


Docker é uma das mais famosas ferramentas para criação e administração de containers no mercado atualmente.


Um container é criado através da definição de uma imagem, que se dá através dos passos contidos em um Dockerfile.


Ainda envolvidos com o universo Docker existem outros artefatos como rede, volume, registry, porém são assuntos para outro momento.


4
90

Comentários (4)

2

Top resumo professor #Gabriel_Faraday, como sempre de Parabéns!

2
Lucas Magalhães

Lucas Magalhães

23/02/2021 21:20

Muito bom. Preciso me aventurar mais no Docker.

1
Silvair Soares

Silvair Soares

24/03/2021 14:27

O primeiro artigo sobre Docker que eu ví, com um nível conceitual e facilmente "entendível" para quem ainda não conhece.

Parabéns Gabriel!

1
Rosemeire Deconti

Rosemeire Deconti

24/03/2021 11:16

Valeu ter colocado o link deste artigo em seu outro artigo mais recente! Grata!