Getting Docker running
Before any of the interesting parts, you need a working Docker. This lesson gets you from nothing to a container you ran yourself, and explains the permission error that tends to arrive with the first command.
What you are installing
Docker ships as two halves. There is a daemon, a background service running
as root that does the actual work, and a client, the docker command you
type. They talk over a Unix socket usually at /var/run/docker.sock.
Install
Docker supports most linux distros, go here if you aren’t on a Ubuntu based system.
Ubuntu ships a docker.io package, and it works, but it lags a long way behind.
Use Docker’s own repository. First remove anything from the distro that would
conflict:
$ for pkg in docker.io docker-compose docker-compose-v2 docker-doc podman-docker containerd runc; do sudo apt-get remove -y $pkg; done
Add Docker’s signing key and repository:
$ sudo apt-get update
$ sudo apt-get install -y ca-certificates curl
$ sudo install -m 0755 -d /etc/apt/keyrings
$ sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
$ sudo chmod a+r /etc/apt/keyrings/docker.asc
$ sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
$ sudo apt-get update
Then install the engine, the CLI, and the two plugins you will use:
$ sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Check what you got:
$ docker --version
Docker version 29.6.1, build 8900f1d
$ docker compose version
Docker Compose version v5.3.1
There is also a Docker snap in the Ubuntu store. Avoid it for this course. The
daemon is confined, so it cannot see paths outside your home directory or any
hidden directory inside it, and a bind mount of /tmp/work silently gives you
an empty directory instead of an error.
macOS and Windows
For macOS and Winodws Docker provides “Docker Desktop”. Details for install are here
There are some subtle differences between docker desktop and docker engine (what we installed for linux). Don’t worry too much about that now, we will call out where you can expect to see differences.
Your first container
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
4f55086f7dd0: Pull complete
Digest: sha256:5dd0d3e6e255913fc30f90b9f2b1d359cc2cbdb48090cc4b65f1676e203243cc
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.
Check that out, assuming you got something similar you are all set up and ready to go.
Permission denied on the socket
What if you got a permission error like this?
$ docker run hello-world
permission denied while trying to connect to the docker API at unix:///var/run/docker.sock
Nothing is broken. Look at the socket:
$ ls -la /var/run/docker.sock
srw-rw---- 1 root docker 0 Aug 15 15:52 /var/run/docker.sock
Owned by root, group docker, mode 660. You are neither, so the kernel says
no before Docker is even involved. Two ways forward.
Use sudo. sudo docker run hello-world works immediately and is honest
about what is happening: you are asking a root service to do something.
Or add yourself to the group, which is what most people do:
$ sudo usermod -aG docker $USER
$ newgrp docker
$ id -nG
evan adm cdrom sudo dip plugdev lxd docker
Note newgrp gives the current shell the new group.
Be warned adding yourself to the docker group is equivalent to giving yourself
passwordless root. The socket is an unauthenticated API to a root daemon, and
anyone who can talk to it can ask for a container with the host’s entire
filesystem mounted inside it. Three commands and you have /etc/shadow.
That is not a vulnerability, it is the design We look at this later in this course, including what you can do when you find that group membership on someone else’s machine.
For sensitive systems Docker has a rootless mode where the daemon runs as you. It costs you some networking features.