Este material era para ser um curso de Docker. Mas eu não tenho skills para gravação/edição de vídeo. Minha intenção aqui é apresentar alguns conceitos básicos de Docker.
O que é Docker?
Introdução
Antes de iniciar qualquer curso sobre Docker, precisamos primeiro entender o que é Docker? Essa pergunta pode não ter uma resposta muito simples, visto que você pode ouvir esse termo em vários contextos diferentes.
Para responder vamos levantar as seguintes perguntas?
- Seria Docker uma empresa?
- Seria Docker um software?
- Seria Docker uma plataforma?
- Seria Docker uma tecnologia?
Seria Docker uma empresa?
SIM!
Sim Docker é a empresa que criou o Docker. A Docker, Inc. provê soluções Enterprise e o Docker Hub.
Seria Docker um Software?
SIM!
Sim, você pode executar um docker --version
em qualquer máquina com Docker instalado. Ele é desenvolvido pela Docker, Inc. e pode ser instalado em qualquer dos mais comuns SOs do mercado.
Seria Docker uma Plataforma?
Podemos dizer que SIM!
Não sou tão assertivo nessa resposta porque o termo plataforma é genérico. Mas há uma série de componentes no Docker que nos permite chamar ele de plataforma. Você usa docker para criar imagens, que pode ser armazenadas em um Docker Registry, que serão carregadas por um Gerenciador de Containers. Há inúmeros nós nessa teia.
Seria Docker uma Tecnologia?
Com certeza SIM!
O que a Docker, Inc. criou foi muito além de um software. Ela utilizou vários recursos já existente para criar um conceito a containerização. Com isso se gerou uma Explosão Cambriana na industria. Novos conceitos e padrões surgirão depois dele.
Assim podemos dizer que a maneira de se gerenciar uma infra-estrutura em 2019 é completamente diferente da maneira que se gerenciava em 2005. COMPLETAMENTE DIFERENTE!
Depois do advento do Docker, a Docker, Inc. cedeu sua core engine para Cloud Native Computing Foundation sob o nome de containerd. Você pode ver pela CNCF Landscape que o containerd é uma caixinha em Container Runtime. A evolução da tecnologia não é mais controlada pela Docker, Inc., mas por essa organização que faz parte da Linux Foundation.
A tecnologia Docker
“Na natureza nada se cria, nada se perde, tudo se transforma” Antoine-Laurent de Lavoisier
Essa frase de Lavoisier se adequa perfeitamente a projetos Open Source! Na verdade Docker não criou nada novo e nem utilizou nenhuma tecnologia nova, mas a partir do que existia uma nova tecnologia foi criada.
Tecnologias Bases
Docker se baseia em algumas tecnologias já existentes no Linux.
COW
Copy On Write é uma técnica que permite a criação de uma estrutura de arquivos por camada. Cada camada altera a anterior e camadas podem ser compartilhadas com processos diferentes.
cgroups
cgroups é uma feature do Linux que permite controlar o tanto de recurso (CPU, Memória, I/O) que um processo pode utilizar.
iptables
iptables é um programa Linux que permite criar regras de redirecionamento de portas dentro do Linux.
Linux Namespaces
Linux Namespaces permite o compartilhamento, e o isolamento, de recursos do SO dentro do Linux. Similar ao cgroups, mas se refere a outros tipos de recursos. Por exemplos: PIDs, nomes de arquivos, hostnames, etc…
Infraestrutura Imutável
O termo Immutable Infrastructure vem em contraste ao que tinhamos antes do Docker, que é a Mutable Infraestructure.
Em uma Infraestrutura mutável, para fazer qualquer alteração em ambientes, deve-se alterar as configurações existente. Cada atualização há um risco muito grande que deve ser minimizado por técnicas como rollback, dry-run e backups. Cada update é um risco, pois o novo deploy vem alterar o antigo.
Com a infraestrutura imutável, o novo deploy vem em paralelo ao antigo. É criado uma nova estrutura e o mesmo substitui o antigo. Assim, caso o novo apresente falhas, o antigo pode ser reutilizado.
Antes do Docker
Antes do Docker existir, para fazer a configuração de um serviço era preciso alguns passos:
- Configurar um Servidor (Instalar Linux, Unix ou Windows)
- Instalar dependências (Apacha httpd, Java, Python, etc…)
- Configurar o Servidor de Aplicação (JBoss, IIS)
- Fazer deploy da Aplicação
- Monitorar o estado da Aplicação (monit)
Configurar um servidor era a tarefa mais fácil, o difícil era fazer atualizações ou gerenciar projetos legados. Muitas vezes duas aplicações precisam de diferentes dependências para rodar. Ou tinha problema com o compartilhamento de recursos, duas aplicações tentando escutar na mesma porta TCP.
Atualizar um servidor de produção, envolvia criar scripts para fazer diversas alterações que nem sempre funcionavam na produção. Quando um erro acontecia na implementação…. ROLLBACK! O que também era uma atividade complexa!
Possível solução
Uma boa e possível solução era a criação de fotos (ou snapshots) do servidor. E se pudéssemos a partir de uma foto rodar um servidor? Ou voltar para uma versão anterior a partir de uma foto? E se esse servidor fosse totalmente isolado? Posso executar duas versões dele em paralelo?
Depois do Docker
Para executar um servidor:
docker pull my-application:1.0.1
docker stop my-app
docker rm my-app
docker run -name my-app -p 8080:80 my-application:1.0.1
Com as 4 linhas acima, podemos atualizar uma aplicação chamada my-application
para versão 1.0.1. Deu erro?
docker stop my-app
docker rm my-app
docker run -name my-app -p 8080:80 my-application:1.0.0
Mais 3 linhas para fazer o rollback seguro!
Conceitos Básicos
Um pouco antes do Docker, uma das tecnologias da moda era a virtualização. Mas em que consistia a virtualização e porque a necessidade de containerização
Virtualização
Talvez você já tenha criado uma Máquina Virtual. Se não criou, gaste algum tempo baixando o VirtualBox e rodando algumas versões de SOs diferentes dentro da sua máquina.
Quando falamos de virtualização, estamos dividindo os recursos físicos da máquina com outras máquinas, que são chamadas máquinas virtuais. Assim, podemos alocar 1 CPU, 2GB de memória, etc… Nessa máquina rodará um Sistema Operacional completo que não compartilhará nenhum recurso com nenhum outro. Se esse SO não utilizar todo o recurso alocado, este não poderá ser compartilhado.
Containerização
Com containers todas as aplicações compartilham o mesmo SO. O SO rodará a aplicação isoladamente, criando e alocando qualquer recurso que o container necessitar.
Vantagens
Como a containerização acontece no nível do Sistema Operacional, há uma série de vantagens:
- Inicialização imediata. Não é necessário se inicializar o Sistema Operacional
- Compartilhamento de Recursos. Caso o container não utilize Memoria ou CPU, esta fica disponível para outro.
- É possível criar mais uma instância do mesmo container imediatamente.
Docker Building Blocks
Gosto do conceito de Building Blocks, quando me refiro a ele estou definindo elementos básicos para algo. Assim em Docker podemos definir alguns building blocks.
Para o desenvolvimento de qualquer aplicação Docker, é necessário entender o que são cada um desses elementos.
- Imagem
- TAGs
- Container
- Volume
- Network
- Registry
- Dockerfile
Imagem
Uma Imagem é uma foto do Container em seu momento inicial. Se formos comparar com os conceitos de máquinas virtuais, a Imagem seria um SNAPSHOT.
Uma Imagem é usada para gerar um Container. Uma Imagem pode ser gerada a partir de um Container. Uma Imagem tem algumas propriedades que estendem o conceito de Snapshot, podemos definir qual comando a Imagem irá executar assim que ela iniciar.
Uma Imagem é preferencialmente construida a partir de um Dockerfile.
TAGs
Uma Imagem pode ter uma ou mais TAG associada. Cada imagem possui um nome, este nome pode estar associado a várias TAGs.
Por exemplo, se formos criar um container do MariaDB, sabemos que o nome dele é mariadb
. Mas se referenciarmos apenas esse nome, será baixada a image mariadb:latest
, o que não é tão bom, visto que não sabemos exatamente qual versão será executada. No caso do MariaDB, temos as seguintes TAGs:
- 10.4.10-bionic, 10.4-bionic, 10-bionic, bionic, 10.4.10, 10.4, 10, latest
- 10.3.20-bionic, 10.3-bionic, 10.3.20, 10.3
- 10.2.29-bionic, 10.2-bionic, 10.2.29, 10.2
- 10.1.43-bionic, 10.1-bionic, 10.1.43, 10.1
Uma boa opção, seria utilizar mariadb:10.4
para escolher a versão 10.4.10 ou qualquer versão futura com bug fixes.
Container
Um Container é uma instância de uma aplicação. Pode haver vários Containers rodando com a partir da mesma Imagem. Ao se executar um Container é preciso uma Imagem e um conjunto de informações:
- Volumes
- Variáveis de Ambiente
- Portas
- etc…
Volume
O Sistema de Arquivo de um Container é descartável. Assim, ao se remover o container, todos os arquivos dele são removidos. Um Volume é um mapeamento entre um diretório da máquina hospedeira para o container. Usando COW, o diretório, ou arquivo, dentro container é sobrescrito.
Network
Quando um container é executado, pode pertencer a uma ou várias Networks. Por padrão, ele pertence a Network Default. Para cada Network associada, ele terá um IP NAT associado.
Uma Network serve para criar uma VPC. Dois containers só podem se comunicar se pertencerem a mesma Network. Uma Network contém DNS que resolve o IP através do nome do container. Assim, se um container tentar acessar container-1:8080
estará tentando acessar a porta 8080 do container com nome container-1.
Registry
Um Registry é um servidor web para armazenar uma Imagem. No ciclo de vida de uma Imagem, ela pode ser gerada ou baixada de um Registry.
O padrão é o Docker Hub, sempre que possível procure imagens lá. No Docker Hub há imagens verificadas e não verificadas. Procure usar as imagens verificadas, caso contrário você pode estar correndo o risco de expor seus dados.
Dockerfile
Dockerfile é o script de criação de uma Imagem. Uma Imagem deve ser construida através de um script, e pode ser reconstruida em qualquer máquina.
Conclusão
Docker pode parecer uma mágica, mas é só o uso inteligente de tecnologias há muito tempo já existiam no Sistema Operacional Linux. Com o uso dessas tecnologias, podemos agora criar deploys completamente independentes dentro de um mesmo sistema operacional, usando a mesma infraestrutura.
Com Docker não há o desperdício de recursos que existia com a Virtualização. Agora os recursos podem ser alocados de forma mais inteligente.