Docker 101 - Tecnologias e Conceitos
Tags: docker, containers, devops, linux
Published: 2020-10-22 13:45:27

---
title: Docker 101 - Tecnologias e Conceitos
published: true
description: Quais são os conceitos por trás do Docker? Como o Docker consegue cria a mágica dos container no Linux?
tags: Docker, Containers, DevOps, Linux
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/vpwhp0r7ampxf1jywqv8.jpg
series: Level Up
---

_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?
1. Seria Docker uma empresa?
2. Seria Docker um software?
3. Seria Docker uma plataforma?
4. 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](https://www.cncf.io/) sob o nome de [containerd](https://github.com/containerd/containerd). Você pode ver pela [CNCF Landscape](https://landscape.cncf.io/) 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](https://pt.wikipedia.org/wiki/C%C3%B3pia_em_grava%C3%A7%C3%A3o)
* [cgroups](https://en.wikipedia.org/wiki/Cgroups)
* [iptables](https://pt.wikipedia.org/wiki/Iptables)
* [Linux Namespaces](https://en.wikipedia.org/wiki/Linux_namespaces)

#### 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:

1. Configurar um Servidor (Instalar Linux, Unix ou Windows)
2. Instalar dependências (Apacha httpd, Java, Python, etc...)
3. Configurar o Servidor de Aplicação (JBoss, IIS)
4. Fazer deploy da Aplicação 
5. Monitorar o estado da Aplicação ([monit](https://mmonit.com/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:

```bash
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?

```bash
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.

![Virtual Machine](https://dev-to-uploads.s3.amazonaws.com/i/q40xfw2qlei05qihud6m.png)

### 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.

![Containers](https://dev-to-uploads.s3.amazonaws.com/i/fj02eotpgiggs4mqfrgo.png)

#### Vantagens

Como a containerização acontece no nível do Sistema Operacional, há uma série de vantagens:
1. Inicialização imediata. Não é necessário se inicializar o Sistema Operacional
2. Compartilhamento de Recursos. Caso o container não utilize Memoria ou CPU, esta fica disponível para outro.
3. É 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](https://hub.docker.com/), 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.

---

![Navio carregado de Containers](https://dev-to-uploads.s3.amazonaws.com/i/vpwhp0r7ampxf1jywqv8.jpg)

[Foto de *Tom Fisk* no *Pexels*.](https://www.pexels.com/pt-br/foto/panorama-vista-paisagem-agua-3057963/)