Instalação
Um engine rodando e os comandos que realmente importam.
Instalação e primeiros passos
Instalar o Docker leva cinco minutos quando se segue o procedimento certo, e uma noite inteira quando se segue o errado. A armadilha mais comum: o pacote docker.io ou docker oferecido pelo gerenciador de pacotes da sua distribuição. Ele existe, instala e funciona mais ou menos — mas costuma estar atrasado em várias versões maiores, às vezes sem o plugin Compose, o que fará você passar vinte minutos tentando entender por que um comando da documentação oficial « não existe » na sua máquina.
A segunda armadilha está em outro lugar e atinge quase todo mundo uma vez: depois de uma instalação perfeitamente bem-sucedida, o primeiro comando responde permission denied while trying to connect to the Docker daemon socket. Isso não é uma falha de instalação. É uma consequência direta da arquitetura vista na lição anterior — o cliente fala com um daemon privilegiado por meio de um socket — e se resolve com uma linha, desde que você entenda qual e por quê.
Esta lição ajuda você a superar esses dois obstáculos de acordo com o seu sistema e depois se concentra no que realmente importa: uma dezena de comandos que cobrem 90 % do trabalho diário. Não uma lista exaustiva de opções — a documentação existe para isso — mas o pequeno conjunto que você digitará todos os dias, com o que acontece por trás de cada um.
No final, você saberá iniciar um contêiner, entrar nele, ler seus logs, entender por que ele parou e recuperar as dezenas de gigabytes que o Docker terá acumulado discretamente no seu disco.
Instalar o Docker Engine no Linux
No Linux, o Docker roda nativamente: sem VM intermediária, sem camada de tradução. É o ambiente mais simples e de melhor desempenho. O método recomendado passa pelo repositório oficial do Docker, o que garante atualizações e a presença dos plugins modernos.
No Debian e no Ubuntu:
# 1. Retirer les paquets anciens ou concurrents, s'ils sont presents
for p in docker.io docker-doc docker-compose podman-docker containerd runc; do
sudo apt-get remove -y "$p"
done
# 2. Ajouter la cle GPG officielle de Docker
sudo apt-get update
sudo apt-get install -y ca-certificates curl
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
# 3. Declarer le depot (le nom de code de la distribution est detecte)
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 4. Installer le moteur ET les plugins (buildx, compose)
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
Os dois últimos pacotes são os que costumam ser esquecidos, e são eles que fornecem docker buildx e docker compose. Para o Debian, substitua as duas ocorrências de ubuntu por debian nas URLs. Para Fedora ou RHEL, o procedimento equivalente usa dnf e o repositório docker-ce.repo; ele está detalhado em docs.docker.com/engine/install.
Resta garantir que o daemon inicie, agora e a cada reinicialização da máquina:
# --now demarre le service, enable l'active au demarrage
sudo systemctl enable --now docker
# Verifier son etat
systemctl status docker --no-pager
Existe uma alternativa para uma máquina descartável ou de teste: o script de instalação oficial.
curl -fsSL https://get.docker.com -o get-docker.sh
# Toujours lire un script avant de l'executer en root
less get-docker.sh
sudo sh get-docker.sh
Ele é prático, mas o próprio Docker o desaconselha explicitamente em produção: ele adivinha a sua distribuição e toma decisões por você, o que não se quer em um servidor que precisa poder ser reconstruído de forma idêntica.
« permission denied »: o grupo docker
Este é o erro que espera todo mundo no primeiro comando:
permission denied while trying to connect to the Docker daemon socket
at unix:///var/run/docker.sock
O daemon escuta em um socket UNIX, /var/run/docker.sock, cujo proprietário é root e o grupo é docker. Seu usuário só pertence a esse grupo se você o tiver adicionado.
# Le groupe existe deja apres l'installation ; la commande est idempotente
sudo groupadd -f docker
# Ajouter votre utilisateur (-a = append, indispensable :
# sans lui, usermod REMPLACE la liste des groupes)
sudo usermod -aG docker "$USER"
# L'appartenance a un groupe est lue a l'ouverture de session.
# Ouvrez une nouvelle session, ou forcez-la pour le shell courant :
newgrp docker
# Verifier
id -nG | tr ' ' '\n' | grep docker
docker run --rm hello-world
Esquecer o -a em usermod -aG é um erro caro: ele remove o usuário de todos os outros grupos, inclusive sudo.
É preciso saber o que essa manipulação realmente autoriza. O daemon roda como root, e a API que ele expõe permite, entre outras coisas, montar qualquer diretório do host em um contêiner. Pertencer ao grupo docker equivale, portanto, na prática, a ter acesso de superusuário à máquina. Isso é aceitável na sua estação de trabalho; em um servidor compartilhado, merece uma decisão consciente. Para os casos em que essa elevação é inaceitável, o Docker oferece um modo rootless que executa o daemon sob a sua própria conta.
macOS e Windows: o desvio por uma máquina virtual
Lembrete da lição 1: uma imagem Linux exige um kernel Linux. Nem o macOS nem o Windows fornecem um. Nesses sistemas, o Docker Desktop instala e gerencia para você uma pequena VM Linux; o cliente docker do seu terminal fala com o daemon que roda dentro dela. Tudo funciona de forma transparente, mas duas consequências se fazem lembrar regularmente: as operações de entrada e saída em arquivos compartilhados com o host são mais lentas, e a memória alocada à VM é um teto global.
No macOS, a instalação é feita pelo pacote .dmg baixado de docs.docker.com/desktop/install/mac-install, ou pelo Homebrew:
brew install --cask docker
# Puis lancer l'application Docker une premiere fois : c'est elle
# qui installe le daemon et demarre la VM.
docker version
Atenção à arquitetura: nos Macs Apple Silicon (M1 e posteriores), o processador é arm64. Uma imagem publicada apenas para amd64 será emulada, lentamente, ou se recusará a iniciar. Se necessário, força-se a arquitetura:
# Voir l'architecture du daemon
docker info --format '{{.Architecture}}'
# Forcer une plateforme, au prix de l'emulation
docker run --rm --platform linux/amd64 alpine:3.20 uname -m
No Windows, a configuração correta é o WSL2 (Windows Subsystem for Linux versão 2), que fornece um kernel Linux de verdade. O antigo modo « Hyper-V » do Docker Desktop deve ser evitado, e o modo « contêineres Windows » atende a uma necessidade diferente (imagens Windows Server).
# Dans PowerShell en administrateur : installe WSL2 et une Ubuntu par defaut
wsl --install
# S'assurer que la version 2 est celle utilisee par defaut
wsl --set-default-version 2
# Verifier : la colonne VERSION doit afficher 2
wsl -l -v
Em seguida, instale o Docker Desktop e ative, nas configurações, em Settings > Resources > WSL Integration, a distribuição que você usa. Assim você poderá digitar seus comandos docker diretamente a partir do shell do Ubuntu.
Uma dica de desempenho que muda tudo no Windows: trabalhe no sistema de arquivos Linux, ou seja, em /home/voce/projetos, e não em /mnt/c/Users/.... Os arquivos montados a partir do disco do Windows atravessam uma camada de tradução; um npm install pode ser dez vezes mais lento ali.
Verificar se a instalação está saudável
Três comandos bastam, e cada um responde a uma pergunta diferente.
# 1. Le client et le daemon se parlent-ils, et en quelle version ?
# Si la section "Server" manque, le daemon est injoignable.
docker version
# 2. Etat detaille : pilote de stockage, nombre de conteneurs, memoire
docker info
# 3. Le chemin complet fonctionne-t-il : pull depuis un registre + execution
docker run --rm hello-world
O terceiro é o verdadeiro teste de ponta a ponta: ele valida a resolução de DNS, o acesso ao registry, a escrita no cache local e a criação de um contêiner. O --rm remove o contêiner assim que ele termina — um reflexo a adquirir para todo contêiner descartável, caso contrário eles se acumulam.
Anatomia do docker run
O docker run é o comando mais usado e o mais denso. Na verdade, ele encadeia três operações: baixar a imagem se ela estiver ausente, criar um contêiner e iniciá-lo.
docker run [OPTIONS] IMAGE [COMMANDE] [ARGUMENTS...]
A ordem não é negociável: o que precede o nome da imagem configura o Docker, o que vem depois é passado ao processo dentro do contêiner. Colocar -p 8080:80 depois do nome da imagem não produz um erro de sintaxe — passa -p 8080:80 como argumento ao programa iniciado, que estranha.
As opções que importam, com o que elas realmente fazem:
docker run \
-d \ # detache : rend le terminal, le conteneur tourne en fond
--name api \ # nom stable, sinon Docker en invente un aleatoire
-p 8080:80 \ # publie le port : 8080 sur l'hote -> 80 dans le conteneur
-e LOG_LEVEL=debug \ # variable d'environnement
-v mes-donnees:/data \ # volume nomme monte sur /data
-w /app \ # repertoire de travail initial
--restart unless-stopped \ # relance apres un crash ou un reboot de l'hote
--memory 512m \ # plafond memoire (cgroups)
nginx:1.27-alpine
Dois modos se opõem e atendem a necessidades distintas. O -d desanexa: é o modo dos serviços. O -it combina -i (manter a entrada padrão aberta) e -t (alocar um pseudo-terminal): é o modo das sessões interativas.
# Une session shell jetable dans une Alpine, supprimee a la sortie
docker run --rm -it alpine:3.20 sh
# Un shell Python temporaire, sans installer Python sur l'hote
docker run --rm -it python:3.12-slim python
# Remplacer la commande par defaut de l'image
docker run --rm nginx:1.27-alpine nginx -v
Esta última linha ilustra uma ideia a reter: o comando declarado na imagem é apenas um valor padrão, que pode ser substituído na inicialização.
O ciclo de vida de um contêiner
Um contêiner passa por estados, e muita confusão vem de uma leitura apressada do docker ps.
docker create
(image) ─────────────────────> created
│ docker start
v
docker stop / le processus finit
exited <─────────────────────── running <──> paused
│ │ (pause/unpause)
│ docker start │ docker restart
│ v
└──> docker rm ──> (disparu) running
# Ne montre QUE les conteneurs en cours d'execution
docker ps
# -a montre aussi les conteneurs arretes. C'est la commande a reflexe
# quand "mon conteneur a disparu" : il est la, en statut Exited.
docker ps -a
# Format personnalise, bien plus lisible que la sortie par defaut
docker ps -a --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
O ponto pouco intuitivo: um contêiner vive tanto quanto seu processo principal (PID 1). Ele não « contém » uma máquina ligada esperando. Se o processo termina, o contêiner passa para Exited, imediatamente.
# Ce conteneur s'arrete instantanement : echo finit son travail.
docker run --name test-court alpine:3.20 echo "bonjour"
docker ps -a --filter name=test-court # Exited (0)
# Celui-la tourne 30 secondes puis sort.
docker run -d --name test-sleep alpine:3.20 sleep 30
Essa é a explicação para o clássico « meu contêiner para sozinho »: a imagem não inicia nenhum serviço duradouro, ou o serviço vai para segundo plano e devolve o controle — o que nunca se deve fazer em um contêiner.
Os comandos de controle:
docker stop api # SIGTERM, puis SIGKILL apres 10 s de grace
docker stop -t 30 api # allonger le delai de grace a 30 s
docker kill api # SIGKILL immediat, aucune chance de finir proprement
docker start api # redemarre un conteneur existant (etat disque conserve)
docker restart api
docker rm api # supprime le conteneur arrete, et sa couche d'ecriture
docker rm -f api # arrete et supprime d'un coup
A diferença entre stop e kill não é cosmética. O stop envia SIGTERM, dando à aplicação tempo para fechar suas conexões e esvaziar seus buffers; o kill corta de imediato, com o risco de corromper dados em escrita. Uma aplicação conteinerizada corretamente deve interceptar o SIGTERM.
Entrar em um contêiner e observá-lo
Quando um serviço não responde, o instinto é olhar por dentro. Três ferramentas, nesta ordem.
Primeiro os logs, pois na maioria das vezes eles bastam. O Docker captura a saída padrão e a saída de erro do processo principal.
docker logs api # tout depuis le demarrage
docker logs -f api # suivre en direct (comme tail -f)
docker logs --tail 50 api # les 50 dernieres lignes
docker logs --since 10m api # les 10 dernieres minutes
docker logs --timestamps api # avec horodatage
Corolário capital: uma aplicação conteinerizada deve escrever seus logs na saída padrão, e não em um arquivo interno. Caso contrário, o docker logs fica vazio e os logs morrem junto com o contêiner.
Depois, abrir um shell em um contêiner em execução:
# bash quand l'image en dispose (Debian, Ubuntu)
docker exec -it api bash
# sh sur les images Alpine et les images minimales : bash n'y est pas
docker exec -it api sh
# Executer une commande unique sans session interactive
docker exec api ls -la /etc/nginx
docker exec api env
Observe bem a distinção: o docker exec adiciona um processo em um contêiner já em execução, enquanto o docker run cria um novo. E tudo o que você modifica durante essa sessão vive na camada de escrita do contêiner: será perdido quando ele for removido. Esse modo serve para diagnosticar, nunca para configurar de forma duradoura.
Por fim, a inspeção e as medições:
# Toda a configuração do contêiner, em JSON
docker inspect api
# Obter um valor específico com um modelo Go
docker inspect --format '{{.State.Status}}' api
docker inspect --format '{{.State.ExitCode}}' api
docker inspect --format '{{range $p, $c := .NetworkSettings.Ports}}{{$p}} {{end}}' api
# Consumo em tempo real (CPU, memória, rede, E/S)
docker stats
# Processos em execução no contêiner
docker top api
# Arquivos modificados em relação à imagem (A adicionado, C alterado, D removido)
docker diff api
# Copiar um arquivo nos dois sentidos
docker cp api:/etc/nginx/nginx.conf ./nginx.conf
docker cp ./nginx.conf api:/etc/nginx/nginx.conf
O código de saída merece atenção: 137 quase sempre significa que o processo recebeu um SIGKILL (128 + 9), frequentemente porque ultrapassou o limite de memória e o kernel o encerrou. É uma informação que nenhuma mensagem de erro da aplicação vai lhe dar.
Limpar: o Docker enche o disco em silêncio
Cada imagem baixada, cada contêiner parado, cada camada intermediária de build permanece no disco. Em uma máquina de desenvolvimento ativa, isso representa muito rapidamente dezenas de gigabytes.
# O balanço: o que o Docker ocupa e o que é recuperável
docker system df
# Detalhe por objeto
docker system df -v
A limpeza é feita em graus crescentes de brutalidade.
# 1. Os contêineres parados
docker container prune
# 2. As imagens sem nome (as "dangling", <none>), produzidas pelos rebuilds
docker image prune
# 3. Os volumes que nenhum contêiner utiliza
# ATENÇÃO: são os seus dados. Verifique antes.
docker volume ls
docker volume prune
# 4. O cache de build, muitas vezes o maior item
docker builder prune
# 5. Tudo de uma vez, incluindo imagens não utilizadas
docker system prune -a
docker system prune -a é o comando que você precisa conhecer e usar com cautela: ele remove todas as imagens que nenhum contêiner utiliza, inclusive aquelas que você vai baixar de novo amanhã. Sem -a, ele se limita aos objetos realmente órfãos.
Algumas combinações práticas, que convém entender antes de colar:
# Parar todos os contêineres em execução (-q retorna apenas os identificadores)
docker stop $(docker ps -q)
# Remover todos os contêineres, inclusive os que estão em execução
docker rm -f $(docker ps -aq)
# Remover as imagens de um repositório específico
docker images --filter reference='mon-app' -q | xargs -r docker rmi
Uma observação para macOS e Windows: o espaço ocupado pela VM do Docker Desktop nem sempre é devolvido ao sistema hospedeiro após um prune. O arquivo de disco da VM permanece dimensionado no seu pico. O Docker Desktop oferece uma ação de recuperação de espaço em suas configurações.
Pontos-chave
- No Linux, instale a partir do repositório oficial do Docker, nunca a partir do pacote da distribuição, e não esqueça de
docker-buildx-pluginedocker-compose-plugin: sem eles,docker composenão existe. - O erro
permission deniedem/var/run/docker.sockse resolve comsudo usermod -aG docker $USER, seguido de uma nova sessão. Saiba que isso equivale a um acesso root à máquina. - No macOS e no Windows, o Docker se apoia em uma VM Linux. No Windows, use o WSL2 e mantenha seus projetos no sistema de arquivos Linux, não em
/mnt/c, sob pena de lentidão significativa. - Um contêiner vive exatamente o tempo de seu processo PID 1. “Ele para sozinho” quase sempre significa que esse processo terminou.
docker ps -amostra os contêineres parados,docker psnão. - O dia a dia cabe em oito comandos:
run,ps -a,logs -f,exec -it,stop,rm,inspect,system df. Adquira o reflexo de usar--rmem todo contêiner descartável. - Monitore o
docker system dfregularmente: imagens, volumes e caches de build enchem um disco sem avisar.
Dica: execute
docker run --rm -it alpine:3.20 she explore livremente. Um contêiner descartável é o ambiente de experimentação mais seguro que existe:exit, e não sobra nada.
Comentários
Os comentários são alimentados pelo GitHub Discussions
Conecte-se com o GitHub para participar da discussão