Imagens Docker
As imagens Docker são como "templates" ou "modelos prontos" usados para criar contêineres. Elas encapsulam tudo o que é necessário para a execução de um aplicativo, garantindo que ele funcione de maneira consistente, independentemente do ambiente onde está sendo executado.
Uma imagem docker é sempre criada a partir de um arquivo chamado Dockerfile
, esse arquivo contém instruções para construir uma imagem Docker. Cada linha do Dockerfile executa uma tarefa, como instalar dependências, copiar arquivos, configurar variáveis e definir o comando principal que será executado no contêiner.
Com o Dockerfile
, podemos apenas criar a imagem com comando docker build
, ou podemos criar a imagem a partir de algum orquestrador, já que eles criam as imagens no momento da execução, como o docker compose, que cria a imagem quando executamos docker compose up caso a imagem não exista.
As imagens Docker são imutáveis, ou seja, depois de criadas, não podem ser alteradas diretamente. Qualquer modificação em uma imagem exige que uma nova imagem seja criada. Existem dois métodos para fazer isso:
Usar um
Dockerfile
: Crie um novo Dockerfile baseado na imagem antiga, faça as alterações necessárias (como instalar pacotes ou adicionar arquivos) e gere uma nova imagem comdocker build
.Usar
docker commit
: Rode um contêiner baseado na imagem antiga, faça alterações manualmente, e então salve o estado do contêiner como uma nova imagem com o comandodocker commit
.
Registry/Docker Hub
Um Registry é, basicamente, um repositório utilizado para armazenar e distribuir imagens Docker. O Docker Hub é uma implementação amplamente utilizada de um registry, funcionando como uma plataforma centralizada para gerenciar imagens Docker. Ele permite que os usuários façam o download de imagens públicas ou enviem suas próprias imagens para compartilhamento e reutilização.
Por padrão, o Docker utiliza o Docker Hub como registry principal, a menos que seja configurado para utilizar outra solução, como um registry privado ou alternativo.
Todas as imagens enviadas para o Docker Hub são públicas por padrão, o que significa que qualquer pessoa pode acessá-las e utilizá-las. Para criar repositórios privados, é necessário um plano pago ou configurações específicas.
Além do Docker Hub, existem várias alternativas de registries que você pode usar para armazenar e distribuir imagens Docker, tanto remotamente quanto localmente. Aqui estão algumas opções:
Alternativas Remotas (SaaS)
Aqui vou citar os registries oferecidos como serviços gerenciados na nuvem.- Amazon Elastic Container Registry (ECR)
- Google Container Registry (GCR)
- Azure Container Registry (ACR)
- GitHub Container Registry (GHCR)
- Quay.io
- Harbor (Hospedado)
Registries Locais (Self-Hosted)
As opções citadas aqui permitem que você configure e gerencie seu próprio registry, ideal para armazenar imagens Docker de forma privada dentro de sua infraestrutura.- Docker Registry (Oficial)
- Harbor
- Artifactory (JFrog)
- GitLab Container Registry
- Nexus Repository (Sonatype)
- Portus
- OCI Distribution (Distribuição OCI Padrão)
Agora vamos ver um passo a passo para autenticar no Docker Hub via linha de comando (CLI), conforme demonstrado na sessão de Introdução ao Docker. Antes de continuar, crie uma conta no docker hub. Após a criação da conta, vamos logar com nossa conta via CLI:
╼ $ docker login
Log in with your Docker ID or email address to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com/ to create one.
You can log in with your password or a Personal Access Token (PAT). Using a limited-scope PAT grants better security and is required for organizations using SSO. Learn more at https://docs.docker.com/go/access-tokens/
Username: fulano
Password: ***************************
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
A credencial fica salva em
/home/fulano/.docker/config.json
.
Não se esqueça de configurar uma credencial para não deixar a senha armazenada em texto puro, como informado na mensagem.
Subindo nosso próprio Registry
Vamos ver um exemplo bem simples de como usar o Docker Registry oficial para implementar nosso próprio registry. Esse procedimento não é recomendado para ambiente de produção.
# Inicie o container do registry:
╼ $ sudo docker run -d -p 5000:5000 --name registry registry:2
# Adicione uma Tag na imagem para apontar para o registry local:
╼ $ sudo docker tag minha-imagem:latest localhost:5000/minha-imagem
# Envie a imagem para o registry:
╼ $ sudo docker push localhost:5000/minha-imagem
# Para baixar a imagem do registry:
╼ $ sudo docker pull localhost:5000/minha-imagem
Tags
As tags em imagens Docker são utilizadas para identificar versões específicas ou variantes de uma imagem. Elas são anexadas aos nomes das imagens para fornecer uma maneira conveniente de especificar uma versão específica ou configuração de uma imagem.
A seguir, alguns exemplos comuns de como as tags podem ser usadas:
<repository>/<image>:<tag>
# repository: O nome do repositório no registry (pode ser omitido para imagens padrão do Docker Hub).
# image: O nome da imagem.
# tag: Um rótulo que indica uma versão ou variação da imagem.
Alguns exemplos reais:
# Nginx na versão 1.25:
nginx:1.25
# Ubuntu na versão 22.04:
ubuntu:22.04
# Ubuntu na última versão:
ubuntu:latest
Lembre-se de nunca usar a tag latest
nas imagens, apenas use quando estiver testando. Usar a tag latest
em produção é considerado uma má prática devido a problemas de previsibilidade, controle e confiabilidade. A tag latest
não é um indicador confiável de uma versão específica. Ela aponta para a última imagem que foi enviada ao repositório, se a imagem no registry for atualizada com uma versão incompatível ou não testada, o ambiente de produção poderá ser afetado.
Quando você usa latest
, qualquer comando que rebaixe a imagem pode pegar uma nova versão inadvertidamente, o que pode causar instabilidade. Isso é especialmente perigoso em pipelines CI/CD ou durante manutenções, onde uma simples atualização do container pode substituir a versão estável com algo não testado.
Aplicando tags
Vamos ver como aplicar uma tag em uma imagem. Para isso a imagem já precisa existir, caso não exista, faça o build da imagem.
# Fazendo o Build de uma imagem e adicionando uma tag (tag é '1.0.0'):
╼ $ sudo docker build -t myapp:1.0.0 .
# Adicionando outra tag na imagem existente (nova tag é 'stable'):
╼ $ sudo docker tag myapp:1.0.0 myapp:stable
# Adicionando duas tags de uma única vez:
╼ $ sudo docker tag myapp:1.0.1 myapp:dev
docker image
O comando docker image
é usado para manipular imagens Docker. As imagens são essenciais no Docker, pois são a base para criar contêineres. Abaixo podemos ver uma tabela com os principais subcomandos do docker image
:
Comando | Descrição |
---|---|
docker image ls | Lista todas as imagens disponíveis no seu sistema. |
docker image pull NAME[:TAG] | Baixa uma imagem específica do Docker Hub ou de outro registro de contêineres para o seu sistema. |
docker image build PATH | Constrói uma nova imagem a partir de um Dockerfile e de um contexto de construção local. |
docker image tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG] | Adiciona uma ou mais tags (rótulos) a uma imagem existente. |
docker image push NAME[:TAG] | Envia uma imagem local para um registro remoto, como o Docker Hub, para que outros usuários possam acessá-la. |
docker image rm IMAGE | Remove uma ou mais imagens do sistema. Você pode usar -f para forçar a remoção mesmo se os contêineres estiverem usando a imagem. |
docker image inspect | Exibe informações detalhadas sobre uma imagem específica, incluindo metadados, camadas e configurações. |
docker image save IMAGE | Salva uma ou mais imagens, compactando a imagem com tar. |
docker image history IMAGE | Exibe o histórico das camadas de uma imagem Docker, mostrando como a imagem foi construída, listando cada instrução do Dockerfile ou comando que gerou as camadas da imagem. Para melhor visualização utilize --no-trunc . |
docker rmi $(docker images -q) | Apaga todas as imagens do host do Docker. |
Agora veremos alguns comandos:
# Listando as imagens que estão no sistema:
╼ $ sudo docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
container3 latest 494e4ccff1a5 About a minute ago 169MB
container2 latest 49d323bcb9d4 2 minutes ago 169MB
teste-apiweb latest 89edc50deb77 20 hours ago 169MB
# Removendo uma image baixada.
╼ $ docker image rm IMAGE_ID
Criando uma nova imagem
Vamos fazer o build de uma imagem, esse será um exemplo muito simples, apenas para exemplificar os comandos.
# Crie o diretório onde vamos colocar o Dockerfile:
╼ $ mkdir /tmp/docker/
# Entre no diretório criado:
╼ $ cd /tmp/docker/
# Criar/editar o arquivo
╼ $ vim /tmp/docker/dockerfile
## Adicione as linhas abaixo no Dockerfile:
FROM debian
RUN /bin/echo "Hello"
# Agora vamos fazer o build da imagem.
## tosko = nome da imagem;
## 1.0 = tag da imagem;
## /tmp/docker/ = Diretório onde está o Dockerfile.
╼ $ sudo docker build -t tosko:1.0 /tmp/docker/
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM debian
---> b5d2d9b1597b
Step 2/2 : RUN /bin/echo "Hello"
---> Running in fe11368daf04
Hello
Removing intermediate container fe11368daf04
---> 36053cf3254f
Successfully built 36053cf3254f
Successfully tagged tosko:1.0
Abordaremos o tema Dockerfile em mais detalhes posteriormente.
Imagens mais usadas
Algumas imagens Docker são amplamente utilizadas por sua versatilidade, eficiência e adoção em ambientes de produção. Entre as mais populares estão distribuições minimalistas, imagens base para frameworks, linguagens de programação, servidores e bancos de dados. Abaixo podemos ver algumas das principais imagens.
Alpine Linux
O Alpine Linux é uma distribuição Linux ultraleve e minimalista, projetada para ser extremamente eficiente em termos de recursos. Com tamanho pequeno (cerca de 5 MB) o torna uma escolha popular para ambientes de alta performance e recursos limitados, como containers Docker e sistemas embarcados.
Por ser uma imagem pequena, o tempo de download e implantação da imagem é muito rápido. Por ser minimalista, reduz a superfície de ataque ao incluir apenas os componentes essenciais do Linux. Essa combinação de desempenho, simplicidade e segurança faz do Alpine Linux uma excelente escolha tanto para containers Docker quanto para sistemas que exigem eficiência máxima e isso mostra porque se tornou uma imagem tão popular.
O gerenciador de pacotes do Alpine Linux é o apk, que significa Alpine Package Keeper. Ele é um gerenciador de pacotes leve, rápido e eficiente, projetado para atender às necessidades minimalistas do Alpine Linux. O apk
permite instalar, remover e atualizar pacotes com facilidade.
Vou descrever um pouco do uso desse gerenciador, já que ele poderá ser útil caso você queira construir alguma imagem usando o Alpine como base.
# Atualizar os repositórios:
apk update
# Atualizar todos os pacotes instalados:
apk upgrade
# Pesquisar pacotes disponíveis nos repositórios:
apk search <nome-do-pacote>
# Listar todos os pacotes instalados:
apk info
# Obter informações detalhadas sobre um pacote específico:
apk info <nome-do-pacote>
# Instalar um pacote específico:
apk add <nome-do-pacote>
# Reinstalar um pacote:
apk fix <nome-do-pacote>
# Remover um pacote instalado:
apk del <nome-do-pacote>