Installing Docker Engine and Desktop, CLI Basics, Daemon Connectivity, Contexts, and Environment Setup: Concepts, Architecture, and Mental Model
Install Docker correctly by modeling the full environment first: supported host or Desktop platform, trusted distribution source, Docker client and Engine boundary, selected context and endpoint, persistent daemon state, and the privilege model used to administer it.
Learning objectives
- Explain why a working Docker CLI does not prove that a local Docker daemon exists or that the intended daemon is selected.
- Distinguish native Linux Docker Engine from Docker Desktop VM-backed execution and from CLI-only remote-client setups.
- Model package source, client/server/API identity, context/endpoint, daemon service, data root, storage/image store, and access mode as separate state.
- Explain the security difference between explicit sudo, docker-group socket access, rootless Docker, and Desktop-managed user access.
- Perform a read-only platform/install preflight before changing packages or daemon configuration.
1. Installation is not just “get a docker command”
Chapter 01 separated the Docker client, the Engine daemon, the runtime stack, the image, and the container process. Installation is the first time those boundaries become operational. A machine can have a Docker CLI with no local daemon, a daemon with a client that targets some other endpoint, Docker Desktop with a daemon inside a managed Linux VM, or two valid local targets selected by different contexts. The command docker ps only has meaning after you know which client is speaking to which endpoint.
A reproducible installation therefore has several identities: host OS and architecture, package or Desktop source, client version, server version and API negotiation, active context, daemon endpoint, data root, storage/image-store behavior, privilege model, and the exact image/container used to verify the environment. If any one is ambiguous, troubleshooting and automation can change the wrong machine while still returning syntactically valid Docker output.
chmod 666 /var/run/docker.sock, broad socket sharing, or unauthenticated TCP exposure.2. The installation mental model
flowchart TD A[Supported host or Desktop platform] --> B[Trusted package or Desktop distribution] B --> C[Docker CLI and Engine or managed VM] C --> D[Selected Docker context and endpoint] D --> E[Daemon runtime state and data root] E --> F[Image content pulled by exact daemon] F --> G[Test container object and process] G --> H[Recorded version context storage and lifecycle evidence]
The arrows matter. A package install can succeed while the daemon service is stopped. A daemon can be healthy while the CLI points at another context. A test container can run while the user still has an unsafe privilege model. A Desktop GUI can be open while a shell overrides the selected context through environment variables. Installation is complete only when the whole chain is proven.
3. Docker Engine and Docker Desktop are different installation boundaries
| Path | Where the daemon runs | Typical endpoint model | What to record |
|---|---|---|---|
| Native Docker Engine on Linux | Directly on the Linux host. | Usually a Unix socket such as /var/run/docker.sock. | Distribution, kernel, package repository, Engine/CLI/API, service unit, data root, storage driver/image store, privilege mode. |
| Docker Desktop on Windows/macOS | Linux containers run through Docker Desktop's managed Linux VM/backend; Windows can also support Windows-container paths under specific editions/modes. | Docker Desktop configures client access to its managed backend. | Desktop version, host OS, backend such as WSL 2/Hyper-V/VMM where applicable, context, Desktop disk/data location, actual Engine reported by docker version. |
| Docker Desktop on Linux | A dedicated Linux VM, separate from a native host Engine. | Desktop creates and selects a desktop-linux context; native Engine commonly remains on default. | Which context is active, Desktop version, host Engine presence, and which environment owns images/containers. |
| CLI-only or remote-client setup | No local daemon is required. | Named SSH/TLS context or another protected endpoint. | Client version, context name, endpoint scheme, TLS/SSH identity, remote server version/API. |
This is why “Docker is installed” is too vague. On macOS a standalone Docker CLI does not include a local Linux daemon. On Linux, Desktop and native Engine can coexist but manage different object stores. On Windows, the Desktop backend and host features determine what the daemon can run.
4. Package source is part of the supply chain
On supported Linux distributions, Docker's own repository provides the current Engine packages. Distribution-maintained packages such as docker.io are a separate supply and support path and can differ in version, build configuration, packaging, or support ownership. Manual static binaries are useful for testing but Docker explicitly discourages them as a normal production installation because automatic security updates and package lifecycle management are weaker.
The convenience script at get.docker.com is also not a production lifecycle strategy. Docker documents it for testing/development and recommends reviewing or dry-running it first. Its convenience is that it detects a platform and configures a package source; its tradeoff is that it hides choices and normally tracks the latest stable release unless you deliberately manage versions afterward.
- Distribution and architecture are supported for the chosen method.
- Repository URL and signing-key location are documented.
- Installed package names and exact versions are captured.
- Upgrade and rollback ownership are known.
- Conflicting distribution/third-party packages are identified before removal.
5. Client version, server version, and API version are separate
The Docker CLI is a client of the Engine API. docker version reports client and server information independently. A newer CLI can often communicate with an older daemon through API negotiation, but that does not mean every new CLI feature is available on that server. The environment variable DOCKER_API_VERSION can force an API version for debugging and disables normal negotiation, so it should not be left behind accidentally in a shell profile.
docker version
docker info
printf 'DOCKER_API_VERSION=%s
' "${DOCKER_API_VERSION:-}"
Record the values the pair actually reports. Version skew is a fact to reason about, not automatically a fault. If a feature fails, first ask whether the selected server supports it.
6. Contexts answer the most important operational question: which daemon?
A Docker context bundles endpoint and related connection metadata under a human-readable name. docker context use changes the persistent default in the client configuration, while --context and DOCKER_CONTEXT can override it. Current CLI documentation states that DOCKER_CONTEXT overrides DOCKER_HOST and the stored default context. Command-line flags override environment variables.
docker context ls
docker context show
docker context inspect "$(docker context show)"
printf 'DOCKER_CONTEXT=%s
' "${DOCKER_CONTEXT:-}"
printf 'DOCKER_HOST=%s
' "${DOCKER_HOST:-}"
Never make a destructive change after looking only at the shell prompt or host name. A remote context can make a local shell administer a remote daemon, and Docker Desktop can deliberately select a context different from a native Engine.
7. Service state, daemon configuration, data root, and object state are different
On a regular Linux Engine installation, dockerd is commonly managed by systemd. Its preferred configuration surface is a JSON file (normally /etc/docker/daemon.json for rootful Linux), while the default persistent Docker data root is /var/lib/docker. Runtime/exec state lives elsewhere. Docker Desktop owns its daemon configuration through Desktop settings rather than asking users to manage the VM's daemon as if it were a normal host service.
docker info --format 'DockerRootDir={{.DockerRootDir}}'
docker info --format 'Driver={{.Driver}} CgroupDriver={{.CgroupDriver}} CgroupVersion={{.CgroupVersion}}'
docker info --format 'SecurityOptions={{json .SecurityOptions}}'
Changing or deleting a data root is not an installation cleanup shortcut. It can destroy images, container metadata, volumes, and other state. Chapter 32 will cover storage internals; at installation time the correct habit is to identify the data root and leave it alone unless a deliberate migration plan exists.
8. “Run Docker without sudo” has two very different meanings
Adding a user to the docker group lets that user access the rootful daemon socket. Docker's own documentation warns that this grants root-level privileges. Rootless Docker is a different architecture: both daemon and containers run without root privileges inside a user namespace, with prerequisites such as newuidmap/newgidmap and subordinate UID/GID ranges.
| Mode | Daemon identity | Main benefit | Main caution |
|---|---|---|---|
sudo docker ... | Rootful daemon; CLI invoked through sudo. | Explicit elevation at use time. | Still full daemon privilege; scripts may become awkward. |
docker group | Rootful daemon; group can access socket. | Convenient non-sudo CLI. | Group membership is root-level privilege, not least privilege. |
| Rootless Docker | Daemon and containers run as an unprivileged user in a user namespace. | Reduces daemon/runtime privilege on the host. | Has platform, networking, storage, cgroup, and subordinate-ID prerequisites/limitations. |
| Docker Desktop user access | Managed backend/VM with Desktop-specific privilege mediation. | Developer-oriented host integration. | Host/VM boundary and Desktop licensing/enterprise policy still matter. |
9. Read-only installation preflight
Before installing or changing anything, collect a short host baseline. These commands are intentionally non-destructive and help explain why a later installation path succeeds or fails.
uname -a
uname -m
cat /etc/os-release 2>/dev/null || true
command -v docker || true
docker --version 2>/dev/null || true
docker context ls 2>/dev/null || true
systemctl status docker --no-pager 2>/dev/null || true
getent group docker 2>/dev/null || true
grep "^${USER}:" /etc/subuid /etc/subgid 2>/dev/null || true
On Windows, record winver/systeminfo, wsl --version, and Docker Desktop's version/backend. On macOS, record sw_vers, architecture, and Desktop version. The purpose is not to collect everything; it is to know which installation assumptions apply.
10. Common wrong models to remove now
| Wrong statement | Correct model |
|---|---|
“If docker --version works, Docker is running.” | That proves only the client binary executes. Server connectivity is a separate state. |
| “The default context means this physical machine.” | A context is client configuration. Inspect its endpoint instead of inferring geography. |
| “Adding myself to the docker group makes Docker unprivileged.” | It gives the user access to a privileged rootful daemon. |
| “Docker Desktop is just the Linux Docker daemon installed directly on Windows or macOS.” | Linux containers run through a managed Linux VM/backend. |
| “Reinstalling Docker resets everything.” | Package removal and daemon data are separate. Existing data roots can persist across uninstall/reinstall. |
Knowledge check
A shell shows Docker CLI 29.8.1, but docker version cannot show a Server section. What has actually been proved?
Only that the Docker client binary runs. No reachable Engine server has been proved yet; inspect the active context, endpoint, daemon service, and any overriding environment variables.
Why is docker context show required before a destructive command?
Because the CLI can administer a local or remote daemon. Context identity is part of resource ownership and prevents operating on an unintended Engine.
Does adding a user to the docker group implement rootless Docker?
No. It gives the user access to the rootful daemon socket. Rootless Docker runs the daemon itself without root and uses a user namespace with additional prerequisites.
Where do Linux containers run when using Docker Desktop on macOS or Windows?
Inside Docker Desktop's managed Linux VM/backend, not directly on the macOS or Windows kernel as native Linux processes.
Why should package source and exact package versions be recorded in an installation evidence packet?
They identify the software supply path and make upgrade, rollback, vulnerability, and reproducibility decisions auditable.
Summary
Installing Docker means establishing a supported platform, trusted distribution source, Docker client, reachable Engine endpoint, explicit context, persistent daemon state, and an understood privilege model. Docker Engine and Docker Desktop can present similar CLI workflows while owning different host/runtime boundaries. The next lesson turns this model into a safe installation and verification workflow on a disposable environment.
Official references and version notes
Version-sensitive statements in this chapter were rechecked against primary documentation on 2026-09-20. Installation support, package names, Desktop requirements, component versions, context behavior, rootless prerequisites, and security guidance evolve. Always record the versions and platform facts actually reported by the environment you are operating.
- Install Docker Engine — supported distribution paths, release channels, package-source boundaries, and installation methods.
- Install Docker Engine on Ubuntu — current official apt-repository procedure, package names, verification, and convenience-script caveats.
- Linux post-installation steps — service startup and the warning that membership in the
dockergroup grants root-level privileges. - Rootless mode — current prerequisites, subordinate UID/GID requirements, user-service behavior, and limitations.
- Docker contexts — endpoint identity, switching contexts, and portable client configuration.
- Docker CLI reference — global flags and environment-variable precedence including
DOCKER_CONTEXTandDOCKER_HOST. - Docker daemon configuration overview — daemon configuration paths, preferred JSON configuration, data root, and validation.
- dockerd reference — daemon sockets,
--validate, configuration conflicts, data-root, and runtime options. - Install Docker Desktop on Windows — current WSL 2/Hyper-V/VMM installation requirements, modes, and Windows support boundaries.
- Install Docker Desktop on Mac — current supported macOS window, architecture downloads, and Desktop subscription terms.
- Install Docker Desktop on Linux — VM-backed Desktop behavior and the dedicated
desktop-linuxcontext. - Docker Desktop release notes — Docker Desktop 4.91.0 was released 2026-09-14.
- Docker Engine 29 release notes — Docker Engine 29.8.1 was released 2026-09-15.
- Buildx releases — Buildx v0.37.1 was released 2026-09-11.
- BuildKit releases — BuildKit v0.33.0 was released 2026-09-02.
- Compose releases — Docker Compose v5.5.1 was released 2026-09-03.
At this chapter's verification date, Docker Engine 29.8.1 and Docker Desktop 4.91.0 are current releases, while Buildx 0.37.1, BuildKit 0.33.0, and Compose 5.5.1 are current upstream releases. Bundled component versions can differ by Engine/Desktop/package source. Use docker version, docker info, docker buildx version, and docker compose version as execution evidence rather than assuming those upstream versions are installed.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this address.