1// Copyright 2013 go-dockerclient authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package docker 6 7import ( 8 "context" 9 "encoding/json" 10 "errors" 11 "fmt" 12 "io" 13 "net/http" 14 "net/url" 15 "strconv" 16 "strings" 17 "time" 18 19 "github.com/docker/go-units" 20) 21 22// ErrContainerAlreadyExists is the error returned by CreateContainer when the 23// container already exists. 24var ErrContainerAlreadyExists = errors.New("container already exists") 25 26// ListContainersOptions specify parameters to the ListContainers function. 27// 28// See https://goo.gl/kaOHGw for more details. 29type ListContainersOptions struct { 30 All bool 31 Size bool 32 Limit int 33 Since string 34 Before string 35 Filters map[string][]string 36 Context context.Context 37} 38 39// APIPort is a type that represents a port mapping returned by the Docker API 40type APIPort struct { 41 PrivatePort int64 `json:"PrivatePort,omitempty" yaml:"PrivatePort,omitempty" toml:"PrivatePort,omitempty"` 42 PublicPort int64 `json:"PublicPort,omitempty" yaml:"PublicPort,omitempty" toml:"PublicPort,omitempty"` 43 Type string `json:"Type,omitempty" yaml:"Type,omitempty" toml:"Type,omitempty"` 44 IP string `json:"IP,omitempty" yaml:"IP,omitempty" toml:"IP,omitempty"` 45} 46 47// APIMount represents a mount point for a container. 48type APIMount struct { 49 Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"` 50 Source string `json:"Source,omitempty" yaml:"Source,omitempty" toml:"Source,omitempty"` 51 Destination string `json:"Destination,omitempty" yaml:"Destination,omitempty" toml:"Destination,omitempty"` 52 Driver string `json:"Driver,omitempty" yaml:"Driver,omitempty" toml:"Driver,omitempty"` 53 Mode string `json:"Mode,omitempty" yaml:"Mode,omitempty" toml:"Mode,omitempty"` 54 RW bool `json:"RW,omitempty" yaml:"RW,omitempty" toml:"RW,omitempty"` 55 Propogation string `json:"Propogation,omitempty" yaml:"Propogation,omitempty" toml:"Propogation,omitempty"` 56} 57 58// APIContainers represents each container in the list returned by 59// ListContainers. 60type APIContainers struct { 61 ID string `json:"Id" yaml:"Id" toml:"Id"` 62 Image string `json:"Image,omitempty" yaml:"Image,omitempty" toml:"Image,omitempty"` 63 Command string `json:"Command,omitempty" yaml:"Command,omitempty" toml:"Command,omitempty"` 64 Created int64 `json:"Created,omitempty" yaml:"Created,omitempty" toml:"Created,omitempty"` 65 State string `json:"State,omitempty" yaml:"State,omitempty" toml:"State,omitempty"` 66 Status string `json:"Status,omitempty" yaml:"Status,omitempty" toml:"Status,omitempty"` 67 Ports []APIPort `json:"Ports,omitempty" yaml:"Ports,omitempty" toml:"Ports,omitempty"` 68 SizeRw int64 `json:"SizeRw,omitempty" yaml:"SizeRw,omitempty" toml:"SizeRw,omitempty"` 69 SizeRootFs int64 `json:"SizeRootFs,omitempty" yaml:"SizeRootFs,omitempty" toml:"SizeRootFs,omitempty"` 70 Names []string `json:"Names,omitempty" yaml:"Names,omitempty" toml:"Names,omitempty"` 71 Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty" toml:"Labels,omitempty"` 72 Networks NetworkList `json:"NetworkSettings,omitempty" yaml:"NetworkSettings,omitempty" toml:"NetworkSettings,omitempty"` 73 Mounts []APIMount `json:"Mounts,omitempty" yaml:"Mounts,omitempty" toml:"Mounts,omitempty"` 74} 75 76// NetworkList encapsulates a map of networks, as returned by the Docker API in 77// ListContainers. 78type NetworkList struct { 79 Networks map[string]ContainerNetwork `json:"Networks" yaml:"Networks,omitempty" toml:"Networks,omitempty"` 80} 81 82// ListContainers returns a slice of containers matching the given criteria. 83// 84// See https://goo.gl/kaOHGw for more details. 85func (c *Client) ListContainers(opts ListContainersOptions) ([]APIContainers, error) { 86 path := "/containers/json?" + queryString(opts) 87 resp, err := c.do("GET", path, doOptions{context: opts.Context}) 88 if err != nil { 89 return nil, err 90 } 91 defer resp.Body.Close() 92 var containers []APIContainers 93 if err := json.NewDecoder(resp.Body).Decode(&containers); err != nil { 94 return nil, err 95 } 96 return containers, nil 97} 98 99// Port represents the port number and the protocol, in the form 100// <number>/<protocol>. For example: 80/tcp. 101type Port string 102 103// Port returns the number of the port. 104func (p Port) Port() string { 105 return strings.Split(string(p), "/")[0] 106} 107 108// Proto returns the name of the protocol. 109func (p Port) Proto() string { 110 parts := strings.Split(string(p), "/") 111 if len(parts) == 1 { 112 return "tcp" 113 } 114 return parts[1] 115} 116 117// HealthCheck represents one check of health. 118type HealthCheck struct { 119 Start time.Time `json:"Start,omitempty" yaml:"Start,omitempty" toml:"Start,omitempty"` 120 End time.Time `json:"End,omitempty" yaml:"End,omitempty" toml:"End,omitempty"` 121 ExitCode int `json:"ExitCode,omitempty" yaml:"ExitCode,omitempty" toml:"ExitCode,omitempty"` 122 Output string `json:"Output,omitempty" yaml:"Output,omitempty" toml:"Output,omitempty"` 123} 124 125// Health represents the health of a container. 126type Health struct { 127 Status string `json:"Status,omitempty" yaml:"Status,omitempty" toml:"Status,omitempty"` 128 FailingStreak int `json:"FailingStreak,omitempty" yaml:"FailingStreak,omitempty" toml:"FailingStreak,omitempty"` 129 Log []HealthCheck `json:"Log,omitempty" yaml:"Log,omitempty" toml:"Log,omitempty"` 130} 131 132// State represents the state of a container. 133type State struct { 134 Status string `json:"Status,omitempty" yaml:"Status,omitempty" toml:"Status,omitempty"` 135 Running bool `json:"Running,omitempty" yaml:"Running,omitempty" toml:"Running,omitempty"` 136 Paused bool `json:"Paused,omitempty" yaml:"Paused,omitempty" toml:"Paused,omitempty"` 137 Restarting bool `json:"Restarting,omitempty" yaml:"Restarting,omitempty" toml:"Restarting,omitempty"` 138 OOMKilled bool `json:"OOMKilled,omitempty" yaml:"OOMKilled,omitempty" toml:"OOMKilled,omitempty"` 139 RemovalInProgress bool `json:"RemovalInProgress,omitempty" yaml:"RemovalInProgress,omitempty" toml:"RemovalInProgress,omitempty"` 140 Dead bool `json:"Dead,omitempty" yaml:"Dead,omitempty" toml:"Dead,omitempty"` 141 Pid int `json:"Pid,omitempty" yaml:"Pid,omitempty" toml:"Pid,omitempty"` 142 ExitCode int `json:"ExitCode,omitempty" yaml:"ExitCode,omitempty" toml:"ExitCode,omitempty"` 143 Error string `json:"Error,omitempty" yaml:"Error,omitempty" toml:"Error,omitempty"` 144 StartedAt time.Time `json:"StartedAt,omitempty" yaml:"StartedAt,omitempty" toml:"StartedAt,omitempty"` 145 FinishedAt time.Time `json:"FinishedAt,omitempty" yaml:"FinishedAt,omitempty" toml:"FinishedAt,omitempty"` 146 Health Health `json:"Health,omitempty" yaml:"Health,omitempty" toml:"Health,omitempty"` 147} 148 149// String returns a human-readable description of the state 150func (s *State) String() string { 151 if s.Running { 152 if s.Paused { 153 return fmt.Sprintf("Up %s (Paused)", units.HumanDuration(time.Now().UTC().Sub(s.StartedAt))) 154 } 155 if s.Restarting { 156 return fmt.Sprintf("Restarting (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt))) 157 } 158 159 return fmt.Sprintf("Up %s", units.HumanDuration(time.Now().UTC().Sub(s.StartedAt))) 160 } 161 162 if s.RemovalInProgress { 163 return "Removal In Progress" 164 } 165 166 if s.Dead { 167 return "Dead" 168 } 169 170 if s.StartedAt.IsZero() { 171 return "Created" 172 } 173 174 if s.FinishedAt.IsZero() { 175 return "" 176 } 177 178 return fmt.Sprintf("Exited (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt))) 179} 180 181// StateString returns a single string to describe state 182func (s *State) StateString() string { 183 if s.Running { 184 if s.Paused { 185 return "paused" 186 } 187 if s.Restarting { 188 return "restarting" 189 } 190 return "running" 191 } 192 193 if s.Dead { 194 return "dead" 195 } 196 197 if s.StartedAt.IsZero() { 198 return "created" 199 } 200 201 return "exited" 202} 203 204// PortBinding represents the host/container port mapping as returned in the 205// `docker inspect` json 206type PortBinding struct { 207 HostIP string `json:"HostIp,omitempty" yaml:"HostIp,omitempty" toml:"HostIp,omitempty"` 208 HostPort string `json:"HostPort,omitempty" yaml:"HostPort,omitempty" toml:"HostPort,omitempty"` 209} 210 211// PortMapping represents a deprecated field in the `docker inspect` output, 212// and its value as found in NetworkSettings should always be nil 213type PortMapping map[string]string 214 215// ContainerNetwork represents the networking settings of a container per network. 216type ContainerNetwork struct { 217 Aliases []string `json:"Aliases,omitempty" yaml:"Aliases,omitempty" toml:"Aliases,omitempty"` 218 MacAddress string `json:"MacAddress,omitempty" yaml:"MacAddress,omitempty" toml:"MacAddress,omitempty"` 219 GlobalIPv6PrefixLen int `json:"GlobalIPv6PrefixLen,omitempty" yaml:"GlobalIPv6PrefixLen,omitempty" toml:"GlobalIPv6PrefixLen,omitempty"` 220 GlobalIPv6Address string `json:"GlobalIPv6Address,omitempty" yaml:"GlobalIPv6Address,omitempty" toml:"GlobalIPv6Address,omitempty"` 221 IPv6Gateway string `json:"IPv6Gateway,omitempty" yaml:"IPv6Gateway,omitempty" toml:"IPv6Gateway,omitempty"` 222 IPPrefixLen int `json:"IPPrefixLen,omitempty" yaml:"IPPrefixLen,omitempty" toml:"IPPrefixLen,omitempty"` 223 IPAddress string `json:"IPAddress,omitempty" yaml:"IPAddress,omitempty" toml:"IPAddress,omitempty"` 224 Gateway string `json:"Gateway,omitempty" yaml:"Gateway,omitempty" toml:"Gateway,omitempty"` 225 EndpointID string `json:"EndpointID,omitempty" yaml:"EndpointID,omitempty" toml:"EndpointID,omitempty"` 226 NetworkID string `json:"NetworkID,omitempty" yaml:"NetworkID,omitempty" toml:"NetworkID,omitempty"` 227} 228 229// NetworkSettings contains network-related information about a container 230type NetworkSettings struct { 231 Networks map[string]ContainerNetwork `json:"Networks,omitempty" yaml:"Networks,omitempty" toml:"Networks,omitempty"` 232 IPAddress string `json:"IPAddress,omitempty" yaml:"IPAddress,omitempty" toml:"IPAddress,omitempty"` 233 IPPrefixLen int `json:"IPPrefixLen,omitempty" yaml:"IPPrefixLen,omitempty" toml:"IPPrefixLen,omitempty"` 234 MacAddress string `json:"MacAddress,omitempty" yaml:"MacAddress,omitempty" toml:"MacAddress,omitempty"` 235 Gateway string `json:"Gateway,omitempty" yaml:"Gateway,omitempty" toml:"Gateway,omitempty"` 236 Bridge string `json:"Bridge,omitempty" yaml:"Bridge,omitempty" toml:"Bridge,omitempty"` 237 PortMapping map[string]PortMapping `json:"PortMapping,omitempty" yaml:"PortMapping,omitempty" toml:"PortMapping,omitempty"` 238 Ports map[Port][]PortBinding `json:"Ports,omitempty" yaml:"Ports,omitempty" toml:"Ports,omitempty"` 239 NetworkID string `json:"NetworkID,omitempty" yaml:"NetworkID,omitempty" toml:"NetworkID,omitempty"` 240 EndpointID string `json:"EndpointID,omitempty" yaml:"EndpointID,omitempty" toml:"EndpointID,omitempty"` 241 SandboxKey string `json:"SandboxKey,omitempty" yaml:"SandboxKey,omitempty" toml:"SandboxKey,omitempty"` 242 GlobalIPv6Address string `json:"GlobalIPv6Address,omitempty" yaml:"GlobalIPv6Address,omitempty" toml:"GlobalIPv6Address,omitempty"` 243 GlobalIPv6PrefixLen int `json:"GlobalIPv6PrefixLen,omitempty" yaml:"GlobalIPv6PrefixLen,omitempty" toml:"GlobalIPv6PrefixLen,omitempty"` 244 IPv6Gateway string `json:"IPv6Gateway,omitempty" yaml:"IPv6Gateway,omitempty" toml:"IPv6Gateway,omitempty"` 245 LinkLocalIPv6Address string `json:"LinkLocalIPv6Address,omitempty" yaml:"LinkLocalIPv6Address,omitempty" toml:"LinkLocalIPv6Address,omitempty"` 246 LinkLocalIPv6PrefixLen int `json:"LinkLocalIPv6PrefixLen,omitempty" yaml:"LinkLocalIPv6PrefixLen,omitempty" toml:"LinkLocalIPv6PrefixLen,omitempty"` 247 SecondaryIPAddresses []string `json:"SecondaryIPAddresses,omitempty" yaml:"SecondaryIPAddresses,omitempty" toml:"SecondaryIPAddresses,omitempty"` 248 SecondaryIPv6Addresses []string `json:"SecondaryIPv6Addresses,omitempty" yaml:"SecondaryIPv6Addresses,omitempty" toml:"SecondaryIPv6Addresses,omitempty"` 249} 250 251// PortMappingAPI translates the port mappings as contained in NetworkSettings 252// into the format in which they would appear when returned by the API 253func (settings *NetworkSettings) PortMappingAPI() []APIPort { 254 var mapping []APIPort 255 for port, bindings := range settings.Ports { 256 p, _ := parsePort(port.Port()) 257 if len(bindings) == 0 { 258 mapping = append(mapping, APIPort{ 259 PrivatePort: int64(p), 260 Type: port.Proto(), 261 }) 262 continue 263 } 264 for _, binding := range bindings { 265 p, _ := parsePort(port.Port()) 266 h, _ := parsePort(binding.HostPort) 267 mapping = append(mapping, APIPort{ 268 PrivatePort: int64(p), 269 PublicPort: int64(h), 270 Type: port.Proto(), 271 IP: binding.HostIP, 272 }) 273 } 274 } 275 return mapping 276} 277 278func parsePort(rawPort string) (int, error) { 279 port, err := strconv.ParseUint(rawPort, 10, 16) 280 if err != nil { 281 return 0, err 282 } 283 return int(port), nil 284} 285 286// Config is the list of configuration options used when creating a container. 287// Config does not contain the options that are specific to starting a container on a 288// given host. Those are contained in HostConfig 289type Config struct { 290 Hostname string `json:"Hostname,omitempty" yaml:"Hostname,omitempty" toml:"Hostname,omitempty"` 291 Domainname string `json:"Domainname,omitempty" yaml:"Domainname,omitempty" toml:"Domainname,omitempty"` 292 User string `json:"User,omitempty" yaml:"User,omitempty" toml:"User,omitempty"` 293 Memory int64 `json:"Memory,omitempty" yaml:"Memory,omitempty" toml:"Memory,omitempty"` 294 MemorySwap int64 `json:"MemorySwap,omitempty" yaml:"MemorySwap,omitempty" toml:"MemorySwap,omitempty"` 295 MemoryReservation int64 `json:"MemoryReservation,omitempty" yaml:"MemoryReservation,omitempty" toml:"MemoryReservation,omitempty"` 296 KernelMemory int64 `json:"KernelMemory,omitempty" yaml:"KernelMemory,omitempty" toml:"KernelMemory,omitempty"` 297 CPUShares int64 `json:"CpuShares,omitempty" yaml:"CpuShares,omitempty" toml:"CpuShares,omitempty"` 298 CPUSet string `json:"Cpuset,omitempty" yaml:"Cpuset,omitempty" toml:"Cpuset,omitempty"` 299 PortSpecs []string `json:"PortSpecs,omitempty" yaml:"PortSpecs,omitempty" toml:"PortSpecs,omitempty"` 300 ExposedPorts map[Port]struct{} `json:"ExposedPorts,omitempty" yaml:"ExposedPorts,omitempty" toml:"ExposedPorts,omitempty"` 301 PublishService string `json:"PublishService,omitempty" yaml:"PublishService,omitempty" toml:"PublishService,omitempty"` 302 StopSignal string `json:"StopSignal,omitempty" yaml:"StopSignal,omitempty" toml:"StopSignal,omitempty"` 303 StopTimeout int `json:"StopTimeout,omitempty" yaml:"StopTimeout,omitempty" toml:"StopTimeout,omitempty"` 304 Env []string `json:"Env,omitempty" yaml:"Env,omitempty" toml:"Env,omitempty"` 305 Cmd []string `json:"Cmd" yaml:"Cmd" toml:"Cmd"` 306 Shell []string `json:"Shell,omitempty" yaml:"Shell,omitempty" toml:"Shell,omitempty"` 307 Healthcheck *HealthConfig `json:"Healthcheck,omitempty" yaml:"Healthcheck,omitempty" toml:"Healthcheck,omitempty"` 308 DNS []string `json:"Dns,omitempty" yaml:"Dns,omitempty" toml:"Dns,omitempty"` // For Docker API v1.9 and below only 309 Image string `json:"Image,omitempty" yaml:"Image,omitempty" toml:"Image,omitempty"` 310 Volumes map[string]struct{} `json:"Volumes,omitempty" yaml:"Volumes,omitempty" toml:"Volumes,omitempty"` 311 VolumeDriver string `json:"VolumeDriver,omitempty" yaml:"VolumeDriver,omitempty" toml:"VolumeDriver,omitempty"` 312 WorkingDir string `json:"WorkingDir,omitempty" yaml:"WorkingDir,omitempty" toml:"WorkingDir,omitempty"` 313 MacAddress string `json:"MacAddress,omitempty" yaml:"MacAddress,omitempty" toml:"MacAddress,omitempty"` 314 Entrypoint []string `json:"Entrypoint" yaml:"Entrypoint" toml:"Entrypoint"` 315 SecurityOpts []string `json:"SecurityOpts,omitempty" yaml:"SecurityOpts,omitempty" toml:"SecurityOpts,omitempty"` 316 OnBuild []string `json:"OnBuild,omitempty" yaml:"OnBuild,omitempty" toml:"OnBuild,omitempty"` 317 Mounts []Mount `json:"Mounts,omitempty" yaml:"Mounts,omitempty" toml:"Mounts,omitempty"` 318 Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty" toml:"Labels,omitempty"` 319 AttachStdin bool `json:"AttachStdin,omitempty" yaml:"AttachStdin,omitempty" toml:"AttachStdin,omitempty"` 320 AttachStdout bool `json:"AttachStdout,omitempty" yaml:"AttachStdout,omitempty" toml:"AttachStdout,omitempty"` 321 AttachStderr bool `json:"AttachStderr,omitempty" yaml:"AttachStderr,omitempty" toml:"AttachStderr,omitempty"` 322 ArgsEscaped bool `json:"ArgsEscaped,omitempty" yaml:"ArgsEscaped,omitempty" toml:"ArgsEscaped,omitempty"` 323 Tty bool `json:"Tty,omitempty" yaml:"Tty,omitempty" toml:"Tty,omitempty"` 324 OpenStdin bool `json:"OpenStdin,omitempty" yaml:"OpenStdin,omitempty" toml:"OpenStdin,omitempty"` 325 StdinOnce bool `json:"StdinOnce,omitempty" yaml:"StdinOnce,omitempty" toml:"StdinOnce,omitempty"` 326 NetworkDisabled bool `json:"NetworkDisabled,omitempty" yaml:"NetworkDisabled,omitempty" toml:"NetworkDisabled,omitempty"` 327 328 // This is no longer used and has been kept here for backward 329 // compatibility, please use HostConfig.VolumesFrom. 330 VolumesFrom string `json:"VolumesFrom,omitempty" yaml:"VolumesFrom,omitempty" toml:"VolumesFrom,omitempty"` 331} 332 333// HostMount represents a mount point in the container in HostConfig. 334// 335// It has been added in the version 1.25 of the Docker API 336type HostMount struct { 337 Target string `json:"Target,omitempty" yaml:"Target,omitempty" toml:"Target,omitempty"` 338 Source string `json:"Source,omitempty" yaml:"Source,omitempty" toml:"Source,omitempty"` 339 Type string `json:"Type,omitempty" yaml:"Type,omitempty" toml:"Type,omitempty"` 340 ReadOnly bool `json:"ReadOnly,omitempty" yaml:"ReadOnly,omitempty" toml:"ReadOnly,omitempty"` 341 BindOptions *BindOptions `json:"BindOptions,omitempty" yaml:"BindOptions,omitempty" toml:"BindOptions,omitempty"` 342 VolumeOptions *VolumeOptions `json:"VolumeOptions,omitempty" yaml:"VolumeOptions,omitempty" toml:"VolumeOptions,omitempty"` 343 TempfsOptions *TempfsOptions `json:"TempfsOptions,omitempty" yaml:"TempfsOptions,omitempty" toml:"TempfsOptions,omitempty"` 344} 345 346// BindOptions contains optional configuration for the bind type 347type BindOptions struct { 348 Propagation string `json:"Propagation,omitempty" yaml:"Propagation,omitempty" toml:"Propagation,omitempty"` 349} 350 351// VolumeOptions contains optional configuration for the volume type 352type VolumeOptions struct { 353 NoCopy bool `json:"NoCopy,omitempty" yaml:"NoCopy,omitempty" toml:"NoCopy,omitempty"` 354 Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty" toml:"Labels,omitempty"` 355 DriverConfig VolumeDriverConfig `json:"DriverConfig,omitempty" yaml:"DriverConfig,omitempty" toml:"DriverConfig,omitempty"` 356} 357 358// TempfsOptions contains optional configuration for the tempfs type 359type TempfsOptions struct { 360 SizeBytes int64 `json:"SizeBytes,omitempty" yaml:"SizeBytes,omitempty" toml:"SizeBytes,omitempty"` 361 Mode int `json:"Mode,omitempty" yaml:"Mode,omitempty" toml:"Mode,omitempty"` 362} 363 364// VolumeDriverConfig holds a map of volume driver specific options 365type VolumeDriverConfig struct { 366 Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"` 367 Options map[string]string `json:"Options,omitempty" yaml:"Options,omitempty" toml:"Options,omitempty"` 368} 369 370// Mount represents a mount point in the container. 371// 372// It has been added in the version 1.20 of the Docker API, available since 373// Docker 1.8. 374type Mount struct { 375 Name string 376 Source string 377 Destination string 378 Driver string 379 Mode string 380 RW bool 381} 382 383// LogConfig defines the log driver type and the configuration for it. 384type LogConfig struct { 385 Type string `json:"Type,omitempty" yaml:"Type,omitempty" toml:"Type,omitempty"` 386 Config map[string]string `json:"Config,omitempty" yaml:"Config,omitempty" toml:"Config,omitempty"` 387} 388 389// ULimit defines system-wide resource limitations This can help a lot in 390// system administration, e.g. when a user starts too many processes and 391// therefore makes the system unresponsive for other users. 392type ULimit struct { 393 Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"` 394 Soft int64 `json:"Soft,omitempty" yaml:"Soft,omitempty" toml:"Soft,omitempty"` 395 Hard int64 `json:"Hard,omitempty" yaml:"Hard,omitempty" toml:"Hard,omitempty"` 396} 397 398// SwarmNode containers information about which Swarm node the container is on. 399type SwarmNode struct { 400 ID string `json:"ID,omitempty" yaml:"ID,omitempty" toml:"ID,omitempty"` 401 IP string `json:"IP,omitempty" yaml:"IP,omitempty" toml:"IP,omitempty"` 402 Addr string `json:"Addr,omitempty" yaml:"Addr,omitempty" toml:"Addr,omitempty"` 403 Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"` 404 CPUs int64 `json:"CPUs,omitempty" yaml:"CPUs,omitempty" toml:"CPUs,omitempty"` 405 Memory int64 `json:"Memory,omitempty" yaml:"Memory,omitempty" toml:"Memory,omitempty"` 406 Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty" toml:"Labels,omitempty"` 407} 408 409// GraphDriver contains information about the GraphDriver used by the 410// container. 411type GraphDriver struct { 412 Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"` 413 Data map[string]string `json:"Data,omitempty" yaml:"Data,omitempty" toml:"Data,omitempty"` 414} 415 416// HealthConfig holds configuration settings for the HEALTHCHECK feature 417// 418// It has been added in the version 1.24 of the Docker API, available since 419// Docker 1.12. 420type HealthConfig struct { 421 // Test is the test to perform to check that the container is healthy. 422 // An empty slice means to inherit the default. 423 // The options are: 424 // {} : inherit healthcheck 425 // {"NONE"} : disable healthcheck 426 // {"CMD", args...} : exec arguments directly 427 // {"CMD-SHELL", command} : run command with system's default shell 428 Test []string `json:"Test,omitempty" yaml:"Test,omitempty" toml:"Test,omitempty"` 429 430 // Zero means to inherit. Durations are expressed as integer nanoseconds. 431 Interval time.Duration `json:"Interval,omitempty" yaml:"Interval,omitempty" toml:"Interval,omitempty"` // Interval is the time to wait between checks. 432 Timeout time.Duration `json:"Timeout,omitempty" yaml:"Timeout,omitempty" toml:"Timeout,omitempty"` // Timeout is the time to wait before considering the check to have hung. 433 StartPeriod time.Duration `json:"StartPeriod,omitempty" yaml:"StartPeriod,omitempty" toml:"StartPeriod,omitempty"` // The start period for the container to initialize before the retries starts to count down. 434 435 // Retries is the number of consecutive failures needed to consider a container as unhealthy. 436 // Zero means inherit. 437 Retries int `json:"Retries,omitempty" yaml:"Retries,omitempty" toml:"Retries,omitempty"` 438} 439 440// Container is the type encompasing everything about a container - its config, 441// hostconfig, etc. 442type Container struct { 443 ID string `json:"Id" yaml:"Id" toml:"Id"` 444 445 Created time.Time `json:"Created,omitempty" yaml:"Created,omitempty" toml:"Created,omitempty"` 446 447 Path string `json:"Path,omitempty" yaml:"Path,omitempty" toml:"Path,omitempty"` 448 Args []string `json:"Args,omitempty" yaml:"Args,omitempty" toml:"Args,omitempty"` 449 450 Config *Config `json:"Config,omitempty" yaml:"Config,omitempty" toml:"Config,omitempty"` 451 State State `json:"State,omitempty" yaml:"State,omitempty" toml:"State,omitempty"` 452 Image string `json:"Image,omitempty" yaml:"Image,omitempty" toml:"Image,omitempty"` 453 454 Node *SwarmNode `json:"Node,omitempty" yaml:"Node,omitempty" toml:"Node,omitempty"` 455 456 NetworkSettings *NetworkSettings `json:"NetworkSettings,omitempty" yaml:"NetworkSettings,omitempty" toml:"NetworkSettings,omitempty"` 457 458 SysInitPath string `json:"SysInitPath,omitempty" yaml:"SysInitPath,omitempty" toml:"SysInitPath,omitempty"` 459 ResolvConfPath string `json:"ResolvConfPath,omitempty" yaml:"ResolvConfPath,omitempty" toml:"ResolvConfPath,omitempty"` 460 HostnamePath string `json:"HostnamePath,omitempty" yaml:"HostnamePath,omitempty" toml:"HostnamePath,omitempty"` 461 HostsPath string `json:"HostsPath,omitempty" yaml:"HostsPath,omitempty" toml:"HostsPath,omitempty"` 462 LogPath string `json:"LogPath,omitempty" yaml:"LogPath,omitempty" toml:"LogPath,omitempty"` 463 Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"` 464 Driver string `json:"Driver,omitempty" yaml:"Driver,omitempty" toml:"Driver,omitempty"` 465 Mounts []Mount `json:"Mounts,omitempty" yaml:"Mounts,omitempty" toml:"Mounts,omitempty"` 466 467 Volumes map[string]string `json:"Volumes,omitempty" yaml:"Volumes,omitempty" toml:"Volumes,omitempty"` 468 VolumesRW map[string]bool `json:"VolumesRW,omitempty" yaml:"VolumesRW,omitempty" toml:"VolumesRW,omitempty"` 469 HostConfig *HostConfig `json:"HostConfig,omitempty" yaml:"HostConfig,omitempty" toml:"HostConfig,omitempty"` 470 ExecIDs []string `json:"ExecIDs,omitempty" yaml:"ExecIDs,omitempty" toml:"ExecIDs,omitempty"` 471 GraphDriver *GraphDriver `json:"GraphDriver,omitempty" yaml:"GraphDriver,omitempty" toml:"GraphDriver,omitempty"` 472 473 RestartCount int `json:"RestartCount,omitempty" yaml:"RestartCount,omitempty" toml:"RestartCount,omitempty"` 474 475 AppArmorProfile string `json:"AppArmorProfile,omitempty" yaml:"AppArmorProfile,omitempty" toml:"AppArmorProfile,omitempty"` 476} 477 478// UpdateContainerOptions specify parameters to the UpdateContainer function. 479// 480// See https://goo.gl/Y6fXUy for more details. 481type UpdateContainerOptions struct { 482 BlkioWeight int `json:"BlkioWeight"` 483 CPUShares int `json:"CpuShares"` 484 CPUPeriod int `json:"CpuPeriod"` 485 CPURealtimePeriod int64 `json:"CpuRealtimePeriod"` 486 CPURealtimeRuntime int64 `json:"CpuRealtimeRuntime"` 487 CPUQuota int `json:"CpuQuota"` 488 CpusetCpus string `json:"CpusetCpus"` 489 CpusetMems string `json:"CpusetMems"` 490 Memory int `json:"Memory"` 491 MemorySwap int `json:"MemorySwap"` 492 MemoryReservation int `json:"MemoryReservation"` 493 KernelMemory int `json:"KernelMemory"` 494 RestartPolicy RestartPolicy `json:"RestartPolicy,omitempty"` 495 Context context.Context 496} 497 498// UpdateContainer updates the container at ID with the options 499// 500// See https://goo.gl/Y6fXUy for more details. 501func (c *Client) UpdateContainer(id string, opts UpdateContainerOptions) error { 502 resp, err := c.do("POST", fmt.Sprintf("/containers/"+id+"/update"), doOptions{ 503 data: opts, 504 forceJSON: true, 505 context: opts.Context, 506 }) 507 if err != nil { 508 return err 509 } 510 defer resp.Body.Close() 511 return nil 512} 513 514// RenameContainerOptions specify parameters to the RenameContainer function. 515// 516// See https://goo.gl/46inai for more details. 517type RenameContainerOptions struct { 518 // ID of container to rename 519 ID string `qs:"-"` 520 521 // New name 522 Name string `json:"name,omitempty" yaml:"name,omitempty"` 523 Context context.Context 524} 525 526// RenameContainer updates and existing containers name 527// 528// See https://goo.gl/46inai for more details. 529func (c *Client) RenameContainer(opts RenameContainerOptions) error { 530 resp, err := c.do("POST", fmt.Sprintf("/containers/"+opts.ID+"/rename?%s", queryString(opts)), doOptions{ 531 context: opts.Context, 532 }) 533 if err != nil { 534 return err 535 } 536 resp.Body.Close() 537 return nil 538} 539 540// InspectContainer returns information about a container by its ID. 541// 542// See https://goo.gl/FaI5JT for more details. 543func (c *Client) InspectContainer(id string) (*Container, error) { 544 return c.inspectContainer(id, doOptions{}) 545} 546 547// InspectContainerWithContext returns information about a container by its ID. 548// The context object can be used to cancel the inspect request. 549// 550// See https://goo.gl/FaI5JT for more details. 551func (c *Client) InspectContainerWithContext(id string, ctx context.Context) (*Container, error) { 552 return c.inspectContainer(id, doOptions{context: ctx}) 553} 554 555func (c *Client) inspectContainer(id string, opts doOptions) (*Container, error) { 556 path := "/containers/" + id + "/json" 557 resp, err := c.do("GET", path, opts) 558 if err != nil { 559 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { 560 return nil, &NoSuchContainer{ID: id} 561 } 562 return nil, err 563 } 564 defer resp.Body.Close() 565 var container Container 566 if err := json.NewDecoder(resp.Body).Decode(&container); err != nil { 567 return nil, err 568 } 569 return &container, nil 570} 571 572// ContainerChanges returns changes in the filesystem of the given container. 573// 574// See https://goo.gl/15KKzh for more details. 575func (c *Client) ContainerChanges(id string) ([]Change, error) { 576 path := "/containers/" + id + "/changes" 577 resp, err := c.do("GET", path, doOptions{}) 578 if err != nil { 579 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { 580 return nil, &NoSuchContainer{ID: id} 581 } 582 return nil, err 583 } 584 defer resp.Body.Close() 585 var changes []Change 586 if err := json.NewDecoder(resp.Body).Decode(&changes); err != nil { 587 return nil, err 588 } 589 return changes, nil 590} 591 592// CreateContainerOptions specify parameters to the CreateContainer function. 593// 594// See https://goo.gl/tyzwVM for more details. 595type CreateContainerOptions struct { 596 Name string 597 Config *Config `qs:"-"` 598 HostConfig *HostConfig `qs:"-"` 599 NetworkingConfig *NetworkingConfig `qs:"-"` 600 Context context.Context 601} 602 603// CreateContainer creates a new container, returning the container instance, 604// or an error in case of failure. 605// 606// The returned container instance contains only the container ID. To get more 607// details about the container after creating it, use InspectContainer. 608// 609// See https://goo.gl/tyzwVM for more details. 610func (c *Client) CreateContainer(opts CreateContainerOptions) (*Container, error) { 611 path := "/containers/create?" + queryString(opts) 612 resp, err := c.do( 613 "POST", 614 path, 615 doOptions{ 616 data: struct { 617 *Config 618 HostConfig *HostConfig `json:"HostConfig,omitempty" yaml:"HostConfig,omitempty" toml:"HostConfig,omitempty"` 619 NetworkingConfig *NetworkingConfig `json:"NetworkingConfig,omitempty" yaml:"NetworkingConfig,omitempty" toml:"NetworkingConfig,omitempty"` 620 }{ 621 opts.Config, 622 opts.HostConfig, 623 opts.NetworkingConfig, 624 }, 625 context: opts.Context, 626 }, 627 ) 628 629 if e, ok := err.(*Error); ok { 630 if e.Status == http.StatusNotFound { 631 return nil, ErrNoSuchImage 632 } 633 if e.Status == http.StatusConflict { 634 return nil, ErrContainerAlreadyExists 635 } 636 // Workaround for 17.09 bug returning 400 instead of 409. 637 // See https://github.com/moby/moby/issues/35021 638 if e.Status == http.StatusBadRequest && strings.Contains(e.Message, "Conflict.") { 639 return nil, ErrContainerAlreadyExists 640 } 641 } 642 643 if err != nil { 644 return nil, err 645 } 646 defer resp.Body.Close() 647 var container Container 648 if err := json.NewDecoder(resp.Body).Decode(&container); err != nil { 649 return nil, err 650 } 651 652 container.Name = opts.Name 653 654 return &container, nil 655} 656 657// KeyValuePair is a type for generic key/value pairs as used in the Lxc 658// configuration 659type KeyValuePair struct { 660 Key string `json:"Key,omitempty" yaml:"Key,omitempty" toml:"Key,omitempty"` 661 Value string `json:"Value,omitempty" yaml:"Value,omitempty" toml:"Value,omitempty"` 662} 663 664// RestartPolicy represents the policy for automatically restarting a container. 665// 666// Possible values are: 667// 668// - always: the docker daemon will always restart the container 669// - on-failure: the docker daemon will restart the container on failures, at 670// most MaximumRetryCount times 671// - unless-stopped: the docker daemon will always restart the container except 672// when user has manually stopped the container 673// - no: the docker daemon will not restart the container automatically 674type RestartPolicy struct { 675 Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"` 676 MaximumRetryCount int `json:"MaximumRetryCount,omitempty" yaml:"MaximumRetryCount,omitempty" toml:"MaximumRetryCount,omitempty"` 677} 678 679// AlwaysRestart returns a restart policy that tells the Docker daemon to 680// always restart the container. 681func AlwaysRestart() RestartPolicy { 682 return RestartPolicy{Name: "always"} 683} 684 685// RestartOnFailure returns a restart policy that tells the Docker daemon to 686// restart the container on failures, trying at most maxRetry times. 687func RestartOnFailure(maxRetry int) RestartPolicy { 688 return RestartPolicy{Name: "on-failure", MaximumRetryCount: maxRetry} 689} 690 691// RestartUnlessStopped returns a restart policy that tells the Docker daemon to 692// always restart the container except when user has manually stopped the container. 693func RestartUnlessStopped() RestartPolicy { 694 return RestartPolicy{Name: "unless-stopped"} 695} 696 697// NeverRestart returns a restart policy that tells the Docker daemon to never 698// restart the container on failures. 699func NeverRestart() RestartPolicy { 700 return RestartPolicy{Name: "no"} 701} 702 703// Device represents a device mapping between the Docker host and the 704// container. 705type Device struct { 706 PathOnHost string `json:"PathOnHost,omitempty" yaml:"PathOnHost,omitempty" toml:"PathOnHost,omitempty"` 707 PathInContainer string `json:"PathInContainer,omitempty" yaml:"PathInContainer,omitempty" toml:"PathInContainer,omitempty"` 708 CgroupPermissions string `json:"CgroupPermissions,omitempty" yaml:"CgroupPermissions,omitempty" toml:"CgroupPermissions,omitempty"` 709} 710 711// BlockWeight represents a relative device weight for an individual device inside 712// of a container 713type BlockWeight struct { 714 Path string `json:"Path,omitempty"` 715 Weight string `json:"Weight,omitempty"` 716} 717 718// BlockLimit represents a read/write limit in IOPS or Bandwidth for a device 719// inside of a container 720type BlockLimit struct { 721 Path string `json:"Path,omitempty"` 722 Rate int64 `json:"Rate,omitempty"` 723} 724 725// HostConfig contains the container options related to starting a container on 726// a given host 727type HostConfig struct { 728 Binds []string `json:"Binds,omitempty" yaml:"Binds,omitempty" toml:"Binds,omitempty"` 729 CapAdd []string `json:"CapAdd,omitempty" yaml:"CapAdd,omitempty" toml:"CapAdd,omitempty"` 730 CapDrop []string `json:"CapDrop,omitempty" yaml:"CapDrop,omitempty" toml:"CapDrop,omitempty"` 731 GroupAdd []string `json:"GroupAdd,omitempty" yaml:"GroupAdd,omitempty" toml:"GroupAdd,omitempty"` 732 ContainerIDFile string `json:"ContainerIDFile,omitempty" yaml:"ContainerIDFile,omitempty" toml:"ContainerIDFile,omitempty"` 733 LxcConf []KeyValuePair `json:"LxcConf,omitempty" yaml:"LxcConf,omitempty" toml:"LxcConf,omitempty"` 734 PortBindings map[Port][]PortBinding `json:"PortBindings,omitempty" yaml:"PortBindings,omitempty" toml:"PortBindings,omitempty"` 735 Links []string `json:"Links,omitempty" yaml:"Links,omitempty" toml:"Links,omitempty"` 736 DNS []string `json:"Dns,omitempty" yaml:"Dns,omitempty" toml:"Dns,omitempty"` // For Docker API v1.10 and above only 737 DNSOptions []string `json:"DnsOptions,omitempty" yaml:"DnsOptions,omitempty" toml:"DnsOptions,omitempty"` 738 DNSSearch []string `json:"DnsSearch,omitempty" yaml:"DnsSearch,omitempty" toml:"DnsSearch,omitempty"` 739 ExtraHosts []string `json:"ExtraHosts,omitempty" yaml:"ExtraHosts,omitempty" toml:"ExtraHosts,omitempty"` 740 VolumesFrom []string `json:"VolumesFrom,omitempty" yaml:"VolumesFrom,omitempty" toml:"VolumesFrom,omitempty"` 741 UsernsMode string `json:"UsernsMode,omitempty" yaml:"UsernsMode,omitempty" toml:"UsernsMode,omitempty"` 742 NetworkMode string `json:"NetworkMode,omitempty" yaml:"NetworkMode,omitempty" toml:"NetworkMode,omitempty"` 743 IpcMode string `json:"IpcMode,omitempty" yaml:"IpcMode,omitempty" toml:"IpcMode,omitempty"` 744 PidMode string `json:"PidMode,omitempty" yaml:"PidMode,omitempty" toml:"PidMode,omitempty"` 745 UTSMode string `json:"UTSMode,omitempty" yaml:"UTSMode,omitempty" toml:"UTSMode,omitempty"` 746 RestartPolicy RestartPolicy `json:"RestartPolicy,omitempty" yaml:"RestartPolicy,omitempty" toml:"RestartPolicy,omitempty"` 747 Devices []Device `json:"Devices,omitempty" yaml:"Devices,omitempty" toml:"Devices,omitempty"` 748 DeviceCgroupRules []string `json:"DeviceCgroupRules,omitempty" yaml:"DeviceCgroupRules,omitempty" toml:"DeviceCgroupRules,omitempty"` 749 LogConfig LogConfig `json:"LogConfig,omitempty" yaml:"LogConfig,omitempty" toml:"LogConfig,omitempty"` 750 SecurityOpt []string `json:"SecurityOpt,omitempty" yaml:"SecurityOpt,omitempty" toml:"SecurityOpt,omitempty"` 751 Cgroup string `json:"Cgroup,omitempty" yaml:"Cgroup,omitempty" toml:"Cgroup,omitempty"` 752 CgroupParent string `json:"CgroupParent,omitempty" yaml:"CgroupParent,omitempty" toml:"CgroupParent,omitempty"` 753 Memory int64 `json:"Memory,omitempty" yaml:"Memory,omitempty" toml:"Memory,omitempty"` 754 MemoryReservation int64 `json:"MemoryReservation,omitempty" yaml:"MemoryReservation,omitempty" toml:"MemoryReservation,omitempty"` 755 KernelMemory int64 `json:"KernelMemory,omitempty" yaml:"KernelMemory,omitempty" toml:"KernelMemory,omitempty"` 756 MemorySwap int64 `json:"MemorySwap,omitempty" yaml:"MemorySwap,omitempty" toml:"MemorySwap,omitempty"` 757 MemorySwappiness int64 `json:"MemorySwappiness,omitempty" yaml:"MemorySwappiness,omitempty" toml:"MemorySwappiness,omitempty"` 758 CPUShares int64 `json:"CpuShares,omitempty" yaml:"CpuShares,omitempty" toml:"CpuShares,omitempty"` 759 CPUSet string `json:"Cpuset,omitempty" yaml:"Cpuset,omitempty" toml:"Cpuset,omitempty"` 760 CPUSetCPUs string `json:"CpusetCpus,omitempty" yaml:"CpusetCpus,omitempty" toml:"CpusetCpus,omitempty"` 761 CPUSetMEMs string `json:"CpusetMems,omitempty" yaml:"CpusetMems,omitempty" toml:"CpusetMems,omitempty"` 762 CPUQuota int64 `json:"CpuQuota,omitempty" yaml:"CpuQuota,omitempty" toml:"CpuQuota,omitempty"` 763 CPUPeriod int64 `json:"CpuPeriod,omitempty" yaml:"CpuPeriod,omitempty" toml:"CpuPeriod,omitempty"` 764 CPURealtimePeriod int64 `json:"CpuRealtimePeriod,omitempty" yaml:"CpuRealtimePeriod,omitempty" toml:"CpuRealtimePeriod,omitempty"` 765 CPURealtimeRuntime int64 `json:"CpuRealtimeRuntime,omitempty" yaml:"CpuRealtimeRuntime,omitempty" toml:"CpuRealtimeRuntime,omitempty"` 766 BlkioWeight int64 `json:"BlkioWeight,omitempty" yaml:"BlkioWeight,omitempty" toml:"BlkioWeight,omitempty"` 767 BlkioWeightDevice []BlockWeight `json:"BlkioWeightDevice,omitempty" yaml:"BlkioWeightDevice,omitempty" toml:"BlkioWeightDevice,omitempty"` 768 BlkioDeviceReadBps []BlockLimit `json:"BlkioDeviceReadBps,omitempty" yaml:"BlkioDeviceReadBps,omitempty" toml:"BlkioDeviceReadBps,omitempty"` 769 BlkioDeviceReadIOps []BlockLimit `json:"BlkioDeviceReadIOps,omitempty" yaml:"BlkioDeviceReadIOps,omitempty" toml:"BlkioDeviceReadIOps,omitempty"` 770 BlkioDeviceWriteBps []BlockLimit `json:"BlkioDeviceWriteBps,omitempty" yaml:"BlkioDeviceWriteBps,omitempty" toml:"BlkioDeviceWriteBps,omitempty"` 771 BlkioDeviceWriteIOps []BlockLimit `json:"BlkioDeviceWriteIOps,omitempty" yaml:"BlkioDeviceWriteIOps,omitempty" toml:"BlkioDeviceWriteIOps,omitempty"` 772 Ulimits []ULimit `json:"Ulimits,omitempty" yaml:"Ulimits,omitempty" toml:"Ulimits,omitempty"` 773 VolumeDriver string `json:"VolumeDriver,omitempty" yaml:"VolumeDriver,omitempty" toml:"VolumeDriver,omitempty"` 774 OomScoreAdj int `json:"OomScoreAdj,omitempty" yaml:"OomScoreAdj,omitempty" toml:"OomScoreAdj,omitempty"` 775 PidsLimit int64 `json:"PidsLimit,omitempty" yaml:"PidsLimit,omitempty" toml:"PidsLimit,omitempty"` 776 ShmSize int64 `json:"ShmSize,omitempty" yaml:"ShmSize,omitempty" toml:"ShmSize,omitempty"` 777 Tmpfs map[string]string `json:"Tmpfs,omitempty" yaml:"Tmpfs,omitempty" toml:"Tmpfs,omitempty"` 778 Privileged bool `json:"Privileged,omitempty" yaml:"Privileged,omitempty" toml:"Privileged,omitempty"` 779 PublishAllPorts bool `json:"PublishAllPorts,omitempty" yaml:"PublishAllPorts,omitempty" toml:"PublishAllPorts,omitempty"` 780 ReadonlyRootfs bool `json:"ReadonlyRootfs,omitempty" yaml:"ReadonlyRootfs,omitempty" toml:"ReadonlyRootfs,omitempty"` 781 OOMKillDisable bool `json:"OomKillDisable,omitempty" yaml:"OomKillDisable,omitempty" toml:"OomKillDisable,omitempty"` 782 AutoRemove bool `json:"AutoRemove,omitempty" yaml:"AutoRemove,omitempty" toml:"AutoRemove,omitempty"` 783 StorageOpt map[string]string `json:"StorageOpt,omitempty" yaml:"StorageOpt,omitempty" toml:"StorageOpt,omitempty"` 784 Sysctls map[string]string `json:"Sysctls,omitempty" yaml:"Sysctls,omitempty" toml:"Sysctls,omitempty"` 785 CPUCount int64 `json:"CpuCount,omitempty" yaml:"CpuCount,omitempty"` 786 CPUPercent int64 `json:"CpuPercent,omitempty" yaml:"CpuPercent,omitempty"` 787 IOMaximumBandwidth int64 `json:"IOMaximumBandwidth,omitempty" yaml:"IOMaximumBandwidth,omitempty"` 788 IOMaximumIOps int64 `json:"IOMaximumIOps,omitempty" yaml:"IOMaximumIOps,omitempty"` 789 Mounts []HostMount `json:"Mounts,omitempty" yaml:"Mounts,omitempty" toml:"Mounts,omitempty"` 790 Init bool `json:",omitempty" yaml:",omitempty"` 791 Runtime string `json:"Runtime,omitempty" yaml:"Runtime,omitempty" toml:"Runtime,omitempty"` 792} 793 794// NetworkingConfig represents the container's networking configuration for each of its interfaces 795// Carries the networking configs specified in the `docker run` and `docker network connect` commands 796type NetworkingConfig struct { 797 EndpointsConfig map[string]*EndpointConfig `json:"EndpointsConfig" yaml:"EndpointsConfig" toml:"EndpointsConfig"` // Endpoint configs for each connecting network 798} 799 800// StartContainer starts a container, returning an error in case of failure. 801// 802// Passing the HostConfig to this method has been deprecated in Docker API 1.22 803// (Docker Engine 1.10.x) and totally removed in Docker API 1.24 (Docker Engine 804// 1.12.x). The client will ignore the parameter when communicating with Docker 805// API 1.24 or greater. 806// 807// See https://goo.gl/fbOSZy for more details. 808func (c *Client) StartContainer(id string, hostConfig *HostConfig) error { 809 return c.startContainer(id, hostConfig, doOptions{}) 810} 811 812// StartContainerWithContext starts a container, returning an error in case of 813// failure. The context can be used to cancel the outstanding start container 814// request. 815// 816// Passing the HostConfig to this method has been deprecated in Docker API 1.22 817// (Docker Engine 1.10.x) and totally removed in Docker API 1.24 (Docker Engine 818// 1.12.x). The client will ignore the parameter when communicating with Docker 819// API 1.24 or greater. 820// 821// See https://goo.gl/fbOSZy for more details. 822func (c *Client) StartContainerWithContext(id string, hostConfig *HostConfig, ctx context.Context) error { 823 return c.startContainer(id, hostConfig, doOptions{context: ctx}) 824} 825 826func (c *Client) startContainer(id string, hostConfig *HostConfig, opts doOptions) error { 827 path := "/containers/" + id + "/start" 828 if c.serverAPIVersion == nil { 829 c.checkAPIVersion() 830 } 831 if c.serverAPIVersion != nil && c.serverAPIVersion.LessThan(apiVersion124) { 832 opts.data = hostConfig 833 opts.forceJSON = true 834 } 835 resp, err := c.do("POST", path, opts) 836 if err != nil { 837 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { 838 return &NoSuchContainer{ID: id, Err: err} 839 } 840 return err 841 } 842 defer resp.Body.Close() 843 if resp.StatusCode == http.StatusNotModified { 844 return &ContainerAlreadyRunning{ID: id} 845 } 846 return nil 847} 848 849// StopContainer stops a container, killing it after the given timeout (in 850// seconds). 851// 852// See https://goo.gl/R9dZcV for more details. 853func (c *Client) StopContainer(id string, timeout uint) error { 854 return c.stopContainer(id, timeout, doOptions{}) 855} 856 857// StopContainerWithContext stops a container, killing it after the given 858// timeout (in seconds). The context can be used to cancel the stop 859// container request. 860// 861// See https://goo.gl/R9dZcV for more details. 862func (c *Client) StopContainerWithContext(id string, timeout uint, ctx context.Context) error { 863 return c.stopContainer(id, timeout, doOptions{context: ctx}) 864} 865 866func (c *Client) stopContainer(id string, timeout uint, opts doOptions) error { 867 path := fmt.Sprintf("/containers/%s/stop?t=%d", id, timeout) 868 resp, err := c.do("POST", path, opts) 869 if err != nil { 870 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { 871 return &NoSuchContainer{ID: id} 872 } 873 return err 874 } 875 defer resp.Body.Close() 876 if resp.StatusCode == http.StatusNotModified { 877 return &ContainerNotRunning{ID: id} 878 } 879 return nil 880} 881 882// RestartContainer stops a container, killing it after the given timeout (in 883// seconds), during the stop process. 884// 885// See https://goo.gl/MrAKQ5 for more details. 886func (c *Client) RestartContainer(id string, timeout uint) error { 887 path := fmt.Sprintf("/containers/%s/restart?t=%d", id, timeout) 888 resp, err := c.do("POST", path, doOptions{}) 889 if err != nil { 890 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { 891 return &NoSuchContainer{ID: id} 892 } 893 return err 894 } 895 resp.Body.Close() 896 return nil 897} 898 899// PauseContainer pauses the given container. 900// 901// See https://goo.gl/D1Yaii for more details. 902func (c *Client) PauseContainer(id string) error { 903 path := fmt.Sprintf("/containers/%s/pause", id) 904 resp, err := c.do("POST", path, doOptions{}) 905 if err != nil { 906 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { 907 return &NoSuchContainer{ID: id} 908 } 909 return err 910 } 911 resp.Body.Close() 912 return nil 913} 914 915// UnpauseContainer unpauses the given container. 916// 917// See https://goo.gl/sZ2faO for more details. 918func (c *Client) UnpauseContainer(id string) error { 919 path := fmt.Sprintf("/containers/%s/unpause", id) 920 resp, err := c.do("POST", path, doOptions{}) 921 if err != nil { 922 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { 923 return &NoSuchContainer{ID: id} 924 } 925 return err 926 } 927 resp.Body.Close() 928 return nil 929} 930 931// TopResult represents the list of processes running in a container, as 932// returned by /containers/<id>/top. 933// 934// See https://goo.gl/FLwpPl for more details. 935type TopResult struct { 936 Titles []string 937 Processes [][]string 938} 939 940// TopContainer returns processes running inside a container 941// 942// See https://goo.gl/FLwpPl for more details. 943func (c *Client) TopContainer(id string, psArgs string) (TopResult, error) { 944 var args string 945 var result TopResult 946 if psArgs != "" { 947 args = fmt.Sprintf("?ps_args=%s", psArgs) 948 } 949 path := fmt.Sprintf("/containers/%s/top%s", id, args) 950 resp, err := c.do("GET", path, doOptions{}) 951 if err != nil { 952 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { 953 return result, &NoSuchContainer{ID: id} 954 } 955 return result, err 956 } 957 defer resp.Body.Close() 958 err = json.NewDecoder(resp.Body).Decode(&result) 959 return result, err 960} 961 962// Stats represents container statistics, returned by /containers/<id>/stats. 963// 964// See https://goo.gl/Dk3Xio for more details. 965type Stats struct { 966 Read time.Time `json:"read,omitempty" yaml:"read,omitempty" toml:"read,omitempty"` 967 PreRead time.Time `json:"preread,omitempty" yaml:"preread,omitempty" toml:"preread,omitempty"` 968 NumProcs uint32 `json:"num_procs" yaml:"num_procs" toml:"num_procs"` 969 PidsStats struct { 970 Current uint64 `json:"current,omitempty" yaml:"current,omitempty"` 971 } `json:"pids_stats,omitempty" yaml:"pids_stats,omitempty" toml:"pids_stats,omitempty"` 972 Network NetworkStats `json:"network,omitempty" yaml:"network,omitempty" toml:"network,omitempty"` 973 Networks map[string]NetworkStats `json:"networks,omitempty" yaml:"networks,omitempty" toml:"networks,omitempty"` 974 MemoryStats struct { 975 Stats struct { 976 TotalPgmafault uint64 `json:"total_pgmafault,omitempty" yaml:"total_pgmafault,omitempty" toml:"total_pgmafault,omitempty"` 977 Cache uint64 `json:"cache,omitempty" yaml:"cache,omitempty" toml:"cache,omitempty"` 978 MappedFile uint64 `json:"mapped_file,omitempty" yaml:"mapped_file,omitempty" toml:"mapped_file,omitempty"` 979 TotalInactiveFile uint64 `json:"total_inactive_file,omitempty" yaml:"total_inactive_file,omitempty" toml:"total_inactive_file,omitempty"` 980 Pgpgout uint64 `json:"pgpgout,omitempty" yaml:"pgpgout,omitempty" toml:"pgpgout,omitempty"` 981 Rss uint64 `json:"rss,omitempty" yaml:"rss,omitempty" toml:"rss,omitempty"` 982 TotalMappedFile uint64 `json:"total_mapped_file,omitempty" yaml:"total_mapped_file,omitempty" toml:"total_mapped_file,omitempty"` 983 Writeback uint64 `json:"writeback,omitempty" yaml:"writeback,omitempty" toml:"writeback,omitempty"` 984 Unevictable uint64 `json:"unevictable,omitempty" yaml:"unevictable,omitempty" toml:"unevictable,omitempty"` 985 Pgpgin uint64 `json:"pgpgin,omitempty" yaml:"pgpgin,omitempty" toml:"pgpgin,omitempty"` 986 TotalUnevictable uint64 `json:"total_unevictable,omitempty" yaml:"total_unevictable,omitempty" toml:"total_unevictable,omitempty"` 987 Pgmajfault uint64 `json:"pgmajfault,omitempty" yaml:"pgmajfault,omitempty" toml:"pgmajfault,omitempty"` 988 TotalRss uint64 `json:"total_rss,omitempty" yaml:"total_rss,omitempty" toml:"total_rss,omitempty"` 989 TotalRssHuge uint64 `json:"total_rss_huge,omitempty" yaml:"total_rss_huge,omitempty" toml:"total_rss_huge,omitempty"` 990 TotalWriteback uint64 `json:"total_writeback,omitempty" yaml:"total_writeback,omitempty" toml:"total_writeback,omitempty"` 991 TotalInactiveAnon uint64 `json:"total_inactive_anon,omitempty" yaml:"total_inactive_anon,omitempty" toml:"total_inactive_anon,omitempty"` 992 RssHuge uint64 `json:"rss_huge,omitempty" yaml:"rss_huge,omitempty" toml:"rss_huge,omitempty"` 993 HierarchicalMemoryLimit uint64 `json:"hierarchical_memory_limit,omitempty" yaml:"hierarchical_memory_limit,omitempty" toml:"hierarchical_memory_limit,omitempty"` 994 TotalPgfault uint64 `json:"total_pgfault,omitempty" yaml:"total_pgfault,omitempty" toml:"total_pgfault,omitempty"` 995 TotalActiveFile uint64 `json:"total_active_file,omitempty" yaml:"total_active_file,omitempty" toml:"total_active_file,omitempty"` 996 ActiveAnon uint64 `json:"active_anon,omitempty" yaml:"active_anon,omitempty" toml:"active_anon,omitempty"` 997 TotalActiveAnon uint64 `json:"total_active_anon,omitempty" yaml:"total_active_anon,omitempty" toml:"total_active_anon,omitempty"` 998 TotalPgpgout uint64 `json:"total_pgpgout,omitempty" yaml:"total_pgpgout,omitempty" toml:"total_pgpgout,omitempty"` 999 TotalCache uint64 `json:"total_cache,omitempty" yaml:"total_cache,omitempty" toml:"total_cache,omitempty"` 1000 InactiveAnon uint64 `json:"inactive_anon,omitempty" yaml:"inactive_anon,omitempty" toml:"inactive_anon,omitempty"` 1001 ActiveFile uint64 `json:"active_file,omitempty" yaml:"active_file,omitempty" toml:"active_file,omitempty"` 1002 Pgfault uint64 `json:"pgfault,omitempty" yaml:"pgfault,omitempty" toml:"pgfault,omitempty"` 1003 InactiveFile uint64 `json:"inactive_file,omitempty" yaml:"inactive_file,omitempty" toml:"inactive_file,omitempty"` 1004 TotalPgpgin uint64 `json:"total_pgpgin,omitempty" yaml:"total_pgpgin,omitempty" toml:"total_pgpgin,omitempty"` 1005 HierarchicalMemswLimit uint64 `json:"hierarchical_memsw_limit,omitempty" yaml:"hierarchical_memsw_limit,omitempty" toml:"hierarchical_memsw_limit,omitempty"` 1006 Swap uint64 `json:"swap,omitempty" yaml:"swap,omitempty" toml:"swap,omitempty"` 1007 } `json:"stats,omitempty" yaml:"stats,omitempty" toml:"stats,omitempty"` 1008 MaxUsage uint64 `json:"max_usage,omitempty" yaml:"max_usage,omitempty" toml:"max_usage,omitempty"` 1009 Usage uint64 `json:"usage,omitempty" yaml:"usage,omitempty" toml:"usage,omitempty"` 1010 Failcnt uint64 `json:"failcnt,omitempty" yaml:"failcnt,omitempty" toml:"failcnt,omitempty"` 1011 Limit uint64 `json:"limit,omitempty" yaml:"limit,omitempty" toml:"limit,omitempty"` 1012 Commit uint64 `json:"commitbytes,omitempty" yaml:"commitbytes,omitempty" toml:"privateworkingset,omitempty"` 1013 CommitPeak uint64 `json:"commitpeakbytes,omitempty" yaml:"commitpeakbytes,omitempty" toml:"commitpeakbytes,omitempty"` 1014 PrivateWorkingSet uint64 `json:"privateworkingset,omitempty" yaml:"privateworkingset,omitempty" toml:"privateworkingset,omitempty"` 1015 } `json:"memory_stats,omitempty" yaml:"memory_stats,omitempty" toml:"memory_stats,omitempty"` 1016 BlkioStats struct { 1017 IOServiceBytesRecursive []BlkioStatsEntry `json:"io_service_bytes_recursive,omitempty" yaml:"io_service_bytes_recursive,omitempty" toml:"io_service_bytes_recursive,omitempty"` 1018 IOServicedRecursive []BlkioStatsEntry `json:"io_serviced_recursive,omitempty" yaml:"io_serviced_recursive,omitempty" toml:"io_serviced_recursive,omitempty"` 1019 IOQueueRecursive []BlkioStatsEntry `json:"io_queue_recursive,omitempty" yaml:"io_queue_recursive,omitempty" toml:"io_queue_recursive,omitempty"` 1020 IOServiceTimeRecursive []BlkioStatsEntry `json:"io_service_time_recursive,omitempty" yaml:"io_service_time_recursive,omitempty" toml:"io_service_time_recursive,omitempty"` 1021 IOWaitTimeRecursive []BlkioStatsEntry `json:"io_wait_time_recursive,omitempty" yaml:"io_wait_time_recursive,omitempty" toml:"io_wait_time_recursive,omitempty"` 1022 IOMergedRecursive []BlkioStatsEntry `json:"io_merged_recursive,omitempty" yaml:"io_merged_recursive,omitempty" toml:"io_merged_recursive,omitempty"` 1023 IOTimeRecursive []BlkioStatsEntry `json:"io_time_recursive,omitempty" yaml:"io_time_recursive,omitempty" toml:"io_time_recursive,omitempty"` 1024 SectorsRecursive []BlkioStatsEntry `json:"sectors_recursive,omitempty" yaml:"sectors_recursive,omitempty" toml:"sectors_recursive,omitempty"` 1025 } `json:"blkio_stats,omitempty" yaml:"blkio_stats,omitempty" toml:"blkio_stats,omitempty"` 1026 CPUStats CPUStats `json:"cpu_stats,omitempty" yaml:"cpu_stats,omitempty" toml:"cpu_stats,omitempty"` 1027 PreCPUStats CPUStats `json:"precpu_stats,omitempty"` 1028 StorageStats struct { 1029 ReadCountNormalized uint64 `json:"read_count_normalized,omitempty" yaml:"read_count_normalized,omitempty" toml:"read_count_normalized,omitempty"` 1030 ReadSizeBytes uint64 `json:"read_size_bytes,omitempty" yaml:"read_size_bytes,omitempty" toml:"read_size_bytes,omitempty"` 1031 WriteCountNormalized uint64 `json:"write_count_normalized,omitempty" yaml:"write_count_normalized,omitempty" toml:"write_count_normalized,omitempty"` 1032 WriteSizeBytes uint64 `json:"write_size_bytes,omitempty" yaml:"write_size_bytes,omitempty" toml:"write_size_bytes,omitempty"` 1033 } `json:"storage_stats,omitempty" yaml:"storage_stats,omitempty" toml:"storage_stats,omitempty"` 1034} 1035 1036// NetworkStats is a stats entry for network stats 1037type NetworkStats struct { 1038 RxDropped uint64 `json:"rx_dropped,omitempty" yaml:"rx_dropped,omitempty" toml:"rx_dropped,omitempty"` 1039 RxBytes uint64 `json:"rx_bytes,omitempty" yaml:"rx_bytes,omitempty" toml:"rx_bytes,omitempty"` 1040 RxErrors uint64 `json:"rx_errors,omitempty" yaml:"rx_errors,omitempty" toml:"rx_errors,omitempty"` 1041 TxPackets uint64 `json:"tx_packets,omitempty" yaml:"tx_packets,omitempty" toml:"tx_packets,omitempty"` 1042 TxDropped uint64 `json:"tx_dropped,omitempty" yaml:"tx_dropped,omitempty" toml:"tx_dropped,omitempty"` 1043 RxPackets uint64 `json:"rx_packets,omitempty" yaml:"rx_packets,omitempty" toml:"rx_packets,omitempty"` 1044 TxErrors uint64 `json:"tx_errors,omitempty" yaml:"tx_errors,omitempty" toml:"tx_errors,omitempty"` 1045 TxBytes uint64 `json:"tx_bytes,omitempty" yaml:"tx_bytes,omitempty" toml:"tx_bytes,omitempty"` 1046} 1047 1048// CPUStats is a stats entry for cpu stats 1049type CPUStats struct { 1050 CPUUsage struct { 1051 PercpuUsage []uint64 `json:"percpu_usage,omitempty" yaml:"percpu_usage,omitempty" toml:"percpu_usage,omitempty"` 1052 UsageInUsermode uint64 `json:"usage_in_usermode,omitempty" yaml:"usage_in_usermode,omitempty" toml:"usage_in_usermode,omitempty"` 1053 TotalUsage uint64 `json:"total_usage,omitempty" yaml:"total_usage,omitempty" toml:"total_usage,omitempty"` 1054 UsageInKernelmode uint64 `json:"usage_in_kernelmode,omitempty" yaml:"usage_in_kernelmode,omitempty" toml:"usage_in_kernelmode,omitempty"` 1055 } `json:"cpu_usage,omitempty" yaml:"cpu_usage,omitempty" toml:"cpu_usage,omitempty"` 1056 SystemCPUUsage uint64 `json:"system_cpu_usage,omitempty" yaml:"system_cpu_usage,omitempty" toml:"system_cpu_usage,omitempty"` 1057 OnlineCPUs uint64 `json:"online_cpus,omitempty" yaml:"online_cpus,omitempty" toml:"online_cpus,omitempty"` 1058 ThrottlingData struct { 1059 Periods uint64 `json:"periods,omitempty"` 1060 ThrottledPeriods uint64 `json:"throttled_periods,omitempty"` 1061 ThrottledTime uint64 `json:"throttled_time,omitempty"` 1062 } `json:"throttling_data,omitempty" yaml:"throttling_data,omitempty" toml:"throttling_data,omitempty"` 1063} 1064 1065// BlkioStatsEntry is a stats entry for blkio_stats 1066type BlkioStatsEntry struct { 1067 Major uint64 `json:"major,omitempty" yaml:"major,omitempty" toml:"major,omitempty"` 1068 Minor uint64 `json:"minor,omitempty" yaml:"minor,omitempty" toml:"minor,omitempty"` 1069 Op string `json:"op,omitempty" yaml:"op,omitempty" toml:"op,omitempty"` 1070 Value uint64 `json:"value,omitempty" yaml:"value,omitempty" toml:"value,omitempty"` 1071} 1072 1073// StatsOptions specify parameters to the Stats function. 1074// 1075// See https://goo.gl/Dk3Xio for more details. 1076type StatsOptions struct { 1077 ID string 1078 Stats chan<- *Stats 1079 Stream bool 1080 // A flag that enables stopping the stats operation 1081 Done <-chan bool 1082 // Initial connection timeout 1083 Timeout time.Duration 1084 // Timeout with no data is received, it's reset every time new data 1085 // arrives 1086 InactivityTimeout time.Duration `qs:"-"` 1087 Context context.Context 1088} 1089 1090// Stats sends container statistics for the given container to the given channel. 1091// 1092// This function is blocking, similar to a streaming call for logs, and should be run 1093// on a separate goroutine from the caller. Note that this function will block until 1094// the given container is removed, not just exited. When finished, this function 1095// will close the given channel. Alternatively, function can be stopped by 1096// signaling on the Done channel. 1097// 1098// See https://goo.gl/Dk3Xio for more details. 1099func (c *Client) Stats(opts StatsOptions) (retErr error) { 1100 errC := make(chan error, 1) 1101 readCloser, writeCloser := io.Pipe() 1102 1103 defer func() { 1104 close(opts.Stats) 1105 1106 select { 1107 case err := <-errC: 1108 if err != nil && retErr == nil { 1109 retErr = err 1110 } 1111 default: 1112 // No errors 1113 } 1114 1115 if err := readCloser.Close(); err != nil && retErr == nil { 1116 retErr = err 1117 } 1118 }() 1119 1120 reqSent := make(chan struct{}) 1121 go func() { 1122 err := c.stream("GET", fmt.Sprintf("/containers/%s/stats?stream=%v", opts.ID, opts.Stream), streamOptions{ 1123 rawJSONStream: true, 1124 useJSONDecoder: true, 1125 stdout: writeCloser, 1126 timeout: opts.Timeout, 1127 inactivityTimeout: opts.InactivityTimeout, 1128 context: opts.Context, 1129 reqSent: reqSent, 1130 }) 1131 if err != nil { 1132 dockerError, ok := err.(*Error) 1133 if ok { 1134 if dockerError.Status == http.StatusNotFound { 1135 err = &NoSuchContainer{ID: opts.ID} 1136 } 1137 } 1138 } 1139 if closeErr := writeCloser.Close(); closeErr != nil && err == nil { 1140 err = closeErr 1141 } 1142 errC <- err 1143 close(errC) 1144 }() 1145 1146 quit := make(chan struct{}) 1147 defer close(quit) 1148 go func() { 1149 // block here waiting for the signal to stop function 1150 select { 1151 case <-opts.Done: 1152 readCloser.Close() 1153 case <-quit: 1154 return 1155 } 1156 }() 1157 1158 decoder := json.NewDecoder(readCloser) 1159 stats := new(Stats) 1160 <-reqSent 1161 for err := decoder.Decode(stats); err != io.EOF; err = decoder.Decode(stats) { 1162 if err != nil { 1163 return err 1164 } 1165 opts.Stats <- stats 1166 stats = new(Stats) 1167 } 1168 return nil 1169} 1170 1171// KillContainerOptions represents the set of options that can be used in a 1172// call to KillContainer. 1173// 1174// See https://goo.gl/JnTxXZ for more details. 1175type KillContainerOptions struct { 1176 // The ID of the container. 1177 ID string `qs:"-"` 1178 1179 // The signal to send to the container. When omitted, Docker server 1180 // will assume SIGKILL. 1181 Signal Signal 1182 Context context.Context 1183} 1184 1185// KillContainer sends a signal to a container, returning an error in case of 1186// failure. 1187// 1188// See https://goo.gl/JnTxXZ for more details. 1189func (c *Client) KillContainer(opts KillContainerOptions) error { 1190 path := "/containers/" + opts.ID + "/kill" + "?" + queryString(opts) 1191 resp, err := c.do("POST", path, doOptions{context: opts.Context}) 1192 if err != nil { 1193 e, ok := err.(*Error) 1194 if !ok { 1195 return err 1196 } 1197 switch e.Status { 1198 case http.StatusNotFound: 1199 return &NoSuchContainer{ID: opts.ID} 1200 case http.StatusConflict: 1201 return &ContainerNotRunning{ID: opts.ID} 1202 default: 1203 return err 1204 } 1205 } 1206 resp.Body.Close() 1207 return nil 1208} 1209 1210// RemoveContainerOptions encapsulates options to remove a container. 1211// 1212// See https://goo.gl/hL5IPC for more details. 1213type RemoveContainerOptions struct { 1214 // The ID of the container. 1215 ID string `qs:"-"` 1216 1217 // A flag that indicates whether Docker should remove the volumes 1218 // associated to the container. 1219 RemoveVolumes bool `qs:"v"` 1220 1221 // A flag that indicates whether Docker should remove the container 1222 // even if it is currently running. 1223 Force bool 1224 Context context.Context 1225} 1226 1227// RemoveContainer removes a container, returning an error in case of failure. 1228// 1229// See https://goo.gl/hL5IPC for more details. 1230func (c *Client) RemoveContainer(opts RemoveContainerOptions) error { 1231 path := "/containers/" + opts.ID + "?" + queryString(opts) 1232 resp, err := c.do("DELETE", path, doOptions{context: opts.Context}) 1233 if err != nil { 1234 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { 1235 return &NoSuchContainer{ID: opts.ID} 1236 } 1237 return err 1238 } 1239 resp.Body.Close() 1240 return nil 1241} 1242 1243// UploadToContainerOptions is the set of options that can be used when 1244// uploading an archive into a container. 1245// 1246// See https://goo.gl/g25o7u for more details. 1247type UploadToContainerOptions struct { 1248 InputStream io.Reader `json:"-" qs:"-"` 1249 Path string `qs:"path"` 1250 NoOverwriteDirNonDir bool `qs:"noOverwriteDirNonDir"` 1251 Context context.Context 1252} 1253 1254// UploadToContainer uploads a tar archive to be extracted to a path in the 1255// filesystem of the container. 1256// 1257// See https://goo.gl/g25o7u for more details. 1258func (c *Client) UploadToContainer(id string, opts UploadToContainerOptions) error { 1259 url := fmt.Sprintf("/containers/%s/archive?", id) + queryString(opts) 1260 1261 return c.stream("PUT", url, streamOptions{ 1262 in: opts.InputStream, 1263 context: opts.Context, 1264 }) 1265} 1266 1267// DownloadFromContainerOptions is the set of options that can be used when 1268// downloading resources from a container. 1269// 1270// See https://goo.gl/W49jxK for more details. 1271type DownloadFromContainerOptions struct { 1272 OutputStream io.Writer `json:"-" qs:"-"` 1273 Path string `qs:"path"` 1274 InactivityTimeout time.Duration `qs:"-"` 1275 Context context.Context 1276} 1277 1278// DownloadFromContainer downloads a tar archive of files or folders in a container. 1279// 1280// See https://goo.gl/W49jxK for more details. 1281func (c *Client) DownloadFromContainer(id string, opts DownloadFromContainerOptions) error { 1282 url := fmt.Sprintf("/containers/%s/archive?", id) + queryString(opts) 1283 1284 return c.stream("GET", url, streamOptions{ 1285 setRawTerminal: true, 1286 stdout: opts.OutputStream, 1287 inactivityTimeout: opts.InactivityTimeout, 1288 context: opts.Context, 1289 }) 1290} 1291 1292// CopyFromContainerOptions contains the set of options used for copying 1293// files from a container. 1294// 1295// Deprecated: Use DownloadFromContainerOptions and DownloadFromContainer instead. 1296type CopyFromContainerOptions struct { 1297 OutputStream io.Writer `json:"-"` 1298 Container string `json:"-"` 1299 Resource string 1300 Context context.Context `json:"-"` 1301} 1302 1303// CopyFromContainer copies files from a container. 1304// 1305// Deprecated: Use DownloadFromContainer and DownloadFromContainer instead. 1306func (c *Client) CopyFromContainer(opts CopyFromContainerOptions) error { 1307 if opts.Container == "" { 1308 return &NoSuchContainer{ID: opts.Container} 1309 } 1310 if c.serverAPIVersion == nil { 1311 c.checkAPIVersion() 1312 } 1313 if c.serverAPIVersion != nil && c.serverAPIVersion.GreaterThanOrEqualTo(apiVersion124) { 1314 return errors.New("go-dockerclient: CopyFromContainer is no longer available in Docker >= 1.12, use DownloadFromContainer instead") 1315 } 1316 url := fmt.Sprintf("/containers/%s/copy", opts.Container) 1317 resp, err := c.do("POST", url, doOptions{ 1318 data: opts, 1319 context: opts.Context, 1320 }) 1321 if err != nil { 1322 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { 1323 return &NoSuchContainer{ID: opts.Container} 1324 } 1325 return err 1326 } 1327 defer resp.Body.Close() 1328 _, err = io.Copy(opts.OutputStream, resp.Body) 1329 return err 1330} 1331 1332// WaitContainer blocks until the given container stops, return the exit code 1333// of the container status. 1334// 1335// See https://goo.gl/4AGweZ for more details. 1336func (c *Client) WaitContainer(id string) (int, error) { 1337 return c.waitContainer(id, doOptions{}) 1338} 1339 1340// WaitContainerWithContext blocks until the given container stops, return the exit code 1341// of the container status. The context object can be used to cancel the 1342// inspect request. 1343// 1344// See https://goo.gl/4AGweZ for more details. 1345func (c *Client) WaitContainerWithContext(id string, ctx context.Context) (int, error) { 1346 return c.waitContainer(id, doOptions{context: ctx}) 1347} 1348 1349func (c *Client) waitContainer(id string, opts doOptions) (int, error) { 1350 resp, err := c.do("POST", "/containers/"+id+"/wait", opts) 1351 if err != nil { 1352 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { 1353 return 0, &NoSuchContainer{ID: id} 1354 } 1355 return 0, err 1356 } 1357 defer resp.Body.Close() 1358 var r struct{ StatusCode int } 1359 if err := json.NewDecoder(resp.Body).Decode(&r); err != nil { 1360 return 0, err 1361 } 1362 return r.StatusCode, nil 1363} 1364 1365// CommitContainerOptions aggregates parameters to the CommitContainer method. 1366// 1367// See https://goo.gl/CzIguf for more details. 1368type CommitContainerOptions struct { 1369 Container string 1370 Repository string `qs:"repo"` 1371 Tag string 1372 Message string `qs:"comment"` 1373 Author string 1374 Changes []string `qs:"changes"` 1375 Run *Config `qs:"-"` 1376 Context context.Context 1377} 1378 1379// CommitContainer creates a new image from a container's changes. 1380// 1381// See https://goo.gl/CzIguf for more details. 1382func (c *Client) CommitContainer(opts CommitContainerOptions) (*Image, error) { 1383 path := "/commit?" + queryString(opts) 1384 resp, err := c.do("POST", path, doOptions{ 1385 data: opts.Run, 1386 context: opts.Context, 1387 }) 1388 if err != nil { 1389 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { 1390 return nil, &NoSuchContainer{ID: opts.Container} 1391 } 1392 return nil, err 1393 } 1394 defer resp.Body.Close() 1395 var image Image 1396 if err := json.NewDecoder(resp.Body).Decode(&image); err != nil { 1397 return nil, err 1398 } 1399 return &image, nil 1400} 1401 1402// AttachToContainerOptions is the set of options that can be used when 1403// attaching to a container. 1404// 1405// See https://goo.gl/JF10Zk for more details. 1406type AttachToContainerOptions struct { 1407 Container string `qs:"-"` 1408 InputStream io.Reader `qs:"-"` 1409 OutputStream io.Writer `qs:"-"` 1410 ErrorStream io.Writer `qs:"-"` 1411 1412 // If set, after a successful connect, a sentinel will be sent and then the 1413 // client will block on receive before continuing. 1414 // 1415 // It must be an unbuffered channel. Using a buffered channel can lead 1416 // to unexpected behavior. 1417 Success chan struct{} 1418 1419 // Use raw terminal? Usually true when the container contains a TTY. 1420 RawTerminal bool `qs:"-"` 1421 1422 // Get container logs, sending it to OutputStream. 1423 Logs bool 1424 1425 // Stream the response? 1426 Stream bool 1427 1428 // Attach to stdin, and use InputStream. 1429 Stdin bool 1430 1431 // Attach to stdout, and use OutputStream. 1432 Stdout bool 1433 1434 // Attach to stderr, and use ErrorStream. 1435 Stderr bool 1436} 1437 1438// AttachToContainer attaches to a container, using the given options. 1439// 1440// See https://goo.gl/JF10Zk for more details. 1441func (c *Client) AttachToContainer(opts AttachToContainerOptions) error { 1442 cw, err := c.AttachToContainerNonBlocking(opts) 1443 if err != nil { 1444 return err 1445 } 1446 return cw.Wait() 1447} 1448 1449// AttachToContainerNonBlocking attaches to a container, using the given options. 1450// This function does not block. 1451// 1452// See https://goo.gl/NKpkFk for more details. 1453func (c *Client) AttachToContainerNonBlocking(opts AttachToContainerOptions) (CloseWaiter, error) { 1454 if opts.Container == "" { 1455 return nil, &NoSuchContainer{ID: opts.Container} 1456 } 1457 path := "/containers/" + opts.Container + "/attach?" + queryString(opts) 1458 return c.hijack("POST", path, hijackOptions{ 1459 success: opts.Success, 1460 setRawTerminal: opts.RawTerminal, 1461 in: opts.InputStream, 1462 stdout: opts.OutputStream, 1463 stderr: opts.ErrorStream, 1464 }) 1465} 1466 1467// LogsOptions represents the set of options used when getting logs from a 1468// container. 1469// 1470// See https://goo.gl/krK0ZH for more details. 1471type LogsOptions struct { 1472 Context context.Context 1473 Container string `qs:"-"` 1474 OutputStream io.Writer `qs:"-"` 1475 ErrorStream io.Writer `qs:"-"` 1476 InactivityTimeout time.Duration `qs:"-"` 1477 Tail string 1478 1479 Since int64 1480 Follow bool 1481 Stdout bool 1482 Stderr bool 1483 Timestamps bool 1484 1485 // Use raw terminal? Usually true when the container contains a TTY. 1486 RawTerminal bool `qs:"-"` 1487} 1488 1489// Logs gets stdout and stderr logs from the specified container. 1490// 1491// When LogsOptions.RawTerminal is set to false, go-dockerclient will multiplex 1492// the streams and send the containers stdout to LogsOptions.OutputStream, and 1493// stderr to LogsOptions.ErrorStream. 1494// 1495// When LogsOptions.RawTerminal is true, callers will get the raw stream on 1496// LogsOptions.OutputStream. The caller can use libraries such as dlog 1497// (github.com/ahmetalpbalkan/dlog). 1498// 1499// See https://goo.gl/krK0ZH for more details. 1500func (c *Client) Logs(opts LogsOptions) error { 1501 if opts.Container == "" { 1502 return &NoSuchContainer{ID: opts.Container} 1503 } 1504 if opts.Tail == "" { 1505 opts.Tail = "all" 1506 } 1507 path := "/containers/" + opts.Container + "/logs?" + queryString(opts) 1508 return c.stream("GET", path, streamOptions{ 1509 setRawTerminal: opts.RawTerminal, 1510 stdout: opts.OutputStream, 1511 stderr: opts.ErrorStream, 1512 inactivityTimeout: opts.InactivityTimeout, 1513 context: opts.Context, 1514 }) 1515} 1516 1517// ResizeContainerTTY resizes the terminal to the given height and width. 1518// 1519// See https://goo.gl/FImjeq for more details. 1520func (c *Client) ResizeContainerTTY(id string, height, width int) error { 1521 params := make(url.Values) 1522 params.Set("h", strconv.Itoa(height)) 1523 params.Set("w", strconv.Itoa(width)) 1524 resp, err := c.do("POST", "/containers/"+id+"/resize?"+params.Encode(), doOptions{}) 1525 if err != nil { 1526 return err 1527 } 1528 resp.Body.Close() 1529 return nil 1530} 1531 1532// ExportContainerOptions is the set of parameters to the ExportContainer 1533// method. 1534// 1535// See https://goo.gl/yGJCIh for more details. 1536type ExportContainerOptions struct { 1537 ID string 1538 OutputStream io.Writer 1539 InactivityTimeout time.Duration `qs:"-"` 1540 Context context.Context 1541} 1542 1543// ExportContainer export the contents of container id as tar archive 1544// and prints the exported contents to stdout. 1545// 1546// See https://goo.gl/yGJCIh for more details. 1547func (c *Client) ExportContainer(opts ExportContainerOptions) error { 1548 if opts.ID == "" { 1549 return &NoSuchContainer{ID: opts.ID} 1550 } 1551 url := fmt.Sprintf("/containers/%s/export", opts.ID) 1552 return c.stream("GET", url, streamOptions{ 1553 setRawTerminal: true, 1554 stdout: opts.OutputStream, 1555 inactivityTimeout: opts.InactivityTimeout, 1556 context: opts.Context, 1557 }) 1558} 1559 1560// PruneContainersOptions specify parameters to the PruneContainers function. 1561// 1562// See https://goo.gl/wnkgDT for more details. 1563type PruneContainersOptions struct { 1564 Filters map[string][]string 1565 Context context.Context 1566} 1567 1568// PruneContainersResults specify results from the PruneContainers function. 1569// 1570// See https://goo.gl/wnkgDT for more details. 1571type PruneContainersResults struct { 1572 ContainersDeleted []string 1573 SpaceReclaimed int64 1574} 1575 1576// PruneContainers deletes containers which are stopped. 1577// 1578// See https://goo.gl/wnkgDT for more details. 1579func (c *Client) PruneContainers(opts PruneContainersOptions) (*PruneContainersResults, error) { 1580 path := "/containers/prune?" + queryString(opts) 1581 resp, err := c.do("POST", path, doOptions{context: opts.Context}) 1582 if err != nil { 1583 return nil, err 1584 } 1585 defer resp.Body.Close() 1586 var results PruneContainersResults 1587 if err := json.NewDecoder(resp.Body).Decode(&results); err != nil { 1588 return nil, err 1589 } 1590 return &results, nil 1591} 1592 1593// NoSuchContainer is the error returned when a given container does not exist. 1594type NoSuchContainer struct { 1595 ID string 1596 Err error 1597} 1598 1599func (err *NoSuchContainer) Error() string { 1600 if err.Err != nil { 1601 return err.Err.Error() 1602 } 1603 return "No such container: " + err.ID 1604} 1605 1606// ContainerAlreadyRunning is the error returned when a given container is 1607// already running. 1608type ContainerAlreadyRunning struct { 1609 ID string 1610} 1611 1612func (err *ContainerAlreadyRunning) Error() string { 1613 return "Container already running: " + err.ID 1614} 1615 1616// ContainerNotRunning is the error returned when a given container is not 1617// running. 1618type ContainerNotRunning struct { 1619 ID string 1620} 1621 1622func (err *ContainerNotRunning) Error() string { 1623 return "Container not running: " + err.ID 1624} 1625