// Package spec defines a normalized, JSON-serializable description of a Docker // container and everything it needs to be recreated on another host. // // The spec is deliberately independent of the Docker SDK types: it is produced // on the source host, travels over SSH or inside an offline migration package, // and is consumed either by the SSH engine or by a generated shell script that // only has the docker CLI available. package spec // MountKind classifies a data location attached to a container. type MountKind string const ( MountVolume MountKind = "volume" // named volume MountAnonymous MountKind = "anonymous" // volume with a generated name MountBind MountKind = "bind" // host directory or file MountTmpfs MountKind = "tmpfs" // in-memory, never carries data ) // Mount is one data location attached to a container. type Mount struct { Kind MountKind `json:"kind"` Name string `json:"name,omitempty"` // volume name (volume kind only) Source string `json:"source,omitempty"` // host path (bind kind only) Destination string `json:"destination"` // path inside the container ReadOnly bool `json:"readOnly"` Propagation string `json:"propagation,omitempty"` TmpfsOpts string `json:"tmpfsOpts,omitempty"` // SizeBytes is a best-effort measurement of the data at this location, // used to show progress and to warn about very large transfers. -1 = unknown. SizeBytes int64 `json:"sizeBytes"` } // HasData reports whether this mount is worth copying. tmpfs never is. func (m Mount) HasData() bool { return m.Kind != MountTmpfs } // Volume describes a named volume so it can be recreated with the same driver, // options and labels rather than falling back to a plain local volume. type Volume struct { Name string `json:"name"` Driver string `json:"driver"` DriverOpts map[string]string `json:"driverOpts,omitempty"` Labels map[string]string `json:"labels,omitempty"` } // IPAMPool is one subnet definition of a user-defined network. type IPAMPool struct { Subnet string `json:"subnet,omitempty"` IPRange string `json:"ipRange,omitempty"` Gateway string `json:"gateway,omitempty"` AuxAddress map[string]string `json:"auxAddress,omitempty"` } // Network describes a user-defined network to recreate on the target. type Network struct { Name string `json:"name"` Driver string `json:"driver"` Scope string `json:"scope,omitempty"` EnableIPv6 bool `json:"enableIPv6,omitempty"` Internal bool `json:"internal,omitempty"` Attachable bool `json:"attachable,omitempty"` Ingress bool `json:"ingress,omitempty"` IPAMDriver string `json:"ipamDriver,omitempty"` IPAMPools []IPAMPool `json:"ipamPools,omitempty"` Options map[string]string `json:"options,omitempty"` Labels map[string]string `json:"labels,omitempty"` } // Endpoint is a container's attachment to one network. type Endpoint struct { Network string `json:"network"` Aliases []string `json:"aliases,omitempty"` IPv4Address string `json:"ipv4Address,omitempty"` IPv6Address string `json:"ipv6Address,omitempty"` MacAddress string `json:"macAddress,omitempty"` Links []string `json:"links,omitempty"` DriverOpts map[string]string `json:"driverOpts,omitempty"` } // PortBinding maps a container port onto the host. type PortBinding struct { ContainerPort string `json:"containerPort"` // e.g. "80/tcp" HostIP string `json:"hostIp,omitempty"` HostPort string `json:"hostPort,omitempty"` } // Healthcheck mirrors the container health configuration when it was // overridden at run time (an image-provided healthcheck is not re-emitted). type Healthcheck struct { Test []string `json:"test,omitempty"` Interval int64 `json:"interval,omitempty"` // nanoseconds Timeout int64 `json:"timeout,omitempty"` // nanoseconds StartPeriod int64 `json:"startPeriod,omitempty"` // nanoseconds Retries int `json:"retries,omitempty"` } // Resources holds the cgroup limits applied to the container. type Resources struct { Memory int64 `json:"memory,omitempty"` MemoryReservation int64 `json:"memoryReservation,omitempty"` MemorySwap int64 `json:"memorySwap,omitempty"` MemorySwappiness *int64 `json:"memorySwappiness,omitempty"` NanoCPUs int64 `json:"nanoCpus,omitempty"` CPUShares int64 `json:"cpuShares,omitempty"` CPUPeriod int64 `json:"cpuPeriod,omitempty"` CPUQuota int64 `json:"cpuQuota,omitempty"` CpusetCpus string `json:"cpusetCpus,omitempty"` CpusetMems string `json:"cpusetMems,omitempty"` PidsLimit *int64 `json:"pidsLimit,omitempty"` OomKillDisable *bool `json:"oomKillDisable,omitempty"` OomScoreAdj int `json:"oomScoreAdj,omitempty"` ShmSize int64 `json:"shmSize,omitempty"` } // Ulimit is a per-container resource limit. type Ulimit struct { Name string `json:"name"` Soft int64 `json:"soft"` Hard int64 `json:"hard"` } // Device is a host device exposed to the container. type Device struct { PathOnHost string `json:"pathOnHost"` PathInContainer string `json:"pathInContainer"` CgroupPermissions string `json:"cgroupPermissions"` } // Container is the full normalized description of one container. type Container struct { ID string `json:"id"` Name string `json:"name"` // without the leading slash State string `json:"state"` // running, exited, ... Image string `json:"image"` // reference as the user wrote it, e.g. nginx:1.27 ImageID string `json:"imageId"` // sha256:... ImageDigest string `json:"imageDigest,omitempty"` // Compose grouping, taken from the standard compose labels. Empty when the // container was not created by docker compose. ComposeProject string `json:"composeProject,omitempty"` ComposeService string `json:"composeService,omitempty"` Hostname string `json:"hostname,omitempty"` Domainname string `json:"domainname,omitempty"` User string `json:"user,omitempty"` WorkingDir string `json:"workingDir,omitempty"` Env []string `json:"env,omitempty"` Labels map[string]string `json:"labels,omitempty"` Cmd []string `json:"cmd,omitempty"` Entrypoint []string `json:"entrypoint,omitempty"` EntrypointSet bool `json:"entrypointSet,omitempty"` // true when overridden at run time CmdSet bool `json:"cmdSet,omitempty"` Tty bool `json:"tty,omitempty"` OpenStdin bool `json:"openStdin,omitempty"` StopSignal string `json:"stopSignal,omitempty"` StopTimeout *int `json:"stopTimeout,omitempty"` Init *bool `json:"init,omitempty"` RestartPolicy string `json:"restartPolicy,omitempty"` RestartMaxRetries int `json:"restartMaxRetries,omitempty"` AutoRemove bool `json:"autoRemove,omitempty"` Privileged bool `json:"privileged,omitempty"` ReadonlyRootfs bool `json:"readonlyRootfs,omitempty"` CapAdd []string `json:"capAdd,omitempty"` CapDrop []string `json:"capDrop,omitempty"` SecurityOpt []string `json:"securityOpt,omitempty"` GroupAdd []string `json:"groupAdd,omitempty"` Sysctls map[string]string `json:"sysctls,omitempty"` Devices []Device `json:"devices,omitempty"` Ulimits []Ulimit `json:"ulimits,omitempty"` Runtime string `json:"runtime,omitempty"` PidMode string `json:"pidMode,omitempty"` IpcMode string `json:"ipcMode,omitempty"` UtsMode string `json:"utsMode,omitempty"` UsernsMode string `json:"usernsMode,omitempty"` CgroupnsMode string `json:"cgroupnsMode,omitempty"` DNS []string `json:"dns,omitempty"` DNSSearch []string `json:"dnsSearch,omitempty"` DNSOptions []string `json:"dnsOptions,omitempty"` ExtraHosts []string `json:"extraHosts,omitempty"` NetworkMode string `json:"networkMode,omitempty"` // bridge, host, none, , container: Endpoints []Endpoint `json:"endpoints,omitempty"` Ports []PortBinding `json:"ports,omitempty"` ExposedPorts []string `json:"exposedPorts,omitempty"` PublishAll bool `json:"publishAll,omitempty"` Mounts []Mount `json:"mounts,omitempty"` LogDriver string `json:"logDriver,omitempty"` LogOptions map[string]string `json:"logOptions,omitempty"` Healthcheck *Healthcheck `json:"healthcheck,omitempty"` Resources Resources `json:"resources"` // Warnings collected while reading the container, surfaced in the UI. Warnings []string `json:"warnings,omitempty"` } // DataMounts returns the mounts that actually carry data. func (c *Container) DataMounts() []Mount { out := make([]Mount, 0, len(c.Mounts)) for _, m := range c.Mounts { if m.HasData() { out = append(out, m) } } return out }