What is /etc/docker/daemon.json, and how do you apply a change you make to it?
answer
- The daemon has its own config file
- Host-wide default, not a docker run flag
- Strict JSON under /etc/docker on Linux
- Only read when the daemon starts
- systemctl reload versus systemctl restart
basics
~20 s/etc/docker/daemon.json is the Docker daemon's own configuration file: host-wide settings such as the default log driver, the storage driver, registry mirrors and data-root. dockerd reads it only at start-up, so an edit needs a daemon reload or restart.
solid answer
~50 s`/etc/docker/daemon.json` configures `dockerd` itself, as opposed to `docker run` flags, which configure one container. Every key is the JSON equivalent of a `dockerd` command-line flag — `log-driver`, `storage-driver`, `data-root`, `registry-mirrors`, `insecure-registries`, `live-restore` — and the file must be strict JSON: no comments, no trailing commas. The daemon parses it only when it starts, so an edit does nothing on its own. `systemctl reload docker` sends the daemon a SIGHUP and re-reads the keys that support reloading; `systemctl restart docker` restarts the process and picks up everything, stopping the host's containers on the way unless `live-restore` is enabled. Check the result with `docker info`, which prints the effective values, rather than by re-reading the file. Two traps: a host-wide default such as `log-driver` applies only to containers created afterwards, and an unparsable file stops the daemon from starting at all.
code
json · 6 lines{
"data-root": "/srv/docker",
"storage-driver": "overlay2",
"live-restore": true,
"log-driver": "local"
}go deeper
Be ready to say where the file lives, that it configures the daemon rather than a container, and that you must reload or restart the daemon for an edit to count. Naming two or three real keys is enough at this level.
Explain that every key mirrors a dockerd flag, that the file is strict JSON validated at start-up, and that a host default such as the log driver applies only to containers created after the change.
Show that you treat an edit as a change with blast radius: validate before applying, know that a bad file stops the engine, and verify the outcome with docker info rather than trusting the file you just wrote.
Own the policy question of which settings are pinned host-wide by configuration management versus left to each workload, and how engine configuration is kept identical and reviewable across a fleet.
## What the file is The Docker Engine is a long-running host process, `dockerd`, usually run as a systemd service. It owns everything that is not one container: the image and container stores on disk, the default networks, the API socket at `/var/run/docker.sock` that the `docker` CLI talks to, and the defaults every new container inherits. Anything that belongs to *that process* is configured in one of two interchangeable ways — as a command-line flag on `dockerd`, or as a key in a JSON file, by default `/etc/docker/daemon.json` on Linux. `dockerd --storage-driver overlay2` and `{"storage-driver": "overlay2"}` say the same thing. The file exists so a host's engine configuration can be managed as data by a configuration-management tool instead of by editing a unit file. ## What belongs in it Host-wide defaults and engine policy. The keys most often seen in a real file: - `data-root` — where the engine keeps images, container state and volumes; defaults to `/var/lib/docker`. - `storage-driver` — which driver the engine uses for image and container filesystems, e.g. `overlay2`. - `log-driver` and `log-opts` — the default logging configuration for containers created from now on. - `registry-mirrors` — pull-through mirrors the daemon tries before the upstream registry. - `insecure-registries` — registries the daemon may talk to over plain HTTP or with an untrusted certificate. - `live-restore` — whether running containers survive a restart of the daemon. - `debug` / `log-level` — the daemon's own logging verbosity. - `hosts` — the addresses the daemon listens on. What does *not* belong in it is anything that describes one container: published ports, memory limits, restart policies, bind mounts. Those are `docker run` flags or Compose fields. A serviceable rule: if two containers on the same host could reasonably want different values, it is not a daemon setting — at most the daemon supplies a default that a per-container flag overrides. ## It is JSON, and only JSON Keys are the long flag names without leading dashes, values are JSON scalars, arrays or objects. There are no comments and no trailing commas, and the daemon rejects keys it does not recognise. This matters more here than in most config files, because the daemon validates the file at start-up and *refuses to start* if it is bad. One stray comma takes the entire engine down, and with it every container on the host that is not protected by `live-restore`. It is also an error to set the same option both in the file and as a flag in the systemd unit — the daemon exits rather than guess which one you meant. Run `systemctl cat docker` to see what flags the shipped unit's `ExecStart` line already passes. ## Applying a change An edit to the file changes nothing by itself. Two ways to apply it: - `systemctl reload docker` sends SIGHUP. The daemon re-reads the file and applies the subset of keys that support live reloading, without touching any running container. - `systemctl restart docker` restarts the process, so every key is re-read. Without `live-restore`, this stops running containers; those with a restart policy come back when the daemon starts again. Beware the vocabulary collision: `docker restart <container>` restarts *a container* and has nothing to do with daemon configuration; restarting the daemon is a host operation done through the init system. Verify the outcome with `docker info`, which prints the daemon's *effective* settings — Storage Driver, Logging Driver, Docker Root Dir, Registry Mirrors, Live Restore Enabled — so you can see that the daemon actually agreed with your file. You can also pre-check a file with `dockerd --validate`, which parses the configuration and exits without starting an engine. ## Scope of a changed default A container records its effective configuration when it is created. Changing `log-driver` in `daemon.json` therefore affects containers created after the change; existing containers keep the driver they were created with until they are recreated. Changing `storage-driver` converts nothing: images written under the old driver simply are not visible to the new one, though they are still on disk under their own directory in `data-root`. ## Docker Desktop On macOS and Windows the engine runs inside a Linux VM, so there is no `/etc/docker` on the host that the engine reads. Docker Desktop exposes the same JSON document in its Settings → Docker Engine pane and applies it by restarting the engine inside the VM for you.
- How do you check a daemon.json edit before you risk restarting the daemon?Run `dockerd --validate`, which parses the configuration file and exits with an error message instead of starting an engine. It catches malformed JSON and unrecognised keys, which is most of what breaks a start-up. After applying the change, confirm what the daemon actually adopted with `docker info` rather than by re-reading the file — the printed Storage Driver, Docker Root Dir, Logging Driver and Registry Mirrors are the effective values.
- Where do you configure the engine when you are running Docker Desktop on macOS?The engine runs inside Docker Desktop's Linux VM, so the macOS host has no `/etc/docker` that the engine reads. Desktop exposes the same JSON document in Settings → Docker Engine and applies it by restarting the VM's engine when you save. The keys are the same ones you would put in `daemon.json` on a Linux server.
- You set a default log driver in daemon.json but an already-running container still uses the old one. Why?Because the daemon's setting is a default applied at container *create* time, not a live property of running containers. Each container stores its effective configuration when it is created, so containers that already exist keep the driver they were created with. Recreating them — not restarting them — is what picks up the new default.
saying these in an interview costs you the question
- Thinks daemon.json changes take effect immediately with no reload
- Confuses docker restart of a container with restarting dockerd
- Puts per-container settings like published ports in daemon.json
- Writes comments or a trailing comma into the JSON file
- Assumes a new default log driver changes running containers
- Sets the same option in daemon.json and as a dockerd flag