Docker
Docker é a plataforma de containers mais usada no mercado. Com ela você empacota uma aplicação e todas as suas dependências em uma unidade portátil que roda de forma idêntica em qualquer ambiente — do laptop do dev até a produção em cloud.
O conceito central é isolamento: cada container roda de forma completamente isolada dos demais e do host, usando recursos do próprio kernel Linux.
Dois tipos de isolamento
Lógico — Namespaces: isolam processos, redes, usuários e sistemas de arquivos. Cada container enxerga apenas o que é seu.
Físico — Cgroups: limitam o uso de CPU, memória e disco. Garantem que um container não consuma recursos dos outros.
Arquitetura
O Docker Engine usa três módulos do kernel Linux:
Namespaces— isolamento lógico de processos, redes, usuáriosCgroups— isolamento físico de CPU, memória, I/ONetfilter— roteamento de rede, NAT e redirecionamento de pacotes
Imagens em camadas: todas as camadas são read-only, exceto a camada superior de cada container (onde as alterações acontecem). Se você tem 5 containers baseados na mesma imagem de 500 MB, o disco não aloca 2,5 GB — todos compartilham a mesma base. Só a camada de escrita de cada container é individual.
Instalação
curl -fsSL https://get.docker.com/ | bash
docker version
docker container ls
Para usar sem sudo, adicione seu usuário ao grupo docker:
sudo usermod -aG docker $USER
Ciclo de Vida do Container
Rodando o primeiro container
docker container run hello-world
Flags essenciais do run
| Flag | Função |
|---|---|
-d |
Daemon — roda em background |
-ti |
Terminal interativo (bash, sh) |
-p 8080:80 |
Mapeia porta do host para o container |
-m 128M |
Limita memória |
--cpus 0.5 |
Limita a 50% de um núcleo |
--name |
Define nome do container |
--rm |
Remove o container ao encerrar |
Containers interativos
# Entrar dentro de um ubuntu
docker container run -ti ubuntu
# Ver processos (apenas os do container)
root@2fd8c26be92e:/# ps -ef
UID PID CMD
root 1 /bin/bash
root 8 ps -ef
CTRL+D encerra o container (mata o processo principal).
CTRL+P+Q sai sem matar o container.
Containers em background (daemon)
Para serviços como nginx, nunca use -ti — o entrypoint não é o bash:
docker container run -d nginx
Para executar comandos dentro de um container em execução, use exec:
docker container exec -ti <id> bash
docker container exec -ti <id> ls /etc/nginx
Gerenciamento
docker container ls # containers em execução
docker container ls -a # todos (incluindo parados)
docker container stop <id>
docker container start <id>
docker container restart <id>
docker container pause <id>
docker container unpause <id>
docker container rm <id> # remove parado
docker container rm -f <id> # força remoção
docker container logs -f <id> # logs em tempo real
docker container inspect <id> # detalhes completos em JSON
docker container stats <id> # uso de CPU/memória em tempo real
docker container top <id> # processos rodando no container
Limitando Recursos
Definir limites na criação:
docker container run -d -m 128M --cpus 0.5 nginx
Atualizar em container já em execução:
docker container update --cpus 0.8 --memory 64M <id>
Testar pressão com stress (instalar dentro do container):
apt-get install -y stress
stress --cpu 1 --vm-bytes 128M --vm 1
Volumes — Persistindo Dados
O filesystem do container é volátil — quando o container é removido, tudo dentro dele some. Volumes existem fora do container e persistem independentemente.
Bind Mount — você define o caminho
# Montar diretório do host no container
docker container run -ti \
--mount type=bind,src=/opt/meuapp,dst=/app \
debian
# Somente leitura
docker container run -ti \
--mount type=bind,src=/opt/meuapp,dst=/app,ro \
debian
Docker Volume — gerenciado pelo Docker
# Criar volume
docker volume create dbdados
# Usar volume no container
docker container run -d \
--mount type=volume,src=dbdados,dst=/data \
postgres:16
# Listar volumes
docker volume ls
# Inspecionar
docker volume inspect dbdados
# Remover (só se não estiver em uso)
docker volume rm dbdados
# Remover todos os volumes não utilizados
docker volume prune
Todos os volumes ficam em /var/lib/docker/volumes/.
Compartilhando volume entre containers
docker container run -d -p 5432:5432 --name pgsql1 \
--mount type=volume,src=dbdados,dst=/data \
postgres:16
docker container run -d -p 5433:5432 --name pgsql2 \
--mount type=volume,src=dbdados,dst=/data \
postgres:16
Ambos os containers leem e escrevem no mesmo volume.
Backup de volume
mkdir /opt/backup
docker container run --rm \
--mount type=volume,src=dbdados,dst=/data \
--mount type=bind,src=/opt/backup,dst=/backup \
debian tar -cvf /backup/bkp-banco.tar /data
Dockerfile — Criando Suas Imagens
O Dockerfile descreve como construir uma imagem. Cada instrução cria uma nova camada.
Instruções principais
| Instrução | Descrição |
|---|---|
FROM |
Imagem base — sempre a primeira linha |
RUN |
Executa comando no build, cria camada |
CMD |
Comando padrão ao iniciar o container |
ENTRYPOINT |
Executável principal do container |
COPY |
Copia arquivos para o filesystem |
ADD |
Como COPY, mas aceita TAR e URLs |
ENV |
Define variáveis de ambiente |
EXPOSE |
Documenta a porta que o container escuta |
VOLUME |
Declara ponto de montagem de volume |
WORKDIR |
Define diretório de trabalho |
USER |
Define usuário (padrão: root) |
LABEL |
Adiciona metadados à imagem |
ARG |
Variável de build-time (não fica na imagem) |
Exemplo: container com stress
FROM debian
LABEL app="stress-test"
ENV AMBIENTE="dev"
RUN apt-get update && apt-get install -y stress && apt-get clean
CMD stress --cpu 1 --vm-bytes 64M --vm 1
docker image build -t meu-stress:1.0 .
docker container run -d meu-stress:1.0
Exemplo: Apache com ENTRYPOINT
FROM debian
RUN apt-get update && apt-get install -y apache2 && apt-get clean
ENV APACHE_LOCK_DIR="/var/lock"
ENV APACHE_PID_FILE="/var/run/apache2/apache2.pid"
ENV APACHE_RUN_USER="www-data"
ENV APACHE_RUN_GROUP="www-data"
ENV APACHE_LOG_DIR="/var/log/apache2"
LABEL description="Webserver" version="1.0.0"
VOLUME /var/www/html/
EXPOSE 80
ENTRYPOINT ["/usr/sbin/apachectl"]
CMD ["-D", "FOREGROUND"]
Multi-stage build — imagem final mínima
Compila em uma imagem pesada, copia apenas o binário para uma imagem leve:
# Stage 1: build
FROM golang AS build
WORKDIR /src
ADD . /src
RUN go build -o goapp
# Stage 2: imagem final
FROM alpine:3.19
WORKDIR /app
COPY --from=build /src/goapp /app
ENTRYPOINT ["./goapp"]
A imagem final tem apenas o binário + Alpine (~5 MB), sem o toolchain Go.
Buildar e publicar
# Build local
docker image build -t minha-imagem:1.0 .
# Ver camadas e histórico
docker history minha-imagem:1.0
# Login no Docker Hub
docker login
# Push
docker image tag minha-imagem:1.0 usuario/minha-imagem:1.0
docker push usuario/minha-imagem:1.0
Registry Local
Para manter suas imagens em ambiente privado sem depender do Docker Hub:
# Subir um registry local na porta 5000
docker container run -d \
-p 5000:5000 \
--restart=always \
--name registry \
registry:2
# Taguear imagem para o registry local
docker tag minha-imagem:1.0 localhost:5000/minha-imagem:1.0
# Push para o registry local
docker push localhost:5000/minha-imagem:1.0
Imagens ficam em /var/lib/registry/docker/registry/v2/repositories/.
Docker Swarm — Orquestração em Cluster
O Swarm transforma múltiplos hosts Docker em um cluster com load balancing e failover automáticos.
Manager — conhece o estado do cluster, agenda containers, expõe a API.
Worker — executa os containers distribuídos pelo manager.
Criando o cluster
# No host manager (gera um token)
docker swarm init
# Nos hosts workers (usar o token gerado)
docker swarm join --token <token> <manager-ip>:2377
# Ver todos os nodes
docker node ls
Gerenciando nodes
# Ver token para adicionar workers
docker swarm join-token worker
# Ver token para adicionar managers
docker swarm join-token manager
# Promover worker a manager
docker node promote fxshell-02
# Rebaixar manager a worker
docker node demote fxshell-02
# Pausar node (não recebe novos containers)
docker node update --availability pause fxshell-02
# Dreno para manutenção (migra containers para outros nodes)
docker node update --availability drain fxshell-02
# Reativar node
docker node update --availability active fxshell-02
# Remover node do cluster
docker swarm leave # rodar no próprio node
docker node rm fxshell-02 # rodar no manager
Services — o coração do Swarm
Um Service define quantas réplicas de um container devem rodar, em quais ports e com quais configs. O Swarm distribui as réplicas pelos workers e garante que o número desejado esteja sempre disponível.
# Criar service com 5 réplicas de nginx
docker service create \
--name webserver \
--replicas 5 \
-p 8080:80 \
nginx
# Listar services
docker service ls
# Ver em quais nodes estão rodando
docker service ps webserver
# Detalhes completos
docker service inspect webserver
# Escalar para 10 réplicas
docker service scale webserver=10
# Logs de todos os containers do service
docker service logs -f webserver
# Remover service
docker service rm webserver
Service com volume
docker service create \
--name webserver \
--replicas 5 \
-p 8080:80 \
--mount type=volume,src=dados,dst=/app \
nginx
O volume dados fica disponível em todos os containers do service, em todos os nodes.
Limpeza
# Remover containers parados
docker container prune
# Remover volumes não utilizados
docker volume prune
# Remover imagens não utilizadas
docker image prune
# Limpeza completa (containers, imagens, redes, cache de build)
docker system prune -a
Referência rápida
# Containers
docker container run -d -p 8080:80 --name web nginx
docker container exec -ti <id> bash
docker container logs -f <id>
docker container stats
docker container inspect <id>
# Imagens
docker image ls
docker image pull ubuntu:22.04
docker image build -t app:1.0 .
docker image push usuario/app:1.0
docker image rm <id>
# Volumes
docker volume create dados
docker volume ls
docker volume inspect dados
docker volume rm dados
# Swarm
docker swarm init
docker node ls
docker service create --name app --replicas 3 -p 80:80 nginx
docker service scale app=5
docker service ps app