Docker: introdução
Nesta aula, você aprenderá os conceitos fundamentais do Docker, incluindo a diferença entre imagens e containers, o comando docker run, o ciclo de vida de um container e os comandos básicos para gerenciá-los. Ao final, você terá uma base sólida para começar a usar Docker no seu fluxo de trabalho DevOps.
O Docker revolucionou a forma como desenvolvemos, empacotamos e executamos aplicações. Ele permite que você empacote uma aplicação e todas as suas dependências em um artefato padronizado chamado imagem, que pode ser executado de forma isolada em qualquer ambiente que tenha o Docker instalado. Nesta aula, vamos explorar os conceitos centrais do Docker: imagens e containers, o comando docker run, o ciclo de vida de um container e os comandos básicos para gerenciar essas entidades. Ao final, você estará apto a executar seus primeiros containers e entender como o Docker se encaixa em práticas de DevOps, como integração contínua e entrega contínua.
Antes de mergulharmos nos detalhes, é importante entender que o Docker utiliza uma arquitetura cliente-servidor. O cliente Docker (a CLI) se comunica com o daemon Docker (o servidor) que é responsável por construir, executar e distribuir os containers. Essa separação permite que você controle o Docker remotamente, mas no nosso dia a dia, usamos a CLI para interagir com o daemon local.
Imagens e containers
No Docker, uma imagem é um pacote imutável que contém tudo o que é necessário para executar uma aplicação: código, runtime, bibliotecas, variáveis de ambiente e configurações. As imagens são construídas a partir de um Dockerfile, que é um arquivo de texto com instruções para criar a imagem. Elas são armazenadas em registries, como o Docker Hub, e podem ser versionadas e compartilhadas. Uma imagem é como uma classe em programação: define o modelo.
Um container, por sua vez, é uma instância executável de uma imagem. Você pode criar, iniciar, parar, mover ou excluir um container. Ele é isolado do host e de outros containers, mas pode ser conectado a redes e volumes. Continuando a analogia, um container é como um objeto criado a partir da classe: é a materialização da imagem em execução. Múltiplos containers podem ser criados a partir da mesma imagem, cada um com seu próprio sistema de arquivos e configurações.
Vamos ver como listar imagens e containers no seu sistema:
# Listar imagens locais
docker images
# Listar containers em execução
docker ps
# Listar todos os containers (incluindo parados)
docker ps -a
No início, você verá que não há imagens locais (a menos que já tenha usado o Docker). Para obter uma imagem, você pode usar o comando docker pull, que baixa uma imagem de um registry.
# Baixar a imagem do Ubuntu mais recente
docker pull ubuntu:latest
Depois de baixada, a imagem fica disponível localmente e pode ser usada para criar containers.
docker run
O comando docker run é o comando mais importante do Docker, pois ele cria e inicia um container a partir de uma imagem. Sua sintaxe básica é:
docker run [OPÇÕES] IMAGEM [COMANDO] [ARG...]
Quando você executa docker run, o Docker verifica se a imagem existe localmente; se não, ele tenta baixá-la do registry padrão (Docker Hub). Em seguida, ele cria um container a partir dessa imagem e o inicia. Se você especificar um comando, ele será executado dentro do container; caso contrário, o comando padrão definido na imagem será usado.
Vamos executar nosso primeiro container usando a imagem hello-world:
docker run hello-world
Esse comando baixa a imagem hello-world (se necessário) e executa um container que imprime uma mensagem de boas-vindas e sai. O container é criado, executa o comando e termina. Ele não fica em execução.
Para executar um container interativo, como um shell, usamos as opções -it (interativo + TTY). Por exemplo, para abrir um shell bash dentro de um container Ubuntu:
docker run -it ubuntu:latest bash
Ao executar esse comando, você estará dentro do container com um prompt bash. Digite exit para sair e o container será encerrado.
Outras opções comuns do docker run incluem:
--name: atribui um nome ao container (ex.:--name meu-container).-d(detached): executa o container em segundo plano, retornando o ID do container.-p: publica uma porta do container para o host (ex.:-p 8080:80).-v: monta um volume (ex.:-v /host/path:/container/path).--rm: remove automaticamente o container quando ele for encerrado.
Exemplo de execução de um servidor web Nginx em segundo plano:
docker run -d --name meu-nginx -p 8080:80 nginx:latest
Esse comando baixa a imagem do Nginx, cria um container chamado meu-nginx, o executa em segundo plano e mapeia a porta 80 do container para a porta 8080 do host. Agora você pode acessar http://localhost:8080.
Ciclo de vida
O ciclo de vida de um container pode ser dividido em várias fases: criação, início, execução, pausa, parada e remoção. O Docker fornece comandos para gerenciar cada uma dessas fases.
Ao usar docker run, você cria e inicia o container de uma só vez. Mas também é possível criar um container sem iniciá-lo usando docker create. Isso é útil quando você quer preparar o container com antecedência e iniciá-lo depois.
# Criar um container sem iniciar
docker create --name meu-container ubuntu:latest
# Iniciar o container
docker start meu-container
Quando um container está em execução, você pode pausá-lo (congelando todos os processos) usando docker pause, e retomá-lo com docker unpause. Isso é diferente de parar o container, que encerra os processos.
# Pausar um container
docker pause meu-container
# Retomar um container pausado
docker unpause meu-container
Para parar um container, usamos docker stop, que envia um sinal SIGTERM e, após um período de graça, SIGKILL. Você pode especificar o tempo de espera com a opção -t. Já o comando docker kill envia SIGKILL imediatamente.
# Parar um container de forma graciosa (padrão 10 segundos)
docker stop meu-container
# Parar imediatamente
docker kill meu-container
Depois que o container está parado, ele ainda existe no sistema e pode ser reiniciado com docker start. Para remover definitivamente um container, use docker rm. Você pode remover containers parados ou forçar a remoção de containers em execução com a opção -f.
# Remover um container parado
docker rm meu-container
# Forçar a remoção de um container em execução
docker rm -f meu-container
O comando docker run com a opção --rm automatiza a remoção: quando o container é encerrado, ele é removido automaticamente. Isso é útil para containers temporários.
Vamos visualizar o ciclo de vida com um diagrama em texto:
+-----------+ docker create +------------+ docker start +------------+
| Nada | -----------------> | Criado | ----------------> | Rodando |
+-----------+ +------------+ +------------+
^ | |
| | docker stop | docker stop
| v v
| +------------+ +------------+
+--------------------------- | Parado | <---------------- | Parando |
+------------+ +------------+
Entender esse ciclo é essencial para gerenciar adequadamente seus containers em produção e em desenvolvimento.
Comandos básicos
Além dos comandos de ciclo de vida, existem outros comandos que você usará constantemente. Vamos listar os mais importantes:
docker ps: lista containers em execução (use-apara incluir parados).docker images: lista imagens locais.docker pull: baixa uma imagem do registry.docker push: envia uma imagem para o registry.docker exec: executa um comando dentro de um container em execução.docker logs: exibe os logs de um container.docker inspect: mostra informações detalhadas sobre um container ou imagem.docker rm: remove um ou mais containers.docker rmi: remove uma ou mais imagens.docker build: constrói uma imagem a partir de um Dockerfile.
Vamos ver alguns exemplos práticos:
# Executar um comando dentro de um container em execução
docker exec -it meu-nginx bash
# Ver os logs de um container
docker logs meu-nginx
# Inspecionar um container (ex.: ver IP, portas, etc.)
docker inspect meu-nginx
# Remover uma imagem local
docker rmi ubuntu:latest
O comando docker exec é particularmente útil para depuração: você pode entrar em um container em execução e inspecionar o ambiente, processos, arquivos, etc. A opção -it é necessária para interatividade.
Outro comando útil é docker system prune, que limpa recursos não utilizados (containers parados, redes não usadas, imagens pendentes, etc.). Isso ajuda a liberar espaço em disco.
# Limpar recursos não utilizados
docker system prune
Lembre-se de que o Docker possui uma vasta documentação e que esses comandos são apenas a ponta do iceberg. Conforme avançamos, você aprenderá a criar suas próprias imagens com Dockerfile, usar Docker Compose para orquestrar múltiplos containers e integrar o Docker em pipelines de CI/CD.
Boas práticas
Ao trabalhar com Docker, siga estas boas práticas para evitar problemas:
- Sempre nomeie seus containers (
--name) para facilitar a identificação. - Use a opção
--rmpara containers temporários, evitando acúmulo de containers parados. - Prefira usar imagens oficiais e com tags específicas, em vez de
latest, para garantir reprodutibilidade. - Evite executar containers como root; crie usuários não privilegiados no Dockerfile.
- Mantenha o Docker atualizado e execute
docker system pruneperiodicamente para limpar resíduos.
Referências
- Documentação oficial do Docker: Get Started
- Referência do comando docker run
- Referência do comando docker ps
- Referência do comando docker exec
- Docker Hub
- Dockerfile reference
- Blog oficial do Docker
Exercícios
- Qual é a diferença entre uma imagem e um container no Docker? Explique com suas palavras e dê um exemplo de uso de cada um.
- Execute o comando
docker run -d --name meu-nginx -p 8080:80 nginx:lateste explique o que cada parte do comando faz. - Quais são os principais comandos para gerenciar o ciclo de vida de um container? Liste e descreva brevemente cada um.
- Você precisa executar um comando dentro de um container que já está em execução. Qual comando você usaria e por quê?
- Como você faria para remover todos os containers parados e imagens não utilizadas de uma vez? Cite o comando e explique sua função.
ubuntu define o sistema base, e quando você executa docker run ubuntu, você cria um container a partir dessa imagem, que pode ser iniciado, parado, etc.
docker run cria e inicia um container. A opção -d executa em segundo plano (detached). --name meu-nginx nomeia o container como meu-nginx. -p 8080:80 publica a porta 80 do container na porta 8080 do host. nginx:latest é a imagem usada (a tag latest indica a versão mais recente).
docker create (cria um container), docker start (inicia um container existente), docker stop (para um container graciosamente), docker kill (força a parada), docker pause (pausa processos), docker unpause (retoma), docker rm (remove um container parado). Também o docker run combina criação e início.
docker exec -it <container> <comando>. Por exemplo, docker exec -it meu-nginx bash para abrir um shell interativo. O -it permite interação e alocação de terminal. Isso é útil para depuração, inspeção de arquivos, etc.
docker system prune remove containers parados, redes não utilizadas, imagens pendentes e caches de build. Para remover também imagens não utilizadas (dangling), pode-se usar docker system prune -a. Ele ajuda a liberar espaço em disco.