Docker Engine Basics
This page is a hands-on intro to running Docker Engine: checking the daemon, running your first containers, and understanding the daemon-versus-CLI split plus rootless mode.
Prerequisites
- Docker Engine 29.6.1 on Linux (BuildKit is the default build backend).
- A user in the
dockergroup, or usesudo, or run rootless mode. systemdto manage the daemon on most distributions.
Quick install on Debian/Ubuntu via the official convenience script:
curl -fsSL https://get.docker.com | sh
sudo systemctl enable --now docker
docker versionBasic Examples
1. Confirm the daemon and CLI are talking
Verify both halves of the client-server system report versions.
docker version- The Client block is the
dockerCLI you typed. - The Server block is
dockerd. If it is missing, the daemon is not running or your socket is wrong. docker infoadds runtime details: storage driver, cgroup version, and the containerd/runc versions.- No Server block usually means
systemctl start dockeris needed.
2. Run your first container
Start a container and see it print output, then exit.
docker run --rm hello-worlddocker runpulls the image if absent, creates a container, and starts it.--rmdeletes the container when it exits, keeping your system clean.- The CLI sent this to the daemon over
/var/run/docker.sock. - The image came from Docker Hub because no registry prefix was given.
3. Run a long-lived service in the background
Detach a web server and map a port to the host.
docker run -d --name web -p 8080:80 nginx:1.27-druns detached so your terminal returns immediately.--name webgives a stable handle instead of a random name.-p 8080:80publishes container port 80 on host port 8080.- Always pin a tag (
nginx:1.27) rather than the movinglatest.
4. List and inspect running containers
See what is running and where.
docker psdocker psshows only running containers; add-ato include stopped ones.- The
STATUScolumn reveals restarts and health-check state. docker ps --format '{{.Names}} {{.Ports}}'trims output to what you need.- Each row is one container process supervised by a shim.
5. Read logs from a container
Stream stdout and stderr the daemon captured.
docker logs -f web-ffollows the log stream liketail -f.- The daemon stores these via its logging driver (
json-fileby default). - Add
--since 10mto bound noisy output. - Apps should log to stdout/stderr so Docker can collect it.
6. Get a shell inside a container
Exec into a running container for debugging.
docker exec -it web shexecstarts a new process inside the container's namespaces.-itallocates an interactive TTY.- This does not restart the container; it joins the live one.
- Prefer
shfor minimal images that lackbash.
7. Stop and remove containers
Clean up cleanly rather than killing processes.
docker stop web && docker rm webstopsends SIGTERM, waits (default 10s), then SIGKILL.rmdeletes the stopped container and its writable layer.- Named volumes survive unless you add
-v. docker rm -f webforce-stops and removes in one step.
Intermediate Examples
8. Understand daemon vs CLI with a remote host
The CLI is a client; point it at another engine without installing anything new.
export DOCKER_HOST=ssh://ops@buildhost
docker psDOCKER_HOSTredirects every CLI call to a remote daemon.- Over SSH, no TLS certificates or open ports are required.
- The containers listed live on
buildhost, not your laptop. - Unset the variable or use contexts to switch back.
9. Run rootless Docker
Run the daemon and containers without real root to shrink the attack surface.
dockerd-rootless-setuptool.sh install
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
docker run --rm hello-world- Rootless runs
dockerdinside a user namespace, sorootin the container maps to your unprivileged UID. - Privileged ports below 1024 need extra configuration to publish.
- Some storage and networking features differ from rootful mode.
- It is a strong default for shared build hosts and developer machines.
10. Limit container resources
Set CPU and memory bounds so one container cannot starve the host.
docker run -d --name api \
--memory=512m --cpus=1.5 \
--restart=on-failure:3 \
myorg/api:1.4.0--memorycaps RAM; the container is OOM-killed if it exceeds it.--cpus=1.5limits it to one and a half cores via cgroups.--restart=on-failure:3retries up to three times on non-zero exit.- These map to the same cgroup controls Kubernetes uses for requests and limits.
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).