Commit Graph
121 Commits
Author SHA1 Message Date
Paweł Gronowski fae7dd19ad Merge pull request #53849 from corhere/ocihook
Move the setkey hook listener from libnetwork to the daemon
2026-10-27 21:15:43 +01:00
Sebastiaan van Stijn 1f11085c8e daemon: RestartSwarmContainers: handle context cancellation
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>
2026-10-12 18:39:42 +02:00
Cory Snider efa5230180 builder-next: set the sandbox key through ocihook
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
2026-10-07 19:06:00 -04:00
Paweł Gronowski 9c49ed8f9d Merge pull request #53867 from thaJeztah/signal_context
daemon/command: setupConfigReloadTrap: handle context cancellation
2026-10-07 16:19:54 +02:00
Sebastiaan van Stijn d80f8c6bc7 daemon/command: setupConfigReloadTrap: log reload event at info level
The Windows config reload event name includes the daemon PID and is
therefore determined dynamically at startup.

Log the event name at info level and expose it as a structured field so
users and tooling can discover which event to signal when requesting a
configuration reload.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-06 12:54:45 +02:00
Sebastiaan van Stijn 6e7e2aefa5 daemon/command: setupConfigReloadTrap: handle context cancellation
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>
2026-10-06 12:11:28 +02:00
Sebastiaan van Stijn 390fba50fe daemon/command: setupConfigReloadTrap: minor cleanup
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-06 12:11:28 +02:00
Sebastiaan van Stijn 81743b974a daemon/command: setupConfigReloadTrap: cleanup Windows event setup
Use the default security attributes when creating the config reload
event instead of passing an otherwise empty SecurityAttributes value.

Also handle errors from CreateEvent and close the event handle when the
reload goroutine exits.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-06 12:11:23 +02:00
Sebastiaan van Stijn 1a80fa4098 daemon: make Windows service unregistration idempotent
Treat an already absent service or one already marked for deletion as a
successful unregister operation.

Continue removing the event log registration in those cases so retries
also clean up stale registration state left by an earlier partial
unregister.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-02 14:19:18 +02:00
Sebastiaan van Stijn 6e077c1505 daemon: clean up Windows service after registration failure
Remove the Windows service if registration fails after it was created,
preventing a partially configured service from being left behind.

Keep the original registration error and treat errors encountered while
rolling back or closing the service handle as best-effort cleanup.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-02 14:07:30 +02:00
Sebastiaan van Stijn f66e638a93 daemon: handle Windows event log removal errors
Delete the Windows service before removing its event log source, so a
failure to delete the service does not leave an installed service without
its event log registration.

Also propagate errors from eventlog.Remove instead of silently ignoring
them.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-02 14:07:26 +02:00
Sebastiaan van Stijn bfc3c961b6 daemon/command/debug: fix restoring state in tests
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-09-18 18:28:42 +02:00
Sebastiaan van Stijn 073cfc5f1a vendor: github.com/containerd/log v0.2.0, with SetLevel
full diff: https://github.com/containerd/log/compare/v0.1.0...v0.2.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-09-11 17:12:50 +02:00
Paweł Gronowski f28c749752 daemon/command: Replace deprecated tracing log hook
NewLogrusHook from containerd/pkg/tracing will be deprecated in 2.4

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-09-10 17:59:42 +02:00
Paweł Gronowski f8b81d9066 daemon: Refactor namegenerator into extension
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>
2026-09-03 11:06:16 +02:00
Sebastiaan van Stijn f675ce2ae9 Merge pull request #52771 from vvoland/apparmor-custom-profiles
daemon: add ability for custom AppArmor profiles
2026-08-28 22:27:21 +02:00
Paweł Gronowski da33e19d2f daemon: Preserve ordered extension configuration
Keep extension-config keyed by ID in daemon.json while retaining its
source order in Go and when re-marshaled. Validate IDs during decoding
and distinguish extension directories with the extension-dirs key.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-08-26 22:33:41 +02:00
Paweł Gronowski ad1af3b58c daemon/command: Route extension gRPC requests
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>
2026-08-26 22:33:40 +02:00
Paweł Gronowski 08d0b9d47d daemon: Add extension configuration
Add `--extension-dir` and `extension-config` support so the extension
host can discover binaries and receive per-extension settings.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-08-26 22:33:40 +02:00
Aleksa Sarai 7bdd547617 daemon: add ability for custom AppArmor profiles
This is a long-requested feature, and it solves several usability
problems with the default AppArmor profile:

1. The profile is completely opaque because we don't write to
  /etc/apparmor.d anymore -- this leads to lots of headaches when
  trying to run certain semi-privileged programs inside containers.
  It's much nicer to be able to have a starting point for a custom
  AppArmor profile.

2. Changes to AppArmor have broken backwards compatibility in the past
  (leading to containers not working properly) -- the poster-child for
  this problem was signal mediation. In order to fix this problem,
  distributions had to patch Docker when it would've been much nicer
  to provide a hotfix in the form of a custom configuration they could
  apply to their hosts.

It also bridges the feature gap between the default seccomp profile
(which has been configurable for a very long time). This patch also
fixes a few minor bugs in the AppArmor profile implementation (notably,
Docker would not forcefully load its built-in profile at start time --
meaning a Docker update wouldn't actually update the profile).

This feature should probably be ported to other container runtimes
(containerd, podman/cri-o, etc) so that we can continue with the effort
to merge all of the disparate AppArmor profile implementations. Ideally
they would all use the same template variables too.

Signed-off-by: Aleksa Sarai <asarai@suse.de>

---

The above was reapplied from the original commit on top of the current
daemon code.

The daemon already force-loads the default AppArmor profile at startup,
so this change wires the configured template into that existing reload
path instead of introducing the reload behavior itself.

The built-in profile now lives in github.com/moby/profiles/apparmor, so
the custom template data follows the current profile variables.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-08-24 13:13:35 +02:00
Sebastiaan van Stijn b25f366ced containerd: fall back to embedded when binary is unavailable
Fall back to the embedded containerd implementation when no system containerd
is configured or running and the managed containerd binary cannot be found.

Keep other managed-containerd startup failures fatal so configuration,
permission, and runtime errors are not silently masked by the fallback.

Apply the same behavior on Unix and Windows.

This moves the default fallback toward the embedded implementation, allowing
the managed-containerd path to be deprecated or removed in the future.

With this patch, the daemon can be started without the containerd binary present;

    command -v containerd || echo 'containerd binary not found'
    containerd binary not found

    dockerd
    INFO[2026-08-16T15:05:35.341440421Z] Starting up
    INFO[2026-08-16T15:05:35.344028963Z] containerd not running, starting managed containerd
    INFO[2026-08-16T15:05:35.344604171Z] containerd binary not found, starting embedded containerd  error="failed to find containerd binary: containerd: exec: \"containerd\": executable file not found in $PATH"
    WARN[2026-08-16T15:05:35.344616963Z] Running with experimental embedded-containerd mode
    INFO[2026-08-16T15:05:35.344720338Z] starting embedded containerd server           address=/var/run/docker/containerd/containerd.sock
    ...
    INFO[2026-08-16T15:05:36.191205463Z] Daemon has completed initialization
    INFO[2026-08-16T15:05:36.191244088Z] API listen on /var/run/docker.sock

One thing worth noting is that it currently does not check for the shim to
be present; the daemon starts successfully;

    command -v containerd-shim-runc-v2 || echo 'containerd shim not found'
    containerd shim not found

    dockerd
    ...
    INFO[2026-08-16T15:05:36.191205463Z] Daemon has completed initialization
    INFO[2026-08-16T15:05:36.191244088Z] API listen on /var/run/docker.sock

Pulling images also works, but the container fails to start;

    docker run --rm --quiet alpine
    docker: Error response from daemon: failed to create task for container: failed to start shim: failed to resolve runtime path: runtime "io.containerd.runc.v2" binary not installed "containerd-shim-runc-v2": file does not exist

Daemon logs;

    INFO[2026-08-16T15:08:56.091416375Z] image pulled                                  digest="sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b" remote="docker.io/library/alpine:latest"
    ERRO[2026-08-16T15:08:56.134184333Z] copy stream failed                            error="reading from a closed fifo" stream=stdout
    ERRO[2026-08-16T15:08:56.134201042Z] copy stream failed                            error="reading from a closed fifo" stream=stderr
    ERRO[2026-08-16T15:08:56.139684375Z] Handler for POST /containers/{name:.*}/start returned error  error-response="failed to create task for container: failed to start shim: failed to resolve runtime path: runtime \"io.containerd.runc.v2\" binary not installed \"containerd-shim-runc-v2\": file does not exist" method=POST module=api request-url=/v1.55/containers/5cdb5c75a4c5e2b6f8a46c14258d9aded81d7e8fd824a1158d613f8704356ecd/start status=500 vars="map[name:5cdb5c75a4c5e2b6f8a46c14258d9aded81d7e8fd824a1158d613f8704356ecd version:1.55]"
    INFO[2026-08-16T15:09:29.483493418Z] image pulled                                  digest="sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b" remote="docker.io/library/alpine:latest"
    ERRO[2026-08-16T15:09:29.518634168Z] copy stream failed                            error="reading from a closed fifo" stream=stdout
    ERRO[2026-08-16T15:09:29.518660043Z] copy stream failed                            error="reading from a closed fifo" stream=stderr
    ERRO[2026-08-16T15:09:29.524466210Z] Handler for POST /containers/{name:.*}/start returned error  error-response="failed to create task for container: failed to start shim: failed to resolve runtime path: runtime \"io.containerd.runc.v2\" binary not installed \"containerd-shim-runc-v2\": file does not exist" method=POST module=api request-url=/v1.55/containers/6ca6224313a2bdc595d108702f89fe88abd97b6ebe021ddcc8b0dce402057cfa/start status=500 vars="map[name:6ca6224313a2bdc595d108702f89fe88abd97b6ebe021ddcc8b0dce402057cfa version:1.55]"

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-08-24 12:04:14 +02:00
Sebastiaan van Stijn 4c3d81a3fd containerd: split supervisor construction from start
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>
2026-08-23 14:53:16 +02:00
Sebastiaan van Stijn 2b27696c37 containerd: simplify supervisor option construction
`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>
2026-08-23 14:53:15 +02:00
Sebastiaan van Stijn fb21f97c41 containerd: make shutdown waiting explicit
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>
2026-08-23 14:52:56 +02:00
Sebastiaan van Stijn 648335c688 daemon: remove OpenCensus-to-OTEL trace bridge
Hcsshim v0.15.0-rc.4 no longer uses opencensus (since [hcsshim@0f25a01]),
so we can remove the bridge that was added in [moby@4535d63].

This reverts commit 4535d63c91.

[hcsshim@0f25a01]: https://github.com/microsoft/hcsshim/commit/0f25a0125d95e6932d27fde08d1436414819e29a
[moby@4535d63]: https://github.com/moby/moby/commit/4535d63c91bd7d2d2767346965f24ec5e6e5f28d

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-08-19 11:39:17 +02:00
Paweł Gronowski 99c1a9c778 daemon: Add configurable default container stop timeout
A container that defines no stop timeout of its own always got 10
seconds on Linux, or 30 on Windows, to shut down before being killed.
The value was a constant in the container package, so operators who
wanted a different grace period had to pass `--stop-timeout` on every
container.

Add a `default-stop-timeout` daemon flag and configuration file option
that supplies that fallback. Stopping a container, killing it, and
computing the daemon shutdown timeout take the value from the daemon
configuration when the container has no timeout of its own, so an
explicit per-container timeout still wins and the container
configuration itself stays untouched. The option can be reloaded, and
negative values are rejected.

mergo cannot tell an unset option from a zero value, so a configured
timeout of `0`, meaning "kill immediately", would be replaced by the
non-zero flag default while merging. Remember whether the
configuration file set the option, and restore its value after the
merge.

`ContainerConfig.StopTimeout` in the API documentation no longer
claims a fixed default of 10 seconds, because the fallback is now
whatever `default-stop-timeout` holds.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-07-27 14:15:55 +02:00
Paweł Gronowski 6d2a4259fb daemon: Allow overriding containerd root from environment
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>
2026-07-24 16:41:18 +02:00
Paweł Gronowski f6f6738a6f daemon/containerd: Fork server bootstrap code
Fork containerd's `cmd/containerd/server` bootstrap into the embedded
package instead of vendoring it, so dockerd owns the plugin graph and
the server lifecycle and only pulls in what the embedded server needs.

The forked server also shuts down cleanly: closing only the ttrpc
listener leaves accepted shim connections and their request contexts
alive after the embedded containerd stops, so cancel the server context
and close the ttrpc server before tearing down plugins. This also lets
the server own listener closure and avoids concurrent Close calls during
shutdown.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-07-24 16:41:07 +02:00
Paweł Gronowski 3b858893a7 builder-next: Use in-memory pipe for embedded containerd
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>
2026-07-24 16:39:06 +02:00
Paweł Gronowski a8a1cfd111 daemon: Add embedded containerd mode
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>
2026-07-24 16:39:06 +02:00
Paweł Gronowski 1e6c7a4b2a libcontainerd: Move supervisor under daemon/internal/containerd/server
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>
2026-07-24 16:39:06 +02:00
Paweł Gronowski aa9c2f20b8 daemon: Set umask to 0000
Previously the daemon forced its umask to 0022, which silently stripped
the group/other-write bits from any explicitly requested file mode.

This caused e.g. `COPY --chmod=777` to result in 0755 rather than 0777.

Clear the umask so explicit modes are honored.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-06-17 14:22:50 +02:00
Sebastiaan van Stijn 99c81194be daemon: windows: remove stray error log on service shutdown
runDaemon would unconditionally send an error event if the daemon
was running as a system service;

    Run New-Item -ItemType Directory -Force -Path ".\bundles" | Out-Null
    2026-06-08T03:31:52.1865738Z [Information] Starting up
    2026-06-08T03:31:52.3160498Z [Information] OTEL tracing is not configured, using no-op tracer provider
    2026-06-08T03:31:52.5037110Z [Information] Windows default isolation mode: process
    2026-06-08T03:31:52.7212058Z [Information] Loading containers: start.
    2026-06-08T03:31:52.7345902Z [Information] [graphdriver] trying configured driver: windowsfilter
    2026-06-08T03:31:52.8920546Z [Information] Restoring containers: start.
    2026-06-08T03:31:52.9910057Z [Information] Restoring existing overlay networks from HNS into docker
    2026-06-08T03:31:53.8958218Z [Information] Loading containers: done.
    2026-06-08T03:31:53.9093383Z [Information] Docker daemon [storage-driver=windowsfilter containerd-snapshotter=false version=29.1.5 commit=3b01d641]
    2026-06-08T03:31:53.9103431Z [Information] Initializing buildkit
    2026-06-08T03:31:54.3243456Z [Information] Completed buildkit initialization
    2026-06-08T03:31:54.4878293Z [Information] Daemon has completed initialization
    2026-06-08T03:31:54.4881959Z [Information] API listen on //./pipe/docker_engine
    2026-06-08T03:47:45.7182269Z [Information] Processing signal 'terminated'
    2026-06-08T03:47:45.7203206Z [Information] Daemon shutdown complete
    Error: 2026-06-08T03:47:45.7206236Z [Error] <nil>

If debug was enabled, it would log this error twice (once as error, and once as debug).

Let's make this a single log, and only an error if there was one. Note that this may still
be redundant, as `daemonCLI.start` also logs this error;
https://github.com/moby/moby/blob/4c19a015750813d4a289879e1e387d374d7403cd/daemon/command/daemon.go#L127-L134

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-06-12 12:45:14 +02:00
Sebastiaan van Stijn 6d39b4ebed daemon/config: set userland-proxy default value in config.New
Set the default as part of the default config, instead of depending on the default
value set in the command-line flags. We should probably consider doing the same
for most (all) other defaults that are not a zero-value.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-05-13 12:42:33 +02:00
Sebastiaan van Stijn c4122f3bc2 daemon/config: set default log-driver in config.New
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-05-12 17:04:25 +02:00
Paweł Gronowski 4c19a01575 Merge pull request #52048 from shiv-tyagi/vendor-detection
Use CDI  for GPU injection for AMD devices for --gpus
2026-03-05 12:06:54 +00:00
Shiv Tyagi 561a5a9b36 Use CDI for GPU injection for AMD devices for --gpus
Signed-off-by: Shiv Tyagi <Shiv.Tyagi@amd.com>
2026-03-04 13:07:26 +00:00
Cory SniderandSebastiaan van Stijn 40f06bf418 Reapply: daemon/command: add support for sd_notify "reload" notifications
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>
2026-02-26 12:08:46 +01:00
Sebastiaan van Stijn 1a1749a082 Merge pull request #52077 from thaJeztah/notify_readier
daemon: send systemd READY=1 after API serve loops start
2026-02-23 14:05:02 +01:00
Sebastiaan van Stijn 99add78b1f daemon: send systemd READY=1 after API serve loops start
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>
2026-02-23 12:04:16 +01:00
Sebastiaan van Stijn 5f3c4002bd daemon: fix "Daemon shutdown complete" log arriving too early
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>
2026-02-21 19:43:43 +01:00
Paweł Gronowski c6ca7d49f9 Revert "daemon/command: don't make notifyReady(), notifyStopping() asynchronous"
This reverts commit 236fc46b5a.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-02-13 13:05:09 +01:00
Paweł Gronowski 5bdfdc0919 Revert "daemon/command: send notifyReady, notifyStopping synchronous"
This reverts commit 0e523625f8.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-02-13 13:05:07 +01:00
Paweł Gronowski ddb636c2bd Revert "daemon/command: add support for sd_notify "reload" notifications"
This reverts commit af18206630.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-02-13 13:05:06 +01:00
Sebastiaan van Stijn d9f16785f9 daemon: warn for unmet system requirements after service registration
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-02-05 21:59:45 +01:00
Sebastiaan van Stijn b8c6046f74 daemon: allow service registration on Windows with missing system dependencies
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>
2026-02-05 21:20:50 +01:00
Cory SniderandSebastiaan van Stijn af18206630 daemon/command: add support for sd_notify "reload" notifications
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>
2026-02-03 12:25:25 -05:00
Sebastiaan van Stijn 0e523625f8 daemon/command: send notifyReady, notifyStopping synchronous
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>
2026-02-03 12:24:08 -05:00
Sebastiaan van Stijn 236fc46b5a daemon/command: don't make notifyReady(), notifyStopping() asynchronous
Leave it to the consumer to decide whether these should be called in a
goroutine.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-02-03 12:24:08 -05:00
Sebastiaan van Stijn 8afb45b42f loadDaemonCliConfig: explicitly set default host
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>
2026-01-26 16:51:41 +01:00