Contenido

Tutorial de Docker Hub: publica imágenes en Docker Hub y en un registro privado

Para ejecutar en un servidor o compartir con tu equipo una imagen que has creado en tu ordenador, tienes que publicarla en un Registry. Docker Hub es el más utilizado; también se usan GitHub Container Registry (ghcr.io) y los registros de las plataformas en la nube.

El nombre de la imagen determina dónde se publica

Al publicar, Docker usa el nombre de la imagen para decidir a qué Registry y cuenta enviarla (consulta las reglas de nomenclatura en Imágenes de Docker):

NombreDestino de la publicación
yourname/mysite:1.0.0La cuenta yourname de Docker Hub
ghcr.io/yourname/mysite:1.0.0GitHub Container Registry
localhost:5000/mysite:1.0.0El Registry privado del puerto local 5000

Por eso, antes de publicar, usa docker tag para asignar a la imagen el nombre correspondiente.

Qué ocurre si publicas sin iniciar sesión

Primero, veamos qué sucede al publicar directamente en Docker Hub sin haber iniciado sesión:

$ 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: Docker Hub ha rechazado la solicitud porque no has iniciado sesión y yourname tampoco es tu cuenta. A continuación, regístrate, inicia sesión y publica la imagen.

Publicar en Docker Hub

1. Crea una cuenta

Regístrate en el sitio oficial de Docker. Puedes usar tu correo electrónico o una cuenta de Google o GitHub. Username será el espacio de nombres que aparecerá al principio del nombre de la imagen:

Página de registro de una cuenta de Docker
Página de registro de una cuenta de Docker (captura de octubre de 2026)

2. Crea un token de acceso e inicia sesión

Se recomienda crear un Personal Access Token en la configuración de la cuenta de Docker Hub y usarlo en lugar de la contraseña para iniciar sesión. También puedes limitar sus permisos, por ejemplo, permitir lectura y escritura, pero no eliminación.

docker login -u yourname

Cuando se te solicite, pega el token de acceso. Si el inicio de sesión se completa correctamente, aparecerá Login Succeeded.

3. Crea un repositorio (opcional)

Docker Hub crea el repositorio automáticamente la primera vez que publicas. Si quieres configurar una descripción de antemano o hacerlo privado, selecciona Create repository en el sitio web de Docker Hub:

Pantalla para crear un repositorio en Docker Hub
Pantalla Create repository de Docker Hub: introduce un nombre y una descripción y elige Public o Private. Imagen: documentación oficial de Docker (Apache-2.0)

Los repositorios de Docker Hub son públicos de forma predeterminada. El plan gratuito limita la cantidad de repositorios privados; consulta los planes de Docker Hub para obtener más información.

4. Etiqueta y publica la imagen

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

Puedes usar -t varias veces para asignar varios nombres en una sola operación. También puedes publicar todos los tags de una vez con docker push --all-tags yourname/mysite. El formato de salida es igual al del ejemplo práctico de la sección «Configura tu propio Registry privado».

Después de publicar, en la pestaña Tags del repositorio de Docker Hub puedes ver cada tag y el comando que otras personas usarán para descargarlo:

Pestaña Tags de un repositorio de Docker Hub
Pestaña Tags de un repositorio de Docker Hub; a la derecha aparece el comando docker pull. Imagen: documentación oficial de Docker (Apache-2.0)

5. Usa la imagen en otra máquina

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

Configura tu propio Registry privado: publicación y descarga en la práctica

Docker ofrece la imagen registry, con la que puedes poner en marcha rápidamente un Registry privado. Es la forma más sencilla de practicar la «publicación» por tu cuenta y no necesitas ninguna cuenta:

$ 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

Etiqueta y publica la imagen:

$ 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
  • En la primera publicación, cada capa muestra Pushed (publicada).
  • Al publicar latest con --all-tags, todas las capas muestran Layer already exists: 1.0.0 y latest son la misma imagen y esas capas ya están en el Registry, así que no hace falta volver a subirlas.
  • El último mensaje Info es un aviso de Docker 29: solo se había descargado localmente nginx para la plataforma linux/amd64, así que solo se publicó esa plataforma. Para publicar imágenes multiplataforma, consulta Imágenes multiplataforma.

Comprueba el contenido con la API de Registry:

$ 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"]}

Elimina las versiones locales y vuelve a descargarlas de tu 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

Este Registry no tiene autenticación ni HTTPS, así que solo sirve para hacer pruebas en tu ordenador o en una red interna. Puedes usar directamente el Registry de localhost; Docker rechazará los Registry HTTP de otras direcciones, a menos que configures insecure-registries. Para usarlo en producción, añade TLS y autenticación o usa un Registry de un proveedor de nube, como AWS ECR, Google Artifact Registry o Azure Container Registry.

Publica en GitHub Container Registry (ghcr.io)

Es una opción adecuada para los proyectos cuyo código está en GitHub. Primero, crea en GitHub un Personal Access Token con el permiso write:packages y luego ejecuta:

echo $GITHUB_TOKEN | docker login ghcr.io -u tu-cuenta-de-GitHub --password-stdin
docker tag mysite ghcr.io/tu-cuenta/mysite:1.0.0
docker push ghcr.io/tu-cuenta/mysite:1.0.0

--password-stdin lee la contraseña desde la entrada estándar y evita que aparezca en el historial de comandos.

Recomendaciones para nombrar tags

PrácticaEjemploDescripción
Versionado semántico1.4.2, 1.4, 1Publica varios niveles para que cada usuario elija cuánto actualizar
Commit de Gitsha-3f2a1c9Permite asociar cada imagen con el código exacto
Entornostaging, productionTags mutables que apuntan a la versión desplegada actualmente
latestlatestEs práctico para probar, pero no dependas de él en producción

Para desplegar en producción, usa un número de versión fijo. Así sabrás qué versión se ejecuta en el servidor y podrás volver rápidamente a la anterior (consulta Despliegue en un servidor en la nube).

Cierra sesión y gestiona las credenciales

docker logout
docker logout ghcr.io

La información de inicio de sesión se guarda de forma predeterminada en ~/.docker/config.json. Docker Desktop usa el gestor de credenciales del sistema operativo (Administrador de credenciales de Windows o Llavero de macOS), que ofrece más seguridad.

Resumen

  • El prefijo del nombre de una imagen determina a qué Registry se publica.
  • Inicia sesión con un token de acceso (Access Token), no con la contraseña de la cuenta.
  • Usa docker tag para añadir el nombre de destino y luego docker push.
  • En producción, usa un tag con un número de versión fijo y no dependas de latest.

Ejercicios

Ejercicio 1: Pon en marcha un Registry local (registry:3, en el puerto 5000) siguiendo los pasos de este capítulo. Publica alpine:3.23, elimina la copia local y vuelve a descargarla.

Respuesta
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

Preguntas frecuentes

¿Aparece «denied: requested access to the resource is denied» al publicar?

Suele ocurrir porque no has iniciado sesión o porque la parte de la cuenta en el nombre de la imagen no es tu cuenta. Usa el formato tu-cuenta/repositorio:tag e inicia sesión con docker login antes de publicar.

¿Hay que pagar por los repositorios privados de Docker Hub?

Las cuentas gratuitas pueden crear un número limitado de repositorios privados. Consulta las condiciones de los planes oficiales de Docker Hub para conocer los límites vigentes. También puedes usar GitHub Container Registry.

¿Se puede publicar automáticamente?

Sí. Puedes usar GitHub Actions para construir y publicar automáticamente cada vez que publiques código o crees un tag de versión. Consulta [Compilación automática con GitHub Actions](/es/docker/ci-cd/).

Actualizado 14 de octubre de 2026