example-projects/reference/docker/08_registries.md

5.2 KiB

Lesson 08: Registries — Pulling and Pushing Images

A registry is a server that stores images. So far, every time you typed docker run ubuntu, Docker silently pulled the image from a registry — by default, Docker Hub (https://hub.docker.com/).

Registries are how an image you build on your laptop gets onto a server, or into a colleague's hands.

Pulling explicitly

docker run pulls if needed, but you can also pull on its own:

docker pull postgres:16

Useful when you want to grab images ahead of time (before a flight, before a workshop, etc.) without running them.

Where images live in image names

The full form of an image reference is:

<registry-host>/<namespace>/<repository>:<tag>

Some examples expanded:

  • ubuntudocker.io/library/ubuntu:latest (Docker Hub's "official" images live under the library namespace, and the registry/tag are filled in by default.)
  • python:3.12-slimdocker.io/library/python:3.12-slim.
  • ghcr.io/myname/myproject:v1 → an image hosted on GitHub Container Registry, under your account, version v1.
  • registry.example.com/team/service:1.4 → an image in some company's private registry.

If the registry isn't specified, Docker assumes docker.io (Docker Hub).

Hosted registry options (and the FOSS take)

You have choices about where your images live. None of them locks you in — you can move images between registries with docker pull and docker push.

  • Docker Hub — the default. Free for public images. Has rate limits on anonymous pulls (a real annoyance for CI, less so for personal use).
  • GitHub Container Registry (ghcr.io) — free for public images, integrates with your GitHub account, no pull rate limit. A good choice if you already use GitHub.
  • GitLab Container Registry — built into GitLab projects.
  • Self-hosted — the reference Docker registry is itself open source. docker run -d -p 5000:5000 registry:2 and you have your own registry running on your machine, no third party involved. Useful if you want full ownership of your images or you're working offline.

Pushing your own image

  1. Create an account on whichever registry you want to use. For Docker Hub, sign up at https://hub.docker.com/. For GHCR, you already have one (your GitHub account).

  2. Log in from the command line:

    docker login                          # Docker Hub
    docker login ghcr.io                  # GitHub Container Registry
    

    You'll be prompted for a username and either a password or a personal access token (recommended; treat it like a password and store it carefully).

  3. Tag your image with the destination address. Suppose you built my-app in lesson 05 and your Docker Hub username is yourname:

    docker tag my-app yourname/my-app:1.0
    

    docker tag doesn't copy the image — it just adds another name pointing at the same content. Now docker images shows both my-app and yourname/my-app:1.0.

  4. Push it:

    docker push yourname/my-app:1.0
    

    Docker uploads it layer by layer to the registry.

  5. Confirm: anyone (or you, from a different machine) can now run:

    docker pull yourname/my-app:1.0
    docker run yourname/my-app:1.0
    

That's the whole flow. Tag, push, pull, run.

Tags as versions

Tags are how you publish multiple versions of the same image. Convention is to:

  • Tag specific releases: yourname/my-app:1.0, yourname/my-app:1.1, …
  • Also tag the most recent as :latest so people who don't specify a tag get something reasonable.
docker tag yourname/my-app:1.0 yourname/my-app:latest
docker push yourname/my-app:latest

:latest is a convention, not magic. It's just a tag named "latest", and you have to explicitly point it at whatever you want to be "latest".

Public vs private

By default Docker Hub repositories are public. If you want a private one, you set that on the registry's website (Docker Hub has free private repos with limits; GHCR private images are free with reasonable limits tied to your GitHub plan). Pushing to a private repo works exactly the same as pushing to a public one — the only difference is who can pull.

A small note on supply-chain caution

Anyone can publish an image to Docker Hub. When you run docker run somebody/cool-thing, you're trusting that "somebody" to not have put anything malicious in there. Use your judgment:

  • Official images (the ones in the library namespace — python, postgres, nginx, ubuntu, etc.) are maintained by the projects themselves and are pretty trustworthy.
  • Verified publisher images on Docker Hub are vetted by Docker.
  • Random images from random accounts are the same risk as random code from random GitHub accounts. Read the Dockerfile if it's available; check the publish date and pull count; prefer well-known maintainers.

Try it yourself

  1. Tag the my-app image you built in lesson 05 with your registry username, then push it to a public Docker Hub repo.
  2. From a different terminal (or after running docker rmi yourname/my-app:1.0 to clear your local copy), docker pull yourname/my-app:1.0. Confirm it runs.
  3. Move on to 09_compose_basics.md, where we stop typing long docker run commands.