Conteúdo

Tutorial de Docker Hub e Registry privado: publique e compartilhe imagens

Para executar em um servidor ou compartilhar com a equipe uma imagem que você criou no seu computador, é preciso publicá-la em um Registry. O mais usado é o Docker Hub, seguido pelo GitHub Container Registry (ghcr.io) e pelos Registries de plataformas de nuvem.

O nome da imagem determina o destino da publicação

Ao publicar, o Docker usa o nome da imagem para determinar em qual Registry e conta ela será enviada (veja as regras de nomenclatura em Imagens):

NomeDestino
yourname/mysite:1.0.0Conta yourname no Docker Hub
ghcr.io/yourname/mysite:1.0.0GitHub Container Registry
localhost:5000/mysite:1.0.0Registry privado na porta 5000 local

Por isso, antes de publicar, use docker tag para dar à imagem o nome correspondente.

O que acontece se você publicar sem fazer login

Veja primeiro o resultado de publicar diretamente no Docker Hub sem fazer login:

$ docker tag nginx:1.30 yourname/mysite:1.0.0

$ docker push yourname/mysite:1.0.0
The push refers to repository [docker.io/yourname/mysite]
f4616bb1be1c: Unavailable
f1a6a629b824: Unavailable
3d774efa34e3: Unavailable
ecc510c1e359: Unavailable
push access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed

push access denied ... authorization failed: o Docker Hub recusou a solicitação porque você não fez login e yourname também não é a sua conta. A seguir, faça o cadastro, login e publicação.

Publicar no Docker Hub

1. Crie uma conta

Cadastre-se no site oficial do Docker. Você pode usar seu e-mail ou entrar diretamente com uma conta Google ou GitHub. O Username será o namespace no início do nome da imagem:

Página de cadastro de conta do Docker
Página de cadastro de conta do Docker (captura de outubro de 2026)

2. Crie um token de acesso e faça login

Recomendamos criar um Personal Access Token nas configurações da sua conta do Docker Hub. Use-o no lugar da senha para fazer login e limitar permissões, por exemplo, permitindo leitura e gravação, mas não exclusão.

docker login -u yourname

Quando solicitado, cole o token de acesso. Se o login for bem-sucedido, será exibido Login Succeeded.

3. Crie um repositório (opcional)

Na primeira publicação, o Docker Hub cria o repositório automaticamente. Para configurar uma descrição antes ou torná-lo privado, clique em Create repository no site do Docker Hub:

Tela de criação de repositório no Docker Hub
Tela Create repository do Docker Hub: digite um nome, uma descrição e escolha Public ou Private. Imagem: documentação oficial do Docker (Apache-2.0)

Por padrão, os repositórios no Docker Hub são públicos. O plano gratuito limita a quantidade de repositórios privados. Consulte os planos do Docker Hub para mais informações.

4. Marque e publique

docker build -t yourname/mysite:1.0.0 -t yourname/mysite:latest .
docker push yourname/mysite:1.0.0
docker push yourname/mysite:latest

Você pode usar -t várias vezes para atribuir vários nomes de uma só vez. Também pode executar docker push --all-tags yourname/mysite para publicar todas as tags de uma vez. A saída é igual à do exemplo prático na seção “Registry privado próprio”.

Depois de publicar, acesse a aba Tags do repositório no Docker Hub para ver cada tag e o comando que outras pessoas podem usar para baixar a imagem:

Aba Tags de um repositório do Docker Hub
Aba Tags de um repositório do Docker Hub, com o comando docker pull à direita. Imagem: documentação oficial do Docker (Apache-2.0)

5. Use em outras máquinas

docker pull yourname/mysite:1.0.0
docker run -d -p 8080:80 yourname/mysite:1.0.0

Registry privado próprio: exemplo prático de publicação e download

O Docker fornece a imagem registry, que permite configurar rapidamente um Registry privado. Essa também é a maneira mais fácil de praticar a publicação, sem precisar de nenhuma conta:

$ docker run -d -p 5000:5000 --restart unless-stopped -v registry-data:/var/lib/registry --name registry registry:3
Unable to find image 'registry:3' locally
3: Pulling from library/registry
e2de96513ba9: Already exists
90764beeca7f: Pull complete
8dc2188d2a74: Pull complete
783ed5b12fca: Pull complete
2aef3a8beb68: Pull complete
Digest: sha256:ddf754342cfc8acc51a56d5d0ab6af06826461864460636d8bd5c546dab2a7b8
Status: Downloaded newer image for registry:3
c5d02febbf0fd6d8c17e6818990adb28fd0a97c380a0d4c0a58ec793f685e4a0

Marque a imagem e publique-a:

$ docker tag nginx:1.30 localhost:5000/mysite:1.0.0

$ docker tag nginx:1.30 localhost:5000/mysite:latest

$ docker push localhost:5000/mysite:1.0.0
The push refers to repository [localhost:5000/mysite]
3d774efa34e3: Pushed
ecc510c1e359: Pushed
f4616bb1be1c: Pushed
f1a6a629b824: Pushed
cb44c3fe542b: Pushed
121907e00c1c: Pushed
220a6ac36368: Pushed
1.0.0: digest: sha256:6e2a172ae5503c0df64cd3294b57c86394ced402016a8cc45436086fa51f5d02 size: 2288

i Info → Not all multiplatform-content is present and only the available single-platform image was pushed
         sha256:9bf97bd7714f5e24c1ccd545ecb9eb5435cb6d109c97cebb15e7e455e0239edb -> sha256:6e2a172ae5503c0df64cd3294b57c86394ced402016a8cc45436086fa51f5d02

$ docker push --all-tags localhost:5000/mysite
The push refers to repository [localhost:5000/mysite]
220a6ac36368: Layer already exists
3d774efa34e3: Layer already exists
ecc510c1e359: Layer already exists
f4616bb1be1c: Layer already exists
f1a6a629b824: Layer already exists
cb44c3fe542b: Layer already exists
121907e00c1c: Layer already exists
1.0.0: digest: sha256:6e2a172ae5503c0df64cd3294b57c86394ced402016a8cc45436086fa51f5d02 size: 2288
220a6ac36368: Layer already exists
3d774efa34e3: Layer already exists
ecc510c1e359: Layer already exists
f4616bb1be1c: Layer already exists
f1a6a629b824: Layer already exists
cb44c3fe542b: Layer already exists
121907e00c1c: Layer already exists
latest: digest: sha256:6e2a172ae5503c0df64cd3294b57c86394ced402016a8cc45436086fa51f5d02 size: 2288

i Info → Not all multiplatform-content is present and only the available single-platform image was pushed
         sha256:9bf97bd7714f5e24c1ccd545ecb9eb5435cb6d109c97cebb15e7e455e0239edb -> sha256:6e2a172ae5503c0df64cd3294b57c86394ced402016a8cc45436086fa51f5d02

i Info → Not all multiplatform-content is present and only the available single-platform image was pushed
         sha256:9bf97bd7714f5e24c1ccd545ecb9eb5435cb6d109c97cebb15e7e455e0239edb -> sha256:6e2a172ae5503c0df64cd3294b57c86394ced402016a8cc45436086fa51f5d02
  • Na primeira publicação, cada camada aparece como Pushed (enviada).
  • Ao publicar latest com --all-tags, todas as camadas aparecem como Layer already exists: 1.0.0 e latest são a mesma imagem, e essas camadas já estão no Registry, então não precisam ser enviadas novamente.
  • A mensagem final Info é um aviso do Docker 29: apenas a plataforma linux/amd64 do nginx foi baixada localmente, então somente essa plataforma foi publicada. Para publicar imagens multiplataforma, veja Imagens multiplataforma.

Use a API do Registry para confirmar o conteúdo:

$ curl -s http://localhost:5000/v2/_catalog
{"repositories":["mysite"]}

$ curl -s http://localhost:5000/v2/mysite/tags/list
{"name":"mysite","tags":["1.0.0","latest"]}

Remova a versão local e baixe-a novamente do seu Registry:

$ docker rmi localhost:5000/mysite:1.0.0 localhost:5000/mysite:latest
Untagged: localhost:5000/mysite:1.0.0
Untagged: localhost:5000/mysite:latest

$ docker pull localhost:5000/mysite:1.0.0
1.0.0: Pulling from mysite
Digest: sha256:6e2a172ae5503c0df64cd3294b57c86394ced402016a8cc45436086fa51f5d02
Status: Downloaded newer image for localhost:5000/mysite:1.0.0
localhost:5000/mysite:1.0.0

Esse Registry não tem autenticação de conta nem HTTPS e só serve para testes locais ou em uma rede interna. Você pode usar diretamente o Registry em localhost; o Docker rejeita Registries HTTP em outros endereços, a menos que você configure insecure-registries. Para uso em produção, configure TLS e autenticação ou use um Registry fornecido por uma plataforma de nuvem, como AWS ECR, Google Artifact Registry ou Azure Container Registry.

Publicar no GitHub Container Registry (ghcr.io)

Essa opção é adequada para projetos cujo código está no GitHub. Primeiro, crie no GitHub um Personal Access Token com a permissão write:packages. Em seguida:

echo $GITHUB_TOKEN | docker login ghcr.io -u suaContaGitHub --password-stdin
docker tag mysite ghcr.io/sua-conta/mysite:1.0.0
docker push ghcr.io/sua-conta/mysite:1.0.0

--password-stdin lê a senha da entrada padrão e evita que ela apareça no histórico de comandos.

Sugestões para nomear tags

PráticaExemploDescrição
Versionamento semântico1.4.2, 1.4, 1Publique vários níveis para que os usuários escolham a abrangência da atualização
Commit do Gitsha-3f2a1c9Cada imagem pode ser associada ao código exato
Ambientestaging, productionTags mutáveis que apontam para a versão implantada no momento
latestlatestPrática para testes, mas não dependa dela em produção

Em implantações de produção, use um número de versão fixo. Assim, você sabe qual versão está em execução no servidor e pode voltar rapidamente à anterior (veja Implantar em um servidor na nuvem).

Logout e credenciais

docker logout
docker logout ghcr.io

As informações de login são armazenadas por padrão em ~/.docker/config.json. O Docker Desktop usa o gerenciador de credenciais do sistema operacional (Gerenciador de Credenciais do Windows ou Chaves do macOS), que oferece mais segurança.

Resumo

  • O prefixo do nome da imagem determina em qual Registry ela será publicada.
  • Use um token de acesso (Access Token) para fazer login, não a senha da conta.
  • Adicione o nome de destino com docker tag e, em seguida, execute docker push.
  • Em produção, use uma tag com número de versão fixo e não dependa de latest.

Exercícios

Exercício 1: usando o método deste capítulo, inicie um Registry local (registry:3, na porta 5000), publique alpine:3.23, remova a cópia local e baixe-a novamente.

Resposta
docker run -d -p 5000:5000 --name registry registry:3
docker tag alpine:3.23 localhost:5000/alpine:3.23
docker push localhost:5000/alpine:3.23
docker rmi localhost:5000/alpine:3.23
docker pull localhost:5000/alpine:3.23

Perguntas frequentes

Aparece denied: requested access to the resource is denied ao publicar?

Geralmente, você não fez login ou a parte do nome da imagem que indica a conta não é a sua. Use sua-conta/repositorio:tag e execute docker login antes.

É preciso pagar pelos repositórios privados do Docker Hub?

Contas gratuitas podem criar alguns repositórios privados. Consulte os planos oficiais do Docker Hub para ver os limites e a quantidade. Você também pode usar o GitHub Container Registry.

É possível publicar automaticamente?

Sim. Com o GitHub Actions, você pode construir a imagem e publicá-la automaticamente sempre que enviar código ou criar uma tag de versão. Veja [Build automático com GitHub Actions](/pt/docker/ci-cd/).

Atualizado 14 de outubro de 2026