How to Run Hello World in Docker: First Container Tutorial for Absolute Beginners

How to Run Hello World in Docker

Every developer’s first real Docker moment is running docker run hello-world, and there’s a reason that specific command has become a rite of passage — it exercises nearly the entire Docker pipeline in one shot: pulling an image, creating a container, running it, and printing proof that the whole system works end to end. I remember running it for the first time not fully understanding what had just happened, so this guide walks through not just the command itself but everything that happens behind it.

Prerequisites

  • Docker installed on your machine (Docker Desktop on Mac/Windows, or Docker Engine on Linux)
  • Verify installation:
docker --version
Docker version 27.3.1, build ce12230
  • Verify the Docker daemon is running:
docker info

If this returns system details rather than a connection error, the daemon is up and ready.

Step 1: Run Hello World

docker run hello-world

Expected output the first time you run it:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
c1ec31eb5944: Pull complete
Digest: sha256:1408fec78703e60de6b7c8f8e9c8b0e9a3fe5c9f5e8b0e9a3fe5c9f5e8b0e9a
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs
    the executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent
    it to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

That block of text is itself printed by a tiny compiled binary inside the hello-world image — it’s genuinely explaining, in real time, the exact pipeline that just executed to produce it.

Step 2: Run It Again and Notice the Difference

docker run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
...

Notice there’s no “Pulling from library/hello-world” this time — Docker found the image already cached locally and skipped the download.

Step 3: Confirm the Image Was Pulled

docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
hello-world   latest    d2c94e258dcb   14 months ago   13.3kB

Thirteen kilobytes — this is about as small as a Docker image gets, since it contains a single statically linked binary and nothing else.

Step 4: See the Container That Ran (and Exited)

docker ps -a
CONTAINER ID   IMAGE         COMMAND    CREATED         STATUS                     NAMES
e5f6a7b8c9d0   hello-world   "/hello"   2 minutes ago   Exited (0) 2 minutes ago   quirky_hopper

The container ran its single command (/hello), printed its message, and exited immediately with status code 0, meaning success. This is expected — hello-world isn’t a long-running service, so it’s supposed to finish right away.

Step 5: Clean Up

Since each run creates a new stopped container, running it several times leaves several stopped containers behind:

docker ps -a
CONTAINER ID   IMAGE         COMMAND    STATUS                     NAMES
e5f6a7b8c9d0   hello-world   "/hello"   Exited (0) 2 minutes ago   quirky_hopper
f6a7b8c9d0e1   hello-world   "/hello"   Exited (0) 5 minutes ago   nostalgic_curie

Remove them:

docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
e5f6a7b8c9d0
f6a7b8c9d0e1

Total reclaimed space: 0B

Internal Working: What Actually Happens Step by Step

  1. Client request: the docker CLI sends a request to the Docker daemon (dockerd) via its REST API, usually over a local Unix socket (/var/run/docker.sock).
  2. Image resolution: the daemon checks its local image store for hello-world:latest. If absent, it contacts Docker Hub’s registry API, negotiates the correct image manifest for your CPU architecture, and downloads the image layer(s).
  3. Layer storage: the downloaded layer is stored under Docker’s storage driver directory (commonly /var/lib/docker/overlay2/ on Linux).
  4. Container creation: containerd, working with runc, prepares Linux namespaces (PID, mount, network, UTS, IPC) and cgroups for resource isolation, then creates a container filesystem by adding a thin writable layer on top of the image’s read-only layers.
  5. Process execution: runc executes the image’s configured command (/hello) inside those namespaces.
  6. Output streaming: the container’s stdout is captured by Docker’s logging driver and streamed back through the daemon to the CLI, which prints it to your terminal.
  7. Exit and cleanup: once /hello finishes, the container’s main process ends, its state becomes Exited, and the container itself remains on disk (though not running) until explicitly removed.

Networking Notes

hello-world doesn’t listen on any port or make any network connections once running — the only network activity involved is the initial image pull from Docker Hub over HTTPS. This makes it a genuinely safe first test even on networks with tight outbound restrictions, aside from that one registry pull.

Storage Notes

Because the image is so small and the container does nothing but print text and exit, there’s essentially no storage footprint beyond the 13.3kB image itself and a tiny per-container metadata directory that docker container prune clears out.

Security Considerations

  • Pulling hello-world (or any public image) means trusting Docker Hub’s content — for anything beyond a first test, verify image digests or use Docker Content Trust for signed images in production.
  • Running containers doesn’t require root privileges on the container side by default for this image, but the Docker daemon itself typically runs as root on Linux, which is worth knowing when reasoning about your host’s security boundaries.

Troubleshooting

“Cannot connect to the Docker daemon”

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

This means the Docker service itself isn’t running. On Linux:

sudo systemctl start docker

On Mac/Windows, start Docker Desktop.

“permission denied while trying to connect to the Docker daemon socket” On Linux, this means your user isn’t in the docker group:

sudo usermod -aG docker $USER

Then log out and back in for the group change to take effect.

Image pull fails with a network/TLS error Usually a proxy or firewall blocking access to registry-1.docker.io. Check outbound HTTPS access and any corporate proxy configuration in Docker’s daemon settings.

Monitoring

For this one-shot container there’s nothing ongoing to monitor, but it’s still worth checking exit codes when scripting against Docker for the first time:

docker run hello-world; echo "Exit code: $?"
Exit code: 0

Best Practices

  • Use hello-world purely as an installation sanity check, not as a template for real application containers.
  • Get comfortable with docker ps -a early — it’s the single most useful command for understanding what containers exist and their current state.
  • Learn docker container prune early too, so leftover stopped containers from experimentation don’t accumulate unnoticed.

Summary

docker run hello-world looks trivial, but it silently exercises the entire Docker pipeline: client-daemon communication, registry image pulls, layer storage, namespace and cgroup setup, process execution, and log streaming. Understanding what happens behind those few lines of output makes every subsequent, more complex docker run command far less mysterious.

References

  • Docker “Get started” guide: https://docs.docker.com/get-started/
  • Docker Hub hello-world image: https://hub.docker.com/_/hello-world
  • Docker Engine overview: https://docs.docker.com/engine/
  • Docker run reference: https://docs.docker.com/reference/cli/docker/container/run/
Total
0
Shares

Leave a Reply

Previous Post
How to Use Docker Experimental Binaries

How to Use Docker Experimental Binaries: Enabling and Testing New Docker Features Guide

Next Post
How to Run a Docker Container in Detached Mode

How to Run a Docker Container in Detached Mode: Background Execution and Management Guide

Related Posts