Installing Docker and the core CLI workflow
Engine, CLI, daemon and socket, the permissions that matter, and the build-run-push loop you will repeat all day.
What you are actually installing
Docker is three things wearing one name: a client (docker), a long-running daemon (dockerd) that does the work, and a Unix socket that carries commands between them. The client only sends requests; every image, container and volume lives with the daemon.
| Piece | What it is | Where it lives |
|---|---|---|
docker CLI | The client you type into | Your PATH, no privileges needed |
dockerd | The daemon that builds and runs containers | A systemd unit on the host |
/var/run/docker.sock | The API endpoint | Owned by root:docker, mode 660 |
| containerd + runc | The runtime that actually starts processes | Started by dockerd |
| Registry | Storage for images | Remote: Docker Hub, GHCR; local: registry:2 |
| Docker Desktop | A VM plus GUI wrapping engine and Kubernetes | macOS and Windows, optional on Linux |
docker version # client AND server - an error here means the daemon is down
docker info # storage driver, cgroup version, runtimes, root dir
docker context ls # which endpoint the CLI talks to
docker context use default
# talk to a remote or rootless daemon without touching the default
DOCKER_HOST=ssh://deploy@web docker ps- If
docker pssucceeds but shows a 'Server' error, the CLI is fine and the daemon is not running — checksystemctl status docker. - On macOS and Windows the daemon runs inside a lightweight VM, so
localhostis the VM, not your machine, and bind mounts go through a file-sharing layer. docker contextis the supported way to point at a remote engine; editingDOCKER_HOSTin a profile file is how people accidentally ship to production.
Install and grant access
# Debian / Ubuntu, from Docker's own repository
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg |
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" |
sudo tee /etc/apt/sources.list.d/docker.list >/dev/null
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker
# run as your own user instead of prefixing every command with sudo
sudo usermod -aG docker "$USER" # log out and back in for it to apply
docker run --rm hello-world # proves client, daemon and registry all work
docker compose version⚠️
Membership of the
docker group is equivalent to root: anyone in it can start a container that mounts the host filesystem. On shared or production machines that matters, so prefer rootless mode (dockerd-rootless-setuptool.sh install) or a remote context instead of adding accounts to the group.The loop: build, run, ship
# 1. build an image from the Dockerfile in this directory
docker build -t registry.example.com/team/app:1.0.0 .
# 2. run it locally, publish a port, name it, drop it on exit
docker run --rm -d --name app -p 8080:3000 --env-file .env registry.example.com/team/app:1.0.0
# 3. look at it, then debug inside it
docker ps
docker logs -f --tail 50 app
# 4. ship it
docker login registry.example.com
docker push registry.example.com/team/app:1.0.0
# 5. reclaim space when you are done experimenting
docker system df
docker system prune -f # -a also removes unused images- An image is inert and shareable; a container is one running instance of it with a thin writable layer that disappears with it.
- A registry stores images by name and tag, which is why the tag must include the registry host when it is not Docker Hub.
docker run=docker create+docker start, so flags you forget at run time cannot be added later.- Anything you type often belongs in a Compose file rather than in a shell history entry.
FAQ
'permission denied while trying to connect to the Docker daemon socket'?
Either your user is not in the
docker group yet (group changes need a fresh login session), or the daemon is not running. Check with systemctl status docker, then id to confirm the group.Should I use Docker Desktop or the engine on Linux?
On a Linux server, install the engine from the distribution or Docker's repository and skip the GUI entirely. Desktop is convenient on macOS and Windows, where a VM is unavoidable, and on a Linux workstation only if you want its Kubernetes and GUI features.
Related
Container lifecycle, logs and debugging Registries, tags and image distribution
Last refreshed 2026-09-18.