Load containerd.d/*.toml next to the daemon configuration file when
using embedded containerd.
Only the plugins, disabled_plugins, and required_plugins settings
apply.
Require version 4 or later and reject nested imports, so the merge
order follows the lexical order of the files.
Warn when drop-ins are present but dockerd uses a system or managed
containerd, which ignore them.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Every daemon with an extension host opened an extra full-access API
socket at startup, even when no extension used the API.
The socket is now created when an extension first connects to the API.
The daemonapi client looks up the endpoint on its first connection, so
NewClient no longer takes a context.
The socket is served separately from the configured hosts, returns 503
until the daemon is ready, and closes after extensions shut down.
It is accessible only to the daemon user, or to Administrators and
LocalSystem on Windows.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Extensions had no supported way to call the Engine API.
The configured hosts may be socket-activated or TLS-only TCP.
Add the org.mobyproject.extension.daemon.api.v0 point.
It returns the address of a private unix socket where the daemon serves
its regular API handler.
daemonapiv0.NewClient helper resolves the point and returns a
*client.Client.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Pass the daemon startup context to RestartSwarmContainers and return an
error if startup is canceled.
Stop scheduling additional container starts after cancellation, wait for
already-started work to finish, and propagate the context error so daemon
initialization does not continue after an interrupted restart.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
BuildKit's bridge network provider creates its sandboxes with
OptionUseExternalKey, so that the sandbox uses the network namespace
runc creates inside the container's user namespace, and installs a
prestart hook which passes that namespace to libnetwork. The hook
re-executed dockerd as "libnetwork-setkey", which located libnetwork's
external key listener from the controller's ID and the exec root, and
the listener looked the sandbox up by container ID.
Make the daemon own an ocihook.Server listening on
<exec-root>/oci-hook.sock, shut it down before the network controller,
and pass it to BuildKit. The provider registers a callback which calls
SetKey on its own sandbox, and unregisters it when the namespace is
closed. It registers the callback with the context BuildKit passed to
the provider when creating the namespace, which is the context of the
container run, so spans started by SetKey are children of the build
step's span, and a cancelled build step cancels SetKey.
Signed-off-by: Cory Snider <csnider@mirantis.com>
Assisted-By: Claude Opus 5.5
Pass the daemon lifecycle context to the config reload trap and stop the
Unix signal handler when the context is canceled. This also unregisters
the SIGHUP notification when the goroutine exits.
On Windows, signal the Win32 event when the context is canceled to wake
the blocking wait and allow the reload goroutine to exit.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Add a single-provider namesgenerator point with the existing random
generator as its built-in implementation.
Installed extensions can now supply container and Swarm service names,
while failures fall back to the built-in generator so create operations
remain available.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Publish extension `service.grpc` services on the API socket while
retaining daemon services and rejecting name collisions. Route
matching gRPC requests through the extension proxy.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Separate construction of the containerd supervisor from starting and
monitoring the daemon.
This allows callers to configure and inspect the supervisor before starting
it, and keeps runtime operations tied to the context passed to Start.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
`getContainerdDaemonOpts` never returned an error; remove the error-return,
rename it to `supervisorOpts`, and inline it.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Always return a containerd shutdown wait function after successful
initialization, including when using an externally managed system containerd,
where the function is a no-op.
Use the returned function during the normal shutdown sequence, after the API
server has stopped, so managed and embedded containerd instances have finished
shutting down before tracing is torn down. Keep a deferred context cancellation
as a safeguard for early returns.
Bound OpenTelemetry shutdown to avoid blocking daemon shutdown indefinitely,
and defer returning ServeAPI errors until containerd and tracing shutdown have
completed.
Also report failures while waiting for containerd to stop instead of silently
discarding them.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Embedded containerd always derives its persistent root from Docker's
data root, which prevents testing against state from a standalone
containerd daemon.
Use DOCKER_CONTAINERD_ROOT as a temporary override for the exact root
path used by embedded and supervised containerd. Preserve the existing
data-root/containerd/daemon default when the variable is unset.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Route BuildKit's worker (and the Windows executor) over the in-memory
pipe instead of the unix socket.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Run containerd inside dockerd when the experimental
`embedded-containerd` feature is enabled through `--feature` or the
daemon configuration.
Serve containerd's gRPC API on a Unix socket, or a named pipe on
Windows, for the plugin executor and external tools.
Use an in-memory listener for dockerd's own containerd client. Serve
TTRPC on a platform endpoint so task shims can publish events.
Register only the containerd plugins dockerd needs. Leave CRI, sandbox,
streaming, transfer, NRI, and the restart monitor out of the embedded
server.
Reject `--cri-containerd` when embedded mode is enabled instead of
silently ignoring the requested CRI support.
Check the feature before `ContainerdAddr` so it can override the default
containerd socket supplied by packaged service units. Continue to use
the configured external containerd when the feature is disabled.
Derive the Windows named-pipe address from the daemon state directory so
multiple daemons can run on the same host. Restrict the pipes to the
built-in Administrators group and LocalSystem with the same protected
DACL as dockerd's API pipe, as the default security descriptor depends
on the process token and can expose the containerd endpoints more
broadly than intended. Treat embedded mode as a containerd runtime in
the Windows test environment.
Add the `no_embedded_containerd` build tag so distributors can omit the
embedded plugin graph and its dependencies.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
The supervisor (managed-containerd lifecycle) package manages a
containerd server rather than the libcontainerd client, so group them
under a new daemon/internal/containerd/server parent.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
This reapplies the af18206 commit which was reverted by ddb636c.
commit f74b856e1a added an [ExecReload] to
the systemd unit, which allows users to signal the daemon to reload its
config through systemd (`systemctl reload docker.service`).
While reloading works, systemd expects the `ExecReload` command to be
synchronous, so that it knows when the reload completes, and can account
for this when managing dependent services.
> Note however that reloading a daemon by enqueuing a signal (...) is usually
> not a good choice, because this is an asynchronous operation and hence not
> suitable when ordering reloads of multiple services against each other.
Systemd 253 introduced a new Type (Type=notify-reload, see [systemd#25916]),
which allows setting a "ReloadSignal" instead, if the service supports
it by including a [MONOTONIC_USEC] value in its "RELOADING=1"
notifications.
This patch:
- adds reload notifications to the daemon to notify when the daemon got
signaled to reload its configuration see [sd_notify(3)].
- appends a [MONOTONIC_USEC] value to the reload notification to support
systemd 253's notify-reload protocol. This is backwards-compatible
with older systemd releases as the systemd service manager ignores
unknown assignments in notifications.
- adds a `notifyReady` callback to notify when the reload finished,
which we currently send regardless if the reload was successful or
failed (which could be due to an invalid config).
[ExecReload]: https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html#ExecReload=
[systemd#25916]: https://github.com/systemd/systemd/pull/25916
[MONOTONIC_USEC]: https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html#MONOTONIC_USEC=…
[sd_notify(3)]: https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html#RELOADING=1
Signed-off-by: Cory Snider <csnider@mirantis.com>
Co-authored-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
The daemon previously signaled systemd (READY=1) before the API Serve loops
were started.
Move the readiness notification until after the API listeners are serving
to reduce the window where systemd considers the daemon ready but the
HTTP accept loop has not yet started.
While modifying, also use `WaitGroup.Go` for a slight cleanup.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Some services are shut-down in a defer, resulting in logs for them being
shut down logged after the "Daemon shutdown complete" log;
^CINFO[2026-02-21T16:57:55.312312593Z] Processing signal 'interrupt'
INFO[2026-02-21T16:57:55.424494218Z] shim disconnected id=1ed1fcfd71c27b5ff4f04c1b33104c17725a841fba7661acea205879fdd687c8 namespace=moby
INFO[2026-02-21T16:57:55.424642052Z] cleaning up after shim disconnected id=1ed1fcfd71c27b5ff4f04c1b33104c17725a841fba7661acea205879fdd687c8 namespace=moby
INFO[2026-02-21T16:57:55.424655718Z] cleaning up dead shim id=1ed1fcfd71c27b5ff4f04c1b33104c17725a841fba7661acea205879fdd687c8 namespace=moby
...
INFO[2026-02-21T16:57:55.535564427Z] stopping event stream following graceful shutdown error="<nil>" module=libcontainerd namespace=moby
INFO[2026-02-21T16:57:55.536002469Z] Daemon shutdown complete
INFO[2026-02-21T16:57:55.536108635Z] stopping healthcheck following graceful shutdown module=libcontainerd
INFO[2026-02-21T16:57:55.536799719Z] stopping event stream following graceful shutdown error="context canceled" module=libcontainerd namespace=plugins.moby
Move printing the log to a defer so that it's printed last:
^CINFO[2026-02-21T17:30:32.762078180Z] Processing signal 'interrupt'
INFO[2026-02-21T17:30:32.844606222Z] shim disconnected id=1ed1fcfd71c27b5ff4f04c1b33104c17725a841fba7661acea205879fdd687c8 namespace=moby
INFO[2026-02-21T17:30:32.844780972Z] cleaning up after shim disconnected id=1ed1fcfd71c27b5ff4f04c1b33104c17725a841fba7661acea205879fdd687c8 namespace=moby
INFO[2026-02-21T17:30:32.844787555Z] cleaning up dead shim id=1ed1fcfd71c27b5ff4f04c1b33104c17725a841fba7661acea205879fdd687c8 namespace=moby
...
INFO[2026-02-21T17:30:32.962354138Z] stopping event stream following graceful shutdown error="<nil>" module=libcontainerd namespace=moby
INFO[2026-02-21T17:30:32.962715347Z] stopping event stream following graceful shutdown error="context canceled" module=libcontainerd namespace=plugins.moby
INFO[2026-02-21T17:30:32.962760680Z] stopping healthcheck following graceful shutdown module=libcontainerd
INFO[2026-02-21T17:30:33.970766458Z] Daemon shutdown complete
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Before b0c8ff7d0c, system validation would
not take place until the daemon was actually started. This allowed (on
Windows) (un)registering the system service (`dockerd --register-service`,
`dockerd --unregister-service`) before installing other system requirements
(most notably, the Windows Containers feature).
This patch changes the behavior to allow this scenario; we perform validation
when explicitly requested (through the `--validate` flag), and perform the
same validation when starting the daemon.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
commit f74b856e1a added an [ExecReload] to
the systemd unit, which allows users to signal the daemon to reload its
config through systemd (`systemctl reload docker.service`).
While reloading works, systemd expects the `ExecReload` command to be
synchronous, so that it knows when the reload completes, and can account
for this when managing dependent services.
> Note however that reloading a daemon by enqueuing a signal (...) is usually
> not a good choice, because this is an asynchronous operation and hence not
> suitable when ordering reloads of multiple services against each other.
Systemd 253 introduced a new Type (Type=notify-reload, see [systemd#25916]),
which allows setting a "ReloadSignal" instead, if the service supports
it by including a [MONOTONIC_USEC] value in its "RELOADING=1"
notifications.
This patch:
- adds reload notifications to the daemon to notify when the daemon got
signaled to reload its configuration see [sd_notify(3)].
- appends a [MONOTONIC_USEC] value to the reload notification to support
systemd 253's notify-reload protocol. This is backwards-compatible
with older systemd releases as the systemd service manager ignores
unknown assignments in notifications.
- adds a `notifyReady` callback to notify when the reload finished,
which we currently send regardless if the reload was successful or
failed (which could be due to an invalid config).
[ExecReload]: https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html#ExecReload=
[systemd#25916]: https://github.com/systemd/systemd/pull/25916
[MONOTONIC_USEC]: https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html#MONOTONIC_USEC=…
[sd_notify(3)]: https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html#RELOADING=1
Signed-off-by: Cory Snider <csnider@mirantis.com>
Co-authored-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
These were called in a goroutine, likely to prevent them from affecting
performance, but doing so also means that there's no promise that the
notifications were actually sent before we continue.
Summarising the discussion from [PR 47358]:
These calls should not be particularly heavy-weight; They open a UNIX datagram
socket, write and close. (see the [go-systemd] implementation), and it's
unlikely these calls would block for a significant length of time unless pid 1
has become unresponsive, in which case you'd have much bigger problems. These
should be lightweight and fast as we can't imagine many C programs would be going
through the trouble of invoking `sd_notify()` in a background thread. Note that
the syslog API is also very similar: apps log by sending unixgrams to the `/dev/log`
socket.
[go-systemd]: https://github.com/coreos/go-systemd/blob/d5623bf85e8e73ae6352f78ee6b55a287619dd4e/daemon/sdnotify.go#L48-L84
[PR 47358]: https://github.com/moby/moby/pull/47358#discussion_r1488177590
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Setting the default host was implicitly handled in `normalizeHosts`; if
no hosts were provided, an empty entry was added to the list of hosts,
then passed through to `opts.ParseHost`, which handled an empty value
to set the default location (depending on TLS being enabled or XDG paths
to be used (when running with RootlessKit).
This patch makes the logic less magical:
- If no hosts are configured by the user (through CLI-flags or daemon.json),
then we append the default location.
- The handling for TLS listeners is open-coded for now; we need to decide
if we want to preserve this behavior (magically using TCP instead of a
unix-socket or named pipe if TLS is enabled).
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Move CheckSystem() call to newDaemonCLI() for earlier validation
of platform-specific requirements.
Signed-off-by: hiroto.toyoda <hiroto.toyoda@dena.com>
Move checkSystem() call from inside NewDaemon() to cli.start()
to validate system requirements earlier in the startup process.
Signed-off-by: hiroto.toyoda <hiroto.toyoda@dena.com>
The /grpc and /session endpoints are now deprecated as the Engine has
been upgraded to properly support HTTP/2 and h2c requests, making these
specialized endpoints unnecessary.
These endpoints will be removed in the next major API version to
complete the cleanup.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
This simplifies `dockerd-rootless.sh` by removing the workaround for
`CDI: Error associated with spec file /etc/cdi: failed to monitor for changes: permission denied`.
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
Export trace spans from the github.com/microsoft/hcsshim module, which
is instrumented with OpenCensus, to the daemon's OpenTelemetry exporter
to provide more visibility into Windows container lifecycle operations.
Signed-off-by: Cory Snider <csnider@mirantis.com>
- Introduced DefaultIsolation method in the Daemon to return the daemon configured isolation mode for Windows.
Signed-off-by: Vigilans <vigilans@foxmail.com>
The `LogLevel` and `LogFormat` options were defined in two locations;
- in the `daemon/commands.daemonOptions` struct.
- in the `daemon/config.Config` (`CommonConfig`) struct.
While we may need some options-struct to initialize the daemon, we currently
don't and the separate structs means they have to be kept in sync, and for
flags to be distributed across multiple places.
Note that some flags will not be configurable in the config-file (such as
the path of the config-file itself), so those options will need to have a
separate struct (which may still live in the `daemon/config` package).
This patch;
- Removes the `LogLevel` and `LogFormat` from `daemon/commands.daemonOptions`
to `daemon/config.CommonConfig`.
- Adds a bare-bones `stringVar` implementation using generics to allow using
strong-typed string values to be used for flags.
- Moves the flags together with the other flags in `installCommonConfigFlags`.
- Sets the default options in the `Config` struct.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
These consts are no longer used, and separate consts were added in both
the client and daemon packages;
- client: 41da5700a4
- daemon: a632b8495b
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This package is used internally by the daemon, and was only used out
side of the daemon by pkg/plugins (for which we still need to look
where it should be kept).
Making it internal because it's trivial to implement if needed by
anyone. The only reason it's a package is to keep it central, and
to make it easier to discover where we have rootlesskit-specific
codepaths in our codebase.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>