O que é um Container ?
Container é uma forma de isolar processos e recursos para executar uma aplicação. É um agrupamento de uma aplicação junto com suas dependências, que compartilham o kernel do sistema operacional do host.
flowchart LR
subgraph FISICA["Máquina física"]
direction TB
subgraph APPS_F["Aplicações"]
direction LR
F1["App 1"]
F2["App 2"]
F3["App 3"]
end
FOS["Sistema operacional"]
FHW["Servidor / Hardware"]
F1 --> FOS
F2 --> FOS
F3 --> FOS
FOS --> FHW
end
subgraph VMS["Máquinas virtuais"]
direction TB
subgraph VM_APPS["VMs"]
direction LR
VM1["VM 1<br/>App + SO"]
VM2["VM 2<br/>App + SO"]
VM3["VM 3<br/>App + SO"]
end
HYP["Hypervisor"]
VOS["Sistema operacional"]
VHW["Servidor / Hardware"]
VM1 --> HYP
VM2 --> HYP
VM3 --> HYP
HYP --> VOS
VOS --> VHW
end
subgraph CONTAINERS["Containers"]
direction TB
subgraph C_APPS["Aplicações isoladas"]
direction LR
C1["App 1"]
C2["App 2"]
C3["App 3"]
end
DOCKER["Docker Engine"]
COS["Sistema operacional do host"]
CHW["Servidor / Hardware"]
C1 --> DOCKER
C2 --> DOCKER
C3 --> DOCKER
DOCKER --> COS
COS --> CHW
end
FOS -->|Virtualização| HYP
VOS -->|Containers| DOCKER
Outro ponto interessante na utilização de containers é a portabilidade. Não importa em qual ambiente você criou o seu container. Ele poderá ser executado em qualquer outro ambiente que possua o Docker instalado. Mas a portabilidade é apenas uma parte do que torna os containers tão úteis. Quando vários containers estão rodando na mesma máquina, é necessário impedir que um deles consuma todos os recursos disponíveis e prejudique os demais.
É nesse ponto que entram os cgroups (control groups). Eles são recursos do kernel Linux responsáveis por controlar e contabilizar o uso de recursos por grupos de processos, como CPU, memória, I/O de disco e quantidade de processos.
NNa prática, os cgroups permitem definir limites para cada container. Assim, uma aplicação com erro ou pico de consumo não utiliza toda a memória ou processamento do host e deixa os outros containers sem recursos.
Apesar disso, os cgroups não realizam o isolamento entre os containers. Sua função é controlar e limitar a quantidade de recursos que cada grupo de processos pode consumir. O isolamento propriamente dito é realizado pelos namespaces, que fazem com que cada container tenha sua própria visão do sistema operacional.
Enquanto os cgroups controlam quanto de recurso um container pode utilizar, os namespaces controlam o que ele consegue enxergar no sistema.
É por meio dos namespaces que cada container possui sua própria visão de processos, rede, usuários, hostname e sistema de arquivos, mesmo compartilhando o mesmo kernel Linux com outros containers.
Namespace:
Namespaces foi adicionados no kernel Linux na versão 2.6.24 e são eles que permitem o isolamento de processos quando estamos utilizando o Docker. São responsáveis por fazer com que cada container possua seu próprio ambiente. ou seja, cada container terá a sua árvore de processos, pontos de montages e etc. Fazendo com que um container não interfira na execução do outro.
PID namespace:
O PID namespace permite que cada container tenha seus próprios identificadores de processo. Isso faz com que o container possua um PID para um processo em execução e, quando você procurar por esse processo na máquina host, ele será encontrado, porém com outra identificação, ou seja, com outro PID.
Net namespace:
O Net namespace permite que cada container possua sua própria interface de rede e suas próprias portas. Para que seja possível a comunicação entre os containers, é criado um par de interfaces virtuais: uma responsável pela interface do container (normalmente utilizando o nome eth0) e outra responsável por uma interface no host, normalmente chamada de veth (veth + um identificador aleatório). Essas duas interfaces estão ligadas através da bridge do Docker no host, permitindo a comunicação entre os containers por meio do roteamento de pacotes.
Mnt namespace:
É a evolução do chroot. Com o Mnt namespace, cada container pode ser dono do seu próprio ponto de montagem, bem como do seu sistema de arquivos raiz. Ele garante que um processo executado em um sistema de arquivos não consiga acessar outro sistema de arquivos montado por outro Mnt namespace.
IPC namespace:
Ele provê um System V IPC isolado, além de uma fila de mensagens POSIX própria.
UTS namespace:
Responsável por prover o isolamento do hostname, do nome de domínio, da versão do sistema operacional, entre outras informações do sistema.
User namespace:
É o namespace mais recente adicionado ao Kernel Linux, disponível desde a versão 3.8. Ele é responsável por manter o mapeamento de identificação de usuários em cada container.