Installing Docker & your first run
hello-world, and what just happened.
Installing Docker puts two programs on the machine. The Docker daemon (dockerd) is a background service: it pulls images, starts containers, and manages networks and volumes. You do not talk to it with a GUI on Linux Engine. The docker CLI is the client: you type a command, it sends an API request to the daemon. Almost every lesson in this course is that client/daemon split.
Which pieces you install depends on the machine in front of you. On Linux you install Docker Engine, and it runs containers directly. A container is an ordinary program running on your machine, fenced off in its own little space so it behaves as if it had the whole computer to itself. Linux already has the kernel a container needs. (The kernel is the core of the operating system, the part that actually talks to the hardware.) On a Mac or on Windows you install Docker Desktop instead. Containers need a Linux kernel, and your Mac or Windows machine doesn't have one, so Desktop quietly runs a small Linux virtual machine in the background, a whole extra computer simulated in software, and keeps your containers inside it. Either way you type the same docker commands. The examples below are Linux, because the one error nearly every beginner hits lives there.
Check that both halves are talking
Before you run anything real, get the two halves to say hello. The command docker version asks each of them to report in, and it prints one block per answer.
$ docker version
Client: Docker Engine - CommunityVersion: 27.3.1API version: 1.47Go version: go1.22.7OS/Arch: linux/amd64Context: defaultServer: Docker Engine - CommunityEngine:Version: 27.3.1API version: 1.47 (minimum version 1.24)Go version: go1.22.7OS/Arch: linux/amd64
Read it from the top. Client is the CLI you typed. Server is the daemon. Two blocks with version numbers means the client reached the daemon. If Server is missing or errors, the daemon is not running, or your account cannot talk to it. On Linux: sudo systemctl start docker. On Docker Desktop: open the app and wait until it is idle. Permission on a fresh Linux install is the usual next failure — trigger it on purpose below.
Your first container
The usual first run is the hello-world image. An image is a read-only bundle of files plus the default process to start. A container is a running (or exited) instance of that image. hello-world lives on Docker Hub. Its default name is hello-world:latest; the part after the colon is the tag, and latest is what Docker fills in when you omit one.
Type it and read what comes back.
$ docker run hello-world
docker: permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Head "http://%2Fvar%2Frun%2Fdocker.sock/_ping": dial unix /var/run/docker.sock: connect: permission denied.Run 'docker run --help' for more information
Nothing is broken here, so do not reinstall. Read the error: permission denied on /var/run/docker.sock. That socket is how the client reaches the daemon. On Linux it is owned such that only root (or members of the docker group) may use it. Your client was refused. docker version on the same machine shows the same Server error for the same reason.
The fix is to let your account use that hatch. Docker creates a group named docker for exactly this purpose, and anyone in that group is allowed to reach the daemon. You add yourself once, with usermod. The -aG flags mean append the account to the named group and leave the groups it already belongs to alone. One snag: your terminal session started before you joined the group, so it hasn't noticed the change. Running newgrp docker opens a fresh session that carries the new membership, and logging out and back in does the same thing. Then the command that failed goes through.
$ sudo usermod -aG docker $USER$ newgrp docker$ docker run hello-world
Unable to find image 'hello-world:latest' locallylatest: Pulling from library/hello-worldc1ec31eb5944: Pull completeDigest: sha256:d000bc569937abbe195e20322a0bde6b2922d805332fd6d8a68b19f524b7d21dStatus: Downloaded newer image for hello-world:latestHello 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 theexecutable that produces the output you are currently reading.4. The Docker daemon streamed that output to the Docker client, which sent itto your terminal.
That wall of text is Docker narrating its own steps. It looked for hello-world on your machine, didn't find it, and said so on the Unable to find image line. Then it pulled a copy down from Docker Hub. Then it created a container from that image and started the one small program inside, which printed the greeting. The program had nothing left to do, so it exited, and the moment a container's program exits, the container stops. Every docker run you ever type follows the same path: look locally, pull the image if it's missing, create the container, start it, and let it run until its program ends.
The daemon has a name worth knowing: dockerd. That is the program doing the real work, pulling images, creating containers, wiring up networks, and on Linux it is what sits on the other side of /var/run/docker.sock. On Docker Desktop it lives inside that small Linux virtual machine, so your order pad is reaching across to another computer to hand over the ticket. Most install trouble is a break somewhere in that handoff, and the error text names which side stopped you, the way the permission line above did.
So make your smoke test boring, and run it in this order. docker version should print a Client block and a Server block. docker run --rm hello-world should print the greeting. docker ps should return a table, even an empty one with nothing but column headings. Once all three behave, you can start blaming your own app. Skip the check and you can lose an afternoon debugging an nginx port mapping on a machine where the daemon never started.
One habit to skip while you are here. You can put sudo in front of every docker command and it will work, which is how plenty of people end up typing sudo docker for years. That habit hides the group setup instead of fixing it, and it stops helping the day you sit at a machine where your account has no sudo rights.
Try this
Prove both halves are alive, then run hello-world with --rm so the finished container doesn't linger on your machine.
docker version --format "{{.Server.Version}}"docker info --format "{{.Driver}} {{.OperatingSystem}}"docker run --rm hello-world
27.x.xoverlay2 Docker DesktopHello from Docker!This message shows that your installation appears to be working correctly.
Takeaway
The docker command is a client and nothing else. If docker version prints no Server block, or hello-world can't reach the socket, that's the engine talking, not your app. Get the engine answering first, before you touch a container of your own.