Docker é uma plataforma de código aberto que simplifica o uso de containers Linux.
Um container é um processo isolado que empacota uma aplicação e suas bibliotecas, sem incluir um sistema operacional completo.
Containers vs Máquinas Virtuais
Máquinas Virtuais simulam um hardware completo através do hypervisor e exige um sistema operacional dedicado para cada instância — é como ter vários computadores físicos rodando em um só.
Containers compartilham o kernel do host e isolam apenas o necessário (processos, rede, sistema de arquivos), consumindo uma fração dos recursos de uma VM.
Comparativo
| Característica | Máquina Virtual | Container |
|---|---|---|
| Tamanho | GBs | MBs |
| Tempo de inicialização | Minutos | Segundos |
| Isolamento | Completo (hardware virtual.) | Nível de processo |
| Sistema Operacional | Completo por VM | Compartilhado |
| Performance | Overhead do hypervisor | Próximo ao nativo |
| Portabilidade | Limitada | Alta |
| Densidade | Dezenas por host | Centenas/milhares por host |
Containers e VMs não são excludentes! É comum executar containers dentro de VMs para combinar os benefícios de ambos.
Docker em Diferentes Sistemas Operacionais
Containers baseados em distribuições Linux dependem de funcionalidades nativas do Kernel Linux, por isso só rodam diretamente no Linux — em outros sistemas operacionais é necessária uma camada de virtualização:
macOS
Apesar de ser um sistema Unix, o macOS é baseado no BSD e usa o kernel Darwin. Como containers baseados em Linux só rodam sobre o Kernel Linux, o Docker Desktop para Mac cria uma VM em segundo plano para executá-los.
Windows
O Windows oferece duas opções:
- WSL 2 (recomendado): O Windows Subsystem for Linux 2 executa um kernel Linux real usando virtualização leve. O Docker Engine pode rodar diretamente dentro do WSL 2 oferece uma performance próxima ao Linux nativo.
- Hyper-V: Alternativa que cria uma VM Linux tradicional, similar ao macOS.
Se você usa Windows com WSL 2, é possível instalar o Docker Engine diretamente na distribuição Linux (Ubuntu, Debian, etc.) sem precisar do Docker Desktop.
O Docker no Windows também pode rodar "Windows Containers" nativos, porém sua adoção é limitada comparada aos containers Linux, que são o padrão da indústria e foco deste guia.
Funcionalidades do Kernel Linux
Containers dependem de três funcionalidades nativas do kernel Linux.
Isolamento por Processo
O processo principal do container (PID 1) é configurado com namespaces e cgroups específicos, e todos os processos filhos herdam essas configurações automaticamente.
Namespaces
Namespaces isolam recursos do sistema para que um processo tenha sua própria visão do ambiente. Cada container recebe seus próprios namespaces:
| Namespace | O que isola | Exemplo prático |
|---|---|---|
| PID | Processos | Container vê apenas seus próprios processos (PID 1 é o processo principal) |
| NET | Rede | Container tem sua própria interface de rede, IP e tabela de rotas |
| MNT | Sistema de arquivos | Container tem sua própria árvore de diretórios |
| UTS | Hostname | Container pode ter seu próprio hostname |
| IPC | Comunicação entre processos | Filas de mensagem e memória compartilhada isoladas |
| USER | Usuários | UID 0 (root) dentro do container pode ser mapeado para usuário não-root no host |
O Linux possui mais dois namespaces: Cgroup namespace (kernel 4.6, 2016) isola a visão da hierarquia de cgroups — não confundir com cgroups em si, que são um mecanismo separado para limitar recursos. Time namespace (kernel 5.6, 2020) isola os relógios do sistema. Ambos são menos comuns no contexto de containers Docker.
Por padrão, cada container recebe seu próprio conjunto de namespaces. Porém, é possível compartilhar namespaces específicos entre containers. Por exemplo, dois containers podem entrar no mesmo namespace de rede e se comunicar via localhost, enquanto mantêm namespaces separados para PID, MNT, UTS, IPC e USER.
Control Groups (cgroups)
Enquanto namespaces isolam o que o processo pode ver, cgroups controlam o quanto de cada recurso ele pode usar:
- CPU: Controla o consumo de processador
- Memória: Define limites de RAM (o container é encerrado se exceder)
# Exemplo: executar container com limite de 512MB de RAM e 50% de CPU
docker run -m 512m --cpus=0.5 nginxUnion File System
O sistema de arquivos em camadas permite que containers compartilhem partes comuns e mantenham apenas suas diferenças. Funciona como uma pilha de transparências:
- Camada base (read-only): Sistema operacional mínimo
- Camadas intermediárias (read-only): Dependências e aplicação
- Camada do container (read-write): Alterações feitas durante execução
Isso explica por que imagens Docker são tão eficientes — se você tem 10 containers baseados na mesma imagem, as camadas base são compartilhadas em disco.
A camada read-write é efêmera: se o container for removido, os dados serão perdidos. Para fazer persistência de dados podemos montar diretórios do host no container (bind mounts) ou usar Volumes gerenciados pelo Docker (que veremos em módulos futuros).
Arquitetura do Docker
- Cliente: A CLI (como
docker run,docker build) envia comandos via REST API para o daemon. - Daemon (dockerd): Processo que roda em background e gerencia imagens, containers, networks e volumes. Delega a execução para o containerd via gRPC.
- containerd: Runtime de alto nível que gerencia o ciclo de vida dos containers, baixa e armazena imagens. Comunica-se com os shims via ttrpc.
- shim: Processo intermediário que permite ao containerd reiniciar sem afetar os containers em execução. Mantém os streams (stdin/stdout/stderr) abertos e reporta o status de saída.
- runc: CLI que cria e executa containers usando namespaces, cgroups e union file system. Instalado junto com o Docker (via pacote
containerd.io), é o runtime de referência da OCI. Após iniciar o container o runc encerra e o shim assume o controle. - container: Processo isolado executando a aplicação. Comunica-se com o shim via stdio (stdin/stdout/stderr) para I/O e gerenciamento de ciclo de vida.
Instalação do Docker (Ubuntu)
- Remova versões antigas (se existirem):
sudo apt remove $(dpkg --get-selections docker.io docker-compose \
docker-compose-v2 docker-doc podman-docker containerd runc | cut -f1) || true- Instale dependências:
sudo apt update
sudo apt install ca-certificates curl- Adicione a chave GPG oficial do Docker:
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc- Configure o repositório:
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF- Instale o Docker Engine:
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginConfiguração Pós-Instalação
Após a instalação configure o Docker para executar sem sudo e iniciar automaticamente com o sistema.
1. Adicione seu usuário ao grupo docker
Por padrão o Docker requer privilégios de root, para executar comandos sem sudo, adicione seu usuário ao grupo docker.
sudo groupadd docker
sudo usermod -aG docker $USERAdicionar um usuário ao grupo docker concede privilégios equivalentes a root. Só faça isso em máquinas de desenvolvimento ou onde você confia nos usuários.
2. Configure o Docker para iniciar no boot
sudo systemctl enable docker.service
sudo systemctl enable containerd.service3. Reinicie o sistema
Reinicie o computador para que todas as configurações sejam aplicadas corretamente.
O reinício é necessário para que seu usuário seja reconhecido no grupo docker. Alternativas como newgrp docker ou logout/login funcionam, mas reiniciar garante que tudo esteja configurado corretamente, incluindo a inicialização automática do Docker.
4. Teste a instalação
Após o reinício, execute seu primeiro container:
docker run hello-worldSe a instalação estiver correta, você verá uma saída similar a esta:
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
17eec7bbc9d7: Pull complete
Digest: sha256:d4aaab6242e0cace87e2ec17a2ed3d779d18fbfd03042ea58f2995626396a274
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
...
Entendendo o Hello World
O que aconteceu?
- O cliente Docker enviou o comando para o daemon
- O daemon verificou se a imagem
hello-worldexistia localmente - Como não existia, baixou do Docker Hub
- Criou um container a partir da imagem
- Executou o programa dentro do container
- O programa imprimiu a mensagem e o container encerrou
Se você executar o mesmo comando novamente, a imagem não será baixada. O Docker usa o cache local, tornando a execução muito mais rápida.
Executando um container interativo
Vamos executar um container Ubuntu de forma interativa:
docker run -it ubuntu bashVocê agora está dentro de um container Ubuntu! Experimente:
cat /etc/os-release
ls /
whoami
exitComandos Básicos
Os comandos abaixo devem ser executados no terminal do seu sistema (host), não dentro de um container. Se você ainda estiver dentro do container Ubuntu, digite exit para sair.
Verificar versão do Docker
docker versionMostra a versão do cliente e do servidor (daemon):
Client: Docker Engine - Community
Version: 28.1.1
API version: 1.49
Go version: go1.23.8
Git commit: 4eba377
Built: Fri Apr 18 09:52:18 2025
OS/Arch: linux/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 28.1.1
API version: 1.49 (minimum version 1.24)
Go version: go1.23.8
Git commit: 01f442b
Built: Fri Apr 18 09:52:18 2025
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.7.27
GitCommit: 05044ec0a9a75232cad458027ca83437aae3f4da
runc:
Version: 1.2.5
GitCommit: v1.2.5-0-g59923ef
docker-init:
Version: 0.19.0
GitCommit: de40ad0
Informações do sistema
docker infoMostra informações detalhadas sobre a instalação:
Client: Docker Engine - Community
Version: 28.1.1
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.23.0
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.35.1
Path: /usr/libexec/docker/cli-plugins/docker-compose
Server:
Containers: 7
Running: 0
Paused: 0
Stopped: 7
Images: 42
Server Version: 28.1.1
...
Uso de disco
docker system dfMostra quanto espaço está sendo usado:
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 42 7 19.45GB 17.99GB (92%)
Containers 7 0 3.805GB 3.805GB (100%)
Local Volumes 6 4 2.36GB 21.04kB (0%)
Build Cache 225 0 1.306kB 1.306kB
Obtendo Ajuda
O Docker possui documentação integrada excelente:
# Ajuda geral
docker --help
# Ajuda para um comando específico
docker run --help
docker image --help
docker container --help- Docker Desktop overview — Docker em macOS e Windows
- Virtual Machine Manager — Opções de virtualização no Docker Desktop para Mac
- WSL 2 backend — Integração com Windows Subsystem for Linux
- Docker security — Namespaces, cgroups, capabilities
- namespaces(7) — Documentação oficial do kernel Linux sobre namespaces
- Control Group v2 — Documentação oficial do kernel Linux sobre cgroups
- runc — Runtime de referência da OCI
- Storage drivers — Camadas de imagem, copy-on-write
- Runtime resource constraints — Limites de CPU e memória
- Docker overview — Arquitetura cliente-servidor, Docker objects
- dockerd — Comunicação do daemon com containerd via gRPC
- containerd — Runtime de alto nível, shims e gerenciamento de ciclo de vida
- Runtime v2 Shim — Documentação oficial do shim e ciclo de vida dos containers
- containerd/ttrpc — Protocolo de comunicação entre containerd e shims
- Install Docker Engine on Ubuntu — Guia oficial de instalação
- Linux post-installation steps — Configuração do grupo docker e inicialização
Exercícios Práticos
- Instale o Docker em seu sistema seguindo as instruções deste módulo
- Execute
docker versione anote as versões do cliente e servidor - Execute
docker infoe identifique:- Quantos containers você tem?
- Qual o Storage Driver sendo usado?
- Remova a imagem hello-world (caso já tenha em cache):
docker rmi hello-world - Execute
docker run hello-world - Execute novamente o mesmo comando
- Compare as saídas - o que mudou na segunda execução? Por quê?
- Execute um container Ubuntu interativo:
docker run -it ubuntu bash - Dentro do container, execute:
cat /etc/os-release- qual versão do Ubuntu está rodando?ps aux- quantos processos estão rodando?hostname- qual o hostname do container?
- Saia do container com
exit
- Execute
docker infoe responda:- O Docker está usando cgroups v1 ou v2?
- Qual o diretório root do Docker?
- A API experimental está habilitada?
Próximo Módulo
No próximo módulo, vamos explorar as Imagens Docker em detalhes: como funcionam as camadas, como baixar, criar tags, e gerenciar imagens no seu sistema.