Documentation
¶
Overview ¶
Package docker is a Docker-backed provider.Provider. It maps each ctrlplane Instance to one Docker container, named "cp-<instanceID>" so lookups by ID are O(1) inspect calls.
Index ¶
- Variables
- type Config
- type Option
- type Provider
- func (p *Provider) Capabilities() []provider.Capability
- func (p *Provider) Deploy(ctx context.Context, req provider.DeployRequest) (*provider.DeployResult, error)
- func (p *Provider) Deprovision(ctx context.Context, instanceID id.ID) error
- func (p *Provider) Exec(_ context.Context, _ id.ID, _ provider.ExecRequest) (*provider.ExecResult, error)
- func (p *Provider) HealthCheck(ctx context.Context) (*provider.HealthStatus, error)
- func (p *Provider) Info() provider.ProviderInfo
- func (p *Provider) Logs(ctx context.Context, instanceID id.ID, opts provider.LogOptions) (io.ReadCloser, error)
- func (p *Provider) Provision(ctx context.Context, req provider.ProvisionRequest) (*provider.ProvisionResult, error)
- func (p *Provider) Resources(ctx context.Context, instanceID id.ID) (*provider.ResourceUsage, error)
- func (p *Provider) Restart(ctx context.Context, instanceID id.ID) error
- func (p *Provider) Rollback(_ context.Context, _ id.ID, _ id.ID) error
- func (p *Provider) Scale(_ context.Context, _ id.ID, _ provider.ResourceSpec) error
- func (p *Provider) Start(ctx context.Context, instanceID id.ID) error
- func (p *Provider) Status(ctx context.Context, instanceID id.ID) (*provider.InstanceStatus, error)
- func (p *Provider) Stop(ctx context.Context, instanceID id.ID) error
Constants ¶
This section is empty.
Variables ¶
var ErrLogsNotImplemented = errors.New("docker: logs not implemented")
ErrLogsNotImplemented is returned when log streaming is requested but the docker exec/logs path hasn't been wired yet.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// Host is the Docker daemon address (e.g., unix:///var/run/docker.sock).
Host string `env:"CP_DOCKER_HOST" json:"host"`
// Network is the Docker network to attach containers to.
Network string `default:"bridge" env:"CP_DOCKER_NETWORK" json:"network"`
// Registry is the default image registry prefix.
Registry string `env:"CP_DOCKER_REGISTRY" json:"registry,omitempty"`
}
Config holds configuration for the Docker provider.
type Option ¶ added in v1.3.0
Option configures a Docker provider.
func WithConfig ¶ added in v1.3.0
WithConfig applies all non-zero fields from a Config struct. This is useful when loading configuration from files or environment variables.
func WithHost ¶ added in v1.3.0
WithHost sets the Docker daemon address (e.g., "unix:///var/run/docker.sock").
func WithNetwork ¶ added in v1.3.0
WithNetwork sets the Docker network to attach containers to.
func WithRegistry ¶ added in v1.3.0
WithRegistry sets the default image registry prefix.
type Provider ¶
type Provider struct {
// contains filtered or unexported fields
}
Provider is a Docker-based infrastructure provider. Each Instance becomes one container; the container name encodes the instance ID for stateless lookups (no per-instance ProviderRef storage needed beyond the canonical "docker:<container_name>" string).
func New ¶
New creates a new Docker provider. Uses standard docker env (DOCKER_HOST, DOCKER_TLS_VERIFY, etc.) by default; pass WithHost to pin a specific socket. Network defaults to "bridge" but should be overridden to a named network when the provider is colocated with a router (e.g. Traefik) that needs to reach containers by DNS name.
func (*Provider) Capabilities ¶
func (p *Provider) Capabilities() []provider.Capability
Capabilities returns the set of features this provider supports.
func (*Provider) Deploy ¶
func (p *Provider) Deploy(ctx context.Context, req provider.DeployRequest) (*provider.DeployResult, error)
Deploy applies a new image / env to an existing container by recreating it. Docker doesn't support in-place image swap, so the implementation is: stop+remove the current container, then create a fresh one with the new spec. Same name, same network, new image.
For the initial provision case (where Provision already ran with the right image) Deploy is effectively a no-op — the container stays as-is. The caller (ctrlplane deploy.Service) treats success here as "release applied" and bumps the deployment state. Deploy applies per-service image / env updates by recreating only the targeted containers within the live project network. Services not listed in req.Services keep running unchanged.
Per-service rollout for a multi-container project is "stop & replace each targeted container in turn" — Docker doesn't support in-place image swap. The Compose-project network stays up across the recreation so sibling services don't drop their network namespace.
func (*Provider) Deprovision ¶
Deprovision tears down every container in the project + the project network. Not-found is treated as success so deprovision is convergent — the goal is "project gone", not strict accounting.
func (*Provider) Exec ¶
func (p *Provider) Exec(_ context.Context, _ id.ID, _ provider.ExecRequest) (*provider.ExecResult, error)
Exec is not yet implemented.
func (*Provider) HealthCheck ¶ added in v1.5.1
HealthCheck pings the docker daemon and reports reachability. The HealthChecker contract is "is this provider's control plane reachable" — so we use cli.Ping (which round-trips to the daemon) rather than docker info / version which load more state.
func (*Provider) Info ¶
func (p *Provider) Info() provider.ProviderInfo
Info returns metadata about this provider. Local Docker has a fixed region of "local" with a default localhost location so studio catalog endpoints surface a usable region in dev environments where no datacenters have been registered yet.
func (*Provider) Logs ¶
func (p *Provider) Logs(ctx context.Context, instanceID id.ID, opts provider.LogOptions) (io.ReadCloser, error)
Logs returns a stream of structured JSON log events (one {"ts":..., "stream":"stdout"|"stderr", "line":"..."} per line) from the container's stdout + stderr. When opts.Follow is true the stream stays open and emits new lines as the container writes them; the caller closes the returned ReadCloser to stop.
Honours opts.Tail (last N lines, "0" = all), opts.Since (only lines newer than this UTC time), and opts.Follow. Multiplexed docker frames are demuxed by demuxedDockerStream.
func (*Provider) Provision ¶
func (p *Provider) Provision(ctx context.Context, req provider.ProvisionRequest) (*provider.ProvisionResult, error)
Provision pulls the image, creates a container with the requested ports/env/labels, starts it, and returns the resulting endpoints.
Endpoints are emitted in two flavours per declared port:
- in-network: http://cp-<instanceID>:<containerPort> — reachable from other containers on the same docker network. Preferred for service-to-service routing (Traefik joins this network and uses these URLs upstream).
- public: http://localhost:<hostPort> — the random host port docker assigned. Useful when hitting a workspace from outside the docker network without a host-side proxy.
Re-provisioning the same instance ID is idempotent: any existing container with the same name is force-removed first so the create succeeds with the fresh config.
func (*Provider) Resources ¶
func (p *Provider) Resources(ctx context.Context, instanceID id.ID) (*provider.ResourceUsage, error)
Resources returns a one-shot point-in-time sample of the container's CPU / memory / network usage via the docker stats API. The non-streaming variant gives us a single JSON document per call, which is what the metrics poller wants — it calls us every N seconds and stores the result in its own ring buffer.
Returns a zero-valued ResourceUsage (no error) when the container doesn't exist or the stats response is empty — the metrics poller treats "missing sample" as a gap, not a failure, so transient container-restart windows don't show up as poller errors.
func (*Provider) Restart ¶
Restart cycles every Main + Sidecar container in the project. Inits stay completed — restart is for live workload bouncing, not init re-runs.
func (*Provider) Rollback ¶
Rollback is a no-op today — docker has no built-in release history, so rollback would have to recreate using the previous image which the deploy service already knows about and could route through Deploy.
func (*Provider) Scale ¶
Scale is a no-op for the docker provider — single-container instances don't have a horizontal scale axis. The kubernetes provider is the right home for replica scaling.
func (*Provider) Start ¶
Start starts every Main + Sidecar container in the project. Init services are not restarted — they ran-once during provision.
func (*Provider) Status ¶
Status aggregates inspect across every container in the project. Worst-of state wins (any Failed → Failed; otherwise any Restarting → Starting; otherwise any not-Running → Stopped). Ready is true only when every Main + Sidecar reports Running. Init containers don't gate readiness once they've completed (they appear as Stopped/exited 0 — the non-Init aggregation ignores them).