moby/moby
Swarm cluster
Purpose
When the daemon is in swarm mode, it embeds a SwarmKit manager and/or agent. Users interact with services, tasks, secrets, configs, and nodes — higher-level primitives than containers. Swarm mode is opt-in (docker swarm init / docker swarm join).
The integration code lives in daemon/cluster/. The actual SwarmKit library is github.com/moby/swarmkit/v2, vendored in.
Layout
daemon/cluster/
├── cluster.go # Cluster object + lifecycle (init, join, leave, lock/unlock)
├── swarm.go # API-facing helpers for swarm config and join/leave
├── nodes.go # Node API
├── services.go # Service create/update/inspect/list/remove
├── tasks.go # Task list/inspect
├── secrets.go # Secrets
├── configs.go # Configs
├── networks.go # Cluster-scoped networks (overlay)
├── volumes.go # Cluster volumes (CSI)
├── helpers.go # Conversions, validation
├── filters.go, errors.go
├── listen_addr.go # Manager listen address resolution
├── noderunner.go # Wraps the SwarmKit node lifecycle
├── controllers/ # Task controllers (run a service task as a local container)
├── convert/ # API <-> SwarmKit type conversions
├── executor/ # Containerd-backed executor for swarm tasks
├── provider/ # Adapter exposing swarm state to libnetwork (cluster.Provider)
└── internal/ # Internal helpersLifecycle
graph TD Init[docker swarm init] --> NodeRunner[noderunner: start SwarmKit Node] Join[docker swarm join] --> NodeRunner NodeRunner --> Manager[Manager goroutine?] NodeRunner --> Agent[Agent goroutine] Manager --> Raft[Raft + dispatcher] Agent --> Executor[executor/ -> containerd] Daemon -->|cluster.Provider| Libnetwork[libnetwork]
noderunner.go wraps the SwarmKit Node with reload + state-machine handling. On a manager node it runs both manager (Raft, dispatcher, scheduler, allocator) and agent. On a worker node only the agent runs. The agent uses the Moby-specific executor in executor/ which spawns service tasks as local containers via the daemon's containerd client.
API surface
The swarm router lives at daemon/server/router/swarm/ and covers /swarm, /services, /tasks, /nodes, /secrets, /configs. Each handler ultimately calls a method on Cluster (cluster.go). The conversions between API types (under api/types/swarm/) and SwarmKit protobuf types live in convert/.
Tasks become containers
When the SwarmKit scheduler assigns a task to this node, the agent invokes executor/. The executor:
- Translates the SwarmKit task spec to a Moby
container.Config/HostConfig. - Pulls the image (via the Image management path).
- Calls
Daemon.CreateContainerandDaemon.StartContainer. - Streams logs and exit info back to SwarmKit.
This is why a swarm-mode task is just a regular Moby container with extra labels — the local daemon handles the actual lifecycle.
Cluster-aware networking
The libnetwork controller exposes a cluster.Provider interface that daemon/cluster/provider/ implements. It feeds:
- The list of cluster-scoped networks (overlay networks created via swarm).
- The local node ID, manager status, and bind addresses.
- Service and task discovery used by the embedded DNS for service VIPs and DNSRR.
This is what makes overlay networks work across a swarm: libnetwork's networkdb gossiping is anchored to the same memberlist used by SwarmKit's dispatcher.
CSI volumes
volumes.go and the cluster-volume types in api/types/swarm/ implement cluster-scoped CSI volumes. The daemon talks to a CSI plugin via gRPC and tracks volume attachments per task.
Secrets and configs
Swarm secrets and configs are stored in the manager's Raft store, encrypted with cluster-wide keys. The agent fetches them per-task and mounts them into the container as files (under /run/secrets/... for secrets). Plumbing lives in secrets.go and configs.go.
Lock / unlock
A swarm can be encrypted at rest. When locked, the Raft store cannot be opened until the operator supplies the unlock key. The flow lives in cluster.go (Cluster.GetUnlockKey, Cluster.UnlockSwarm).
Tests
Integration tests for swarm live under integration/service/, integration/secret/, integration/network/, and integration-cli/ (legacy).
Entry points for modification
- New swarm API field: update
api/swagger.yaml, the type underapi/types/swarm/, the router, the converter inconvert/, and the SwarmKit conversion in the manager. - Task controller behavior: see
controllers/andexecutor/. - Cluster networking adapter:
provider/.
See also
- Networking (libnetwork) for overlay and
networkdb. - Container runtime for how tasks become containerd tasks.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.