container.go 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325
  1. // Copyright 2015 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. package docker
  5. import (
  6. "encoding/json"
  7. "errors"
  8. "fmt"
  9. "io"
  10. "net/http"
  11. "net/url"
  12. "strconv"
  13. "strings"
  14. "time"
  15. "github.com/fsouza/go-dockerclient/external/github.com/docker/go-units"
  16. )
  17. // ErrContainerAlreadyExists is the error returned by CreateContainer when the
  18. // container already exists.
  19. var ErrContainerAlreadyExists = errors.New("container already exists")
  20. // ListContainersOptions specify parameters to the ListContainers function.
  21. //
  22. // See https://goo.gl/47a6tO for more details.
  23. type ListContainersOptions struct {
  24. All bool
  25. Size bool
  26. Limit int
  27. Since string
  28. Before string
  29. Filters map[string][]string
  30. }
  31. // APIPort is a type that represents a port mapping returned by the Docker API
  32. type APIPort struct {
  33. PrivatePort int64 `json:"PrivatePort,omitempty" yaml:"PrivatePort,omitempty"`
  34. PublicPort int64 `json:"PublicPort,omitempty" yaml:"PublicPort,omitempty"`
  35. Type string `json:"Type,omitempty" yaml:"Type,omitempty"`
  36. IP string `json:"IP,omitempty" yaml:"IP,omitempty"`
  37. }
  38. // APIMount represents a mount point for a container.
  39. type APIMount struct {
  40. Name string `json:"Name,omitempty" yaml:"Name,omitempty"`
  41. Source string `json:"Source,omitempty" yaml:"Source,omitempty"`
  42. Destination string `json:"Destination,omitempty" yaml:"Destination,omitempty"`
  43. Driver string `json:"Driver,omitempty" yaml:"Driver,omitempty"`
  44. Mode string `json:"Mode,omitempty" yaml:"Mode,omitempty"`
  45. RW bool `json:"RW,omitempty" yaml:"RW,omitempty"`
  46. Propogation string `json:"Propogation,omitempty" yaml:"Propogation,omitempty"`
  47. }
  48. // APIContainers represents each container in the list returned by
  49. // ListContainers.
  50. type APIContainers struct {
  51. ID string `json:"Id" yaml:"Id"`
  52. Image string `json:"Image,omitempty" yaml:"Image,omitempty"`
  53. Command string `json:"Command,omitempty" yaml:"Command,omitempty"`
  54. Created int64 `json:"Created,omitempty" yaml:"Created,omitempty"`
  55. State string `json:"State,omitempty" yaml:"State,omitempty"`
  56. Status string `json:"Status,omitempty" yaml:"Status,omitempty"`
  57. Ports []APIPort `json:"Ports,omitempty" yaml:"Ports,omitempty"`
  58. SizeRw int64 `json:"SizeRw,omitempty" yaml:"SizeRw,omitempty"`
  59. SizeRootFs int64 `json:"SizeRootFs,omitempty" yaml:"SizeRootFs,omitempty"`
  60. Names []string `json:"Names,omitempty" yaml:"Names,omitempty"`
  61. Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty"`
  62. Networks NetworkList `json:"NetworkSettings,omitempty" yaml:"NetworkSettings,omitempty"`
  63. Mounts []APIMount `json:"Mounts,omitempty" yaml:"Mounts,omitempty"`
  64. }
  65. // NetworkList encapsulates a map of networks, as returned by the Docker API in
  66. // ListContainers.
  67. type NetworkList struct {
  68. Networks map[string]ContainerNetwork `json:"Networks" yaml:"Networks,omitempty"`
  69. }
  70. // ListContainers returns a slice of containers matching the given criteria.
  71. //
  72. // See https://goo.gl/47a6tO for more details.
  73. func (c *Client) ListContainers(opts ListContainersOptions) ([]APIContainers, error) {
  74. path := "/containers/json?" + queryString(opts)
  75. resp, err := c.do("GET", path, doOptions{})
  76. if err != nil {
  77. return nil, err
  78. }
  79. defer resp.Body.Close()
  80. var containers []APIContainers
  81. if err := json.NewDecoder(resp.Body).Decode(&containers); err != nil {
  82. return nil, err
  83. }
  84. return containers, nil
  85. }
  86. // Port represents the port number and the protocol, in the form
  87. // <number>/<protocol>. For example: 80/tcp.
  88. type Port string
  89. // Port returns the number of the port.
  90. func (p Port) Port() string {
  91. return strings.Split(string(p), "/")[0]
  92. }
  93. // Proto returns the name of the protocol.
  94. func (p Port) Proto() string {
  95. parts := strings.Split(string(p), "/")
  96. if len(parts) == 1 {
  97. return "tcp"
  98. }
  99. return parts[1]
  100. }
  101. // State represents the state of a container.
  102. type State struct {
  103. Status string `json:"Status,omitempty" yaml:"Status,omitempty"`
  104. Running bool `json:"Running,omitempty" yaml:"Running,omitempty"`
  105. Paused bool `json:"Paused,omitempty" yaml:"Paused,omitempty"`
  106. Restarting bool `json:"Restarting,omitempty" yaml:"Restarting,omitempty"`
  107. OOMKilled bool `json:"OOMKilled,omitempty" yaml:"OOMKilled,omitempty"`
  108. RemovalInProgress bool `json:"RemovalInProgress,omitempty" yaml:"RemovalInProgress,omitempty"`
  109. Dead bool `json:"Dead,omitempty" yaml:"Dead,omitempty"`
  110. Pid int `json:"Pid,omitempty" yaml:"Pid,omitempty"`
  111. ExitCode int `json:"ExitCode,omitempty" yaml:"ExitCode,omitempty"`
  112. Error string `json:"Error,omitempty" yaml:"Error,omitempty"`
  113. StartedAt time.Time `json:"StartedAt,omitempty" yaml:"StartedAt,omitempty"`
  114. FinishedAt time.Time `json:"FinishedAt,omitempty" yaml:"FinishedAt,omitempty"`
  115. }
  116. // String returns a human-readable description of the state
  117. func (s *State) String() string {
  118. if s.Running {
  119. if s.Paused {
  120. return fmt.Sprintf("Up %s (Paused)", units.HumanDuration(time.Now().UTC().Sub(s.StartedAt)))
  121. }
  122. if s.Restarting {
  123. return fmt.Sprintf("Restarting (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt)))
  124. }
  125. return fmt.Sprintf("Up %s", units.HumanDuration(time.Now().UTC().Sub(s.StartedAt)))
  126. }
  127. if s.RemovalInProgress {
  128. return "Removal In Progress"
  129. }
  130. if s.Dead {
  131. return "Dead"
  132. }
  133. if s.StartedAt.IsZero() {
  134. return "Created"
  135. }
  136. if s.FinishedAt.IsZero() {
  137. return ""
  138. }
  139. return fmt.Sprintf("Exited (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt)))
  140. }
  141. // StateString returns a single string to describe state
  142. func (s *State) StateString() string {
  143. if s.Running {
  144. if s.Paused {
  145. return "paused"
  146. }
  147. if s.Restarting {
  148. return "restarting"
  149. }
  150. return "running"
  151. }
  152. if s.Dead {
  153. return "dead"
  154. }
  155. if s.StartedAt.IsZero() {
  156. return "created"
  157. }
  158. return "exited"
  159. }
  160. // PortBinding represents the host/container port mapping as returned in the
  161. // `docker inspect` json
  162. type PortBinding struct {
  163. HostIP string `json:"HostIP,omitempty" yaml:"HostIP,omitempty"`
  164. HostPort string `json:"HostPort,omitempty" yaml:"HostPort,omitempty"`
  165. }
  166. // PortMapping represents a deprecated field in the `docker inspect` output,
  167. // and its value as found in NetworkSettings should always be nil
  168. type PortMapping map[string]string
  169. // ContainerNetwork represents the networking settings of a container per network.
  170. type ContainerNetwork struct {
  171. MacAddress string `json:"MacAddress,omitempty" yaml:"MacAddress,omitempty"`
  172. GlobalIPv6PrefixLen int `json:"GlobalIPv6PrefixLen,omitempty" yaml:"GlobalIPv6PrefixLen,omitempty"`
  173. GlobalIPv6Address string `json:"GlobalIPv6Address,omitempty" yaml:"GlobalIPv6Address,omitempty"`
  174. IPv6Gateway string `json:"IPv6Gateway,omitempty" yaml:"IPv6Gateway,omitempty"`
  175. IPPrefixLen int `json:"IPPrefixLen,omitempty" yaml:"IPPrefixLen,omitempty"`
  176. IPAddress string `json:"IPAddress,omitempty" yaml:"IPAddress,omitempty"`
  177. Gateway string `json:"Gateway,omitempty" yaml:"Gateway,omitempty"`
  178. EndpointID string `json:"EndpointID,omitempty" yaml:"EndpointID,omitempty"`
  179. NetworkID string `json:"NetworkID,omitempty" yaml:"NetworkID,omitempty"`
  180. }
  181. // NetworkSettings contains network-related information about a container
  182. type NetworkSettings struct {
  183. Networks map[string]ContainerNetwork `json:"Networks,omitempty" yaml:"Networks,omitempty"`
  184. IPAddress string `json:"IPAddress,omitempty" yaml:"IPAddress,omitempty"`
  185. IPPrefixLen int `json:"IPPrefixLen,omitempty" yaml:"IPPrefixLen,omitempty"`
  186. MacAddress string `json:"MacAddress,omitempty" yaml:"MacAddress,omitempty"`
  187. Gateway string `json:"Gateway,omitempty" yaml:"Gateway,omitempty"`
  188. Bridge string `json:"Bridge,omitempty" yaml:"Bridge,omitempty"`
  189. PortMapping map[string]PortMapping `json:"PortMapping,omitempty" yaml:"PortMapping,omitempty"`
  190. Ports map[Port][]PortBinding `json:"Ports,omitempty" yaml:"Ports,omitempty"`
  191. NetworkID string `json:"NetworkID,omitempty" yaml:"NetworkID,omitempty"`
  192. EndpointID string `json:"EndpointID,omitempty" yaml:"EndpointID,omitempty"`
  193. SandboxKey string `json:"SandboxKey,omitempty" yaml:"SandboxKey,omitempty"`
  194. GlobalIPv6Address string `json:"GlobalIPv6Address,omitempty" yaml:"GlobalIPv6Address,omitempty"`
  195. GlobalIPv6PrefixLen int `json:"GlobalIPv6PrefixLen,omitempty" yaml:"GlobalIPv6PrefixLen,omitempty"`
  196. IPv6Gateway string `json:"IPv6Gateway,omitempty" yaml:"IPv6Gateway,omitempty"`
  197. LinkLocalIPv6Address string `json:"LinkLocalIPv6Address,omitempty" yaml:"LinkLocalIPv6Address,omitempty"`
  198. LinkLocalIPv6PrefixLen int `json:"LinkLocalIPv6PrefixLen,omitempty" yaml:"LinkLocalIPv6PrefixLen,omitempty"`
  199. SecondaryIPAddresses []string `json:"SecondaryIPAddresses,omitempty" yaml:"SecondaryIPAddresses,omitempty"`
  200. SecondaryIPv6Addresses []string `json:"SecondaryIPv6Addresses,omitempty" yaml:"SecondaryIPv6Addresses,omitempty"`
  201. }
  202. // PortMappingAPI translates the port mappings as contained in NetworkSettings
  203. // into the format in which they would appear when returned by the API
  204. func (settings *NetworkSettings) PortMappingAPI() []APIPort {
  205. var mapping []APIPort
  206. for port, bindings := range settings.Ports {
  207. p, _ := parsePort(port.Port())
  208. if len(bindings) == 0 {
  209. mapping = append(mapping, APIPort{
  210. PrivatePort: int64(p),
  211. Type: port.Proto(),
  212. })
  213. continue
  214. }
  215. for _, binding := range bindings {
  216. p, _ := parsePort(port.Port())
  217. h, _ := parsePort(binding.HostPort)
  218. mapping = append(mapping, APIPort{
  219. PrivatePort: int64(p),
  220. PublicPort: int64(h),
  221. Type: port.Proto(),
  222. IP: binding.HostIP,
  223. })
  224. }
  225. }
  226. return mapping
  227. }
  228. func parsePort(rawPort string) (int, error) {
  229. port, err := strconv.ParseUint(rawPort, 10, 16)
  230. if err != nil {
  231. return 0, err
  232. }
  233. return int(port), nil
  234. }
  235. // Config is the list of configuration options used when creating a container.
  236. // Config does not contain the options that are specific to starting a container on a
  237. // given host. Those are contained in HostConfig
  238. type Config struct {
  239. Hostname string `json:"Hostname,omitempty" yaml:"Hostname,omitempty"`
  240. Domainname string `json:"Domainname,omitempty" yaml:"Domainname,omitempty"`
  241. User string `json:"User,omitempty" yaml:"User,omitempty"`
  242. Memory int64 `json:"Memory,omitempty" yaml:"Memory,omitempty"`
  243. MemorySwap int64 `json:"MemorySwap,omitempty" yaml:"MemorySwap,omitempty"`
  244. MemoryReservation int64 `json:"MemoryReservation,omitempty" yaml:"MemoryReservation,omitempty"`
  245. KernelMemory int64 `json:"KernelMemory,omitempty" yaml:"KernelMemory,omitempty"`
  246. PidsLimit int64 `json:"PidsLimit,omitempty" yaml:"PidsLimit,omitempty"`
  247. CPUShares int64 `json:"CpuShares,omitempty" yaml:"CpuShares,omitempty"`
  248. CPUSet string `json:"Cpuset,omitempty" yaml:"Cpuset,omitempty"`
  249. AttachStdin bool `json:"AttachStdin,omitempty" yaml:"AttachStdin,omitempty"`
  250. AttachStdout bool `json:"AttachStdout,omitempty" yaml:"AttachStdout,omitempty"`
  251. AttachStderr bool `json:"AttachStderr,omitempty" yaml:"AttachStderr,omitempty"`
  252. PortSpecs []string `json:"PortSpecs,omitempty" yaml:"PortSpecs,omitempty"`
  253. ExposedPorts map[Port]struct{} `json:"ExposedPorts,omitempty" yaml:"ExposedPorts,omitempty"`
  254. StopSignal string `json:"StopSignal,omitempty" yaml:"StopSignal,omitempty"`
  255. Tty bool `json:"Tty,omitempty" yaml:"Tty,omitempty"`
  256. OpenStdin bool `json:"OpenStdin,omitempty" yaml:"OpenStdin,omitempty"`
  257. StdinOnce bool `json:"StdinOnce,omitempty" yaml:"StdinOnce,omitempty"`
  258. Env []string `json:"Env,omitempty" yaml:"Env,omitempty"`
  259. Cmd []string `json:"Cmd" yaml:"Cmd"`
  260. DNS []string `json:"Dns,omitempty" yaml:"Dns,omitempty"` // For Docker API v1.9 and below only
  261. Image string `json:"Image,omitempty" yaml:"Image,omitempty"`
  262. Volumes map[string]struct{} `json:"Volumes,omitempty" yaml:"Volumes,omitempty"`
  263. VolumeDriver string `json:"VolumeDriver,omitempty" yaml:"VolumeDriver,omitempty"`
  264. VolumesFrom string `json:"VolumesFrom,omitempty" yaml:"VolumesFrom,omitempty"`
  265. WorkingDir string `json:"WorkingDir,omitempty" yaml:"WorkingDir,omitempty"`
  266. MacAddress string `json:"MacAddress,omitempty" yaml:"MacAddress,omitempty"`
  267. Entrypoint []string `json:"Entrypoint" yaml:"Entrypoint"`
  268. NetworkDisabled bool `json:"NetworkDisabled,omitempty" yaml:"NetworkDisabled,omitempty"`
  269. SecurityOpts []string `json:"SecurityOpts,omitempty" yaml:"SecurityOpts,omitempty"`
  270. OnBuild []string `json:"OnBuild,omitempty" yaml:"OnBuild,omitempty"`
  271. Mounts []Mount `json:"Mounts,omitempty" yaml:"Mounts,omitempty"`
  272. Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty"`
  273. }
  274. // Mount represents a mount point in the container.
  275. //
  276. // It has been added in the version 1.20 of the Docker API, available since
  277. // Docker 1.8.
  278. type Mount struct {
  279. Name string
  280. Source string
  281. Destination string
  282. Driver string
  283. Mode string
  284. RW bool
  285. }
  286. // LogConfig defines the log driver type and the configuration for it.
  287. type LogConfig struct {
  288. Type string `json:"Type,omitempty" yaml:"Type,omitempty"`
  289. Config map[string]string `json:"Config,omitempty" yaml:"Config,omitempty"`
  290. }
  291. // ULimit defines system-wide resource limitations
  292. // This can help a lot in system administration, e.g. when a user starts too many processes and therefore makes the system unresponsive for other users.
  293. type ULimit struct {
  294. Name string `json:"Name,omitempty" yaml:"Name,omitempty"`
  295. Soft int64 `json:"Soft,omitempty" yaml:"Soft,omitempty"`
  296. Hard int64 `json:"Hard,omitempty" yaml:"Hard,omitempty"`
  297. }
  298. // SwarmNode containers information about which Swarm node the container is on
  299. type SwarmNode struct {
  300. ID string `json:"ID,omitempty" yaml:"ID,omitempty"`
  301. IP string `json:"IP,omitempty" yaml:"IP,omitempty"`
  302. Addr string `json:"Addr,omitempty" yaml:"Addr,omitempty"`
  303. Name string `json:"Name,omitempty" yaml:"Name,omitempty"`
  304. CPUs int64 `json:"CPUs,omitempty" yaml:"CPUs,omitempty"`
  305. Memory int64 `json:"Memory,omitempty" yaml:"Memory,omitempty"`
  306. Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty"`
  307. }
  308. // GraphDriver contains information about the GraphDriver used by the container
  309. type GraphDriver struct {
  310. Name string `json:"Name,omitempty" yaml:"Name,omitempty"`
  311. Data map[string]string `json:"Data,omitempty" yaml:"Data,omitempty"`
  312. }
  313. // Container is the type encompasing everything about a container - its config,
  314. // hostconfig, etc.
  315. type Container struct {
  316. ID string `json:"Id" yaml:"Id"`
  317. Created time.Time `json:"Created,omitempty" yaml:"Created,omitempty"`
  318. Path string `json:"Path,omitempty" yaml:"Path,omitempty"`
  319. Args []string `json:"Args,omitempty" yaml:"Args,omitempty"`
  320. Config *Config `json:"Config,omitempty" yaml:"Config,omitempty"`
  321. State State `json:"State,omitempty" yaml:"State,omitempty"`
  322. Image string `json:"Image,omitempty" yaml:"Image,omitempty"`
  323. Node *SwarmNode `json:"Node,omitempty" yaml:"Node,omitempty"`
  324. NetworkSettings *NetworkSettings `json:"NetworkSettings,omitempty" yaml:"NetworkSettings,omitempty"`
  325. SysInitPath string `json:"SysInitPath,omitempty" yaml:"SysInitPath,omitempty"`
  326. ResolvConfPath string `json:"ResolvConfPath,omitempty" yaml:"ResolvConfPath,omitempty"`
  327. HostnamePath string `json:"HostnamePath,omitempty" yaml:"HostnamePath,omitempty"`
  328. HostsPath string `json:"HostsPath,omitempty" yaml:"HostsPath,omitempty"`
  329. LogPath string `json:"LogPath,omitempty" yaml:"LogPath,omitempty"`
  330. Name string `json:"Name,omitempty" yaml:"Name,omitempty"`
  331. Driver string `json:"Driver,omitempty" yaml:"Driver,omitempty"`
  332. Mounts []Mount `json:"Mounts,omitempty" yaml:"Mounts,omitempty"`
  333. Volumes map[string]string `json:"Volumes,omitempty" yaml:"Volumes,omitempty"`
  334. VolumesRW map[string]bool `json:"VolumesRW,omitempty" yaml:"VolumesRW,omitempty"`
  335. HostConfig *HostConfig `json:"HostConfig,omitempty" yaml:"HostConfig,omitempty"`
  336. ExecIDs []string `json:"ExecIDs,omitempty" yaml:"ExecIDs,omitempty"`
  337. GraphDriver *GraphDriver `json:"GraphDriver,omitempty" yaml:"GraphDriver,omitempty"`
  338. RestartCount int `json:"RestartCount,omitempty" yaml:"RestartCount,omitempty"`
  339. AppArmorProfile string `json:"AppArmorProfile,omitempty" yaml:"AppArmorProfile,omitempty"`
  340. }
  341. // UpdateContainerOptions specify parameters to the UpdateContainer function.
  342. //
  343. // See https://goo.gl/Y6fXUy for more details.
  344. type UpdateContainerOptions struct {
  345. BlkioWeight int `json:"BlkioWeight"`
  346. CPUShares int `json:"CpuShares"`
  347. CPUPeriod int `json:"CpuPeriod"`
  348. CPUQuota int `json:"CpuQuota"`
  349. CpusetCpus string `json:"CpusetCpus"`
  350. CpusetMems string `json:"CpusetMems"`
  351. Memory int `json:"Memory"`
  352. MemorySwap int `json:"MemorySwap"`
  353. MemoryReservation int `json:"MemoryReservation"`
  354. KernelMemory int `json:"KernelMemory"`
  355. RestartPolicy RestartPolicy `json:"RestartPolicy,omitempty"`
  356. }
  357. // UpdateContainer updates the container at ID with the options
  358. //
  359. // See https://goo.gl/Y6fXUy for more details.
  360. func (c *Client) UpdateContainer(id string, opts UpdateContainerOptions) error {
  361. resp, err := c.do("POST", fmt.Sprintf("/containers/"+id+"/update"), doOptions{data: opts, forceJSON: true})
  362. if err != nil {
  363. return err
  364. }
  365. defer resp.Body.Close()
  366. return nil
  367. }
  368. // RenameContainerOptions specify parameters to the RenameContainer function.
  369. //
  370. // See https://goo.gl/laSOIy for more details.
  371. type RenameContainerOptions struct {
  372. // ID of container to rename
  373. ID string `qs:"-"`
  374. // New name
  375. Name string `json:"name,omitempty" yaml:"name,omitempty"`
  376. }
  377. // RenameContainer updates and existing containers name
  378. //
  379. // See https://goo.gl/laSOIy for more details.
  380. func (c *Client) RenameContainer(opts RenameContainerOptions) error {
  381. resp, err := c.do("POST", fmt.Sprintf("/containers/"+opts.ID+"/rename?%s", queryString(opts)), doOptions{})
  382. if err != nil {
  383. return err
  384. }
  385. resp.Body.Close()
  386. return nil
  387. }
  388. // InspectContainer returns information about a container by its ID.
  389. //
  390. // See https://goo.gl/RdIq0b for more details.
  391. func (c *Client) InspectContainer(id string) (*Container, error) {
  392. path := "/containers/" + id + "/json"
  393. resp, err := c.do("GET", path, doOptions{})
  394. if err != nil {
  395. if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
  396. return nil, &NoSuchContainer{ID: id}
  397. }
  398. return nil, err
  399. }
  400. defer resp.Body.Close()
  401. var container Container
  402. if err := json.NewDecoder(resp.Body).Decode(&container); err != nil {
  403. return nil, err
  404. }
  405. return &container, nil
  406. }
  407. // ContainerChanges returns changes in the filesystem of the given container.
  408. //
  409. // See https://goo.gl/9GsTIF for more details.
  410. func (c *Client) ContainerChanges(id string) ([]Change, error) {
  411. path := "/containers/" + id + "/changes"
  412. resp, err := c.do("GET", path, doOptions{})
  413. if err != nil {
  414. if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
  415. return nil, &NoSuchContainer{ID: id}
  416. }
  417. return nil, err
  418. }
  419. defer resp.Body.Close()
  420. var changes []Change
  421. if err := json.NewDecoder(resp.Body).Decode(&changes); err != nil {
  422. return nil, err
  423. }
  424. return changes, nil
  425. }
  426. // CreateContainerOptions specify parameters to the CreateContainer function.
  427. //
  428. // See https://goo.gl/WxQzrr for more details.
  429. type CreateContainerOptions struct {
  430. Name string
  431. Config *Config `qs:"-"`
  432. HostConfig *HostConfig `qs:"-"`
  433. }
  434. // CreateContainer creates a new container, returning the container instance,
  435. // or an error in case of failure.
  436. //
  437. // See https://goo.gl/WxQzrr for more details.
  438. func (c *Client) CreateContainer(opts CreateContainerOptions) (*Container, error) {
  439. path := "/containers/create?" + queryString(opts)
  440. resp, err := c.do(
  441. "POST",
  442. path,
  443. doOptions{
  444. data: struct {
  445. *Config
  446. HostConfig *HostConfig `json:"HostConfig,omitempty" yaml:"HostConfig,omitempty"`
  447. }{
  448. opts.Config,
  449. opts.HostConfig,
  450. },
  451. },
  452. )
  453. if e, ok := err.(*Error); ok {
  454. if e.Status == http.StatusNotFound {
  455. return nil, ErrNoSuchImage
  456. }
  457. if e.Status == http.StatusConflict {
  458. return nil, ErrContainerAlreadyExists
  459. }
  460. }
  461. if err != nil {
  462. return nil, err
  463. }
  464. defer resp.Body.Close()
  465. var container Container
  466. if err := json.NewDecoder(resp.Body).Decode(&container); err != nil {
  467. return nil, err
  468. }
  469. container.Name = opts.Name
  470. return &container, nil
  471. }
  472. // KeyValuePair is a type for generic key/value pairs as used in the Lxc
  473. // configuration
  474. type KeyValuePair struct {
  475. Key string `json:"Key,omitempty" yaml:"Key,omitempty"`
  476. Value string `json:"Value,omitempty" yaml:"Value,omitempty"`
  477. }
  478. // RestartPolicy represents the policy for automatically restarting a container.
  479. //
  480. // Possible values are:
  481. //
  482. // - always: the docker daemon will always restart the container
  483. // - on-failure: the docker daemon will restart the container on failures, at
  484. // most MaximumRetryCount times
  485. // - no: the docker daemon will not restart the container automatically
  486. type RestartPolicy struct {
  487. Name string `json:"Name,omitempty" yaml:"Name,omitempty"`
  488. MaximumRetryCount int `json:"MaximumRetryCount,omitempty" yaml:"MaximumRetryCount,omitempty"`
  489. }
  490. // AlwaysRestart returns a restart policy that tells the Docker daemon to
  491. // always restart the container.
  492. func AlwaysRestart() RestartPolicy {
  493. return RestartPolicy{Name: "always"}
  494. }
  495. // RestartOnFailure returns a restart policy that tells the Docker daemon to
  496. // restart the container on failures, trying at most maxRetry times.
  497. func RestartOnFailure(maxRetry int) RestartPolicy {
  498. return RestartPolicy{Name: "on-failure", MaximumRetryCount: maxRetry}
  499. }
  500. // NeverRestart returns a restart policy that tells the Docker daemon to never
  501. // restart the container on failures.
  502. func NeverRestart() RestartPolicy {
  503. return RestartPolicy{Name: "no"}
  504. }
  505. // Device represents a device mapping between the Docker host and the
  506. // container.
  507. type Device struct {
  508. PathOnHost string `json:"PathOnHost,omitempty" yaml:"PathOnHost,omitempty"`
  509. PathInContainer string `json:"PathInContainer,omitempty" yaml:"PathInContainer,omitempty"`
  510. CgroupPermissions string `json:"CgroupPermissions,omitempty" yaml:"CgroupPermissions,omitempty"`
  511. }
  512. // BlockWeight represents a relative device weight for an individual device inside
  513. // of a container
  514. //
  515. // See https://goo.gl/FSdP0H for more details.
  516. type BlockWeight struct {
  517. Path string `json:"Path,omitempty"`
  518. Weight string `json:"Weight,omitempty"`
  519. }
  520. // BlockLimit represents a read/write limit in IOPS or Bandwidth for a device
  521. // inside of a container
  522. //
  523. // See https://goo.gl/FSdP0H for more details.
  524. type BlockLimit struct {
  525. Path string `json:"Path,omitempty"`
  526. Rate string `json:"Rate,omitempty"`
  527. }
  528. // HostConfig contains the container options related to starting a container on
  529. // a given host
  530. type HostConfig struct {
  531. Binds []string `json:"Binds,omitempty" yaml:"Binds,omitempty"`
  532. CapAdd []string `json:"CapAdd,omitempty" yaml:"CapAdd,omitempty"`
  533. CapDrop []string `json:"CapDrop,omitempty" yaml:"CapDrop,omitempty"`
  534. GroupAdd []string `json:"GroupAdd,omitempty" yaml:"GroupAdd,omitempty"`
  535. ContainerIDFile string `json:"ContainerIDFile,omitempty" yaml:"ContainerIDFile,omitempty"`
  536. LxcConf []KeyValuePair `json:"LxcConf,omitempty" yaml:"LxcConf,omitempty"`
  537. Privileged bool `json:"Privileged,omitempty" yaml:"Privileged,omitempty"`
  538. PortBindings map[Port][]PortBinding `json:"PortBindings,omitempty" yaml:"PortBindings,omitempty"`
  539. Links []string `json:"Links,omitempty" yaml:"Links,omitempty"`
  540. PublishAllPorts bool `json:"PublishAllPorts,omitempty" yaml:"PublishAllPorts,omitempty"`
  541. DNS []string `json:"Dns,omitempty" yaml:"Dns,omitempty"` // For Docker API v1.10 and above only
  542. DNSOptions []string `json:"DnsOptions,omitempty" yaml:"DnsOptions,omitempty"`
  543. DNSSearch []string `json:"DnsSearch,omitempty" yaml:"DnsSearch,omitempty"`
  544. ExtraHosts []string `json:"ExtraHosts,omitempty" yaml:"ExtraHosts,omitempty"`
  545. VolumesFrom []string `json:"VolumesFrom,omitempty" yaml:"VolumesFrom,omitempty"`
  546. UsernsMode string `json:"UsernsMode,omitempty" yaml:"UsernsMode,omitempty"`
  547. NetworkMode string `json:"NetworkMode,omitempty" yaml:"NetworkMode,omitempty"`
  548. IpcMode string `json:"IpcMode,omitempty" yaml:"IpcMode,omitempty"`
  549. PidMode string `json:"PidMode,omitempty" yaml:"PidMode,omitempty"`
  550. UTSMode string `json:"UTSMode,omitempty" yaml:"UTSMode,omitempty"`
  551. RestartPolicy RestartPolicy `json:"RestartPolicy,omitempty" yaml:"RestartPolicy,omitempty"`
  552. Devices []Device `json:"Devices,omitempty" yaml:"Devices,omitempty"`
  553. LogConfig LogConfig `json:"LogConfig,omitempty" yaml:"LogConfig,omitempty"`
  554. ReadonlyRootfs bool `json:"ReadonlyRootfs,omitempty" yaml:"ReadonlyRootfs,omitempty"`
  555. SecurityOpt []string `json:"SecurityOpt,omitempty" yaml:"SecurityOpt,omitempty"`
  556. CgroupParent string `json:"CgroupParent,omitempty" yaml:"CgroupParent,omitempty"`
  557. Memory int64 `json:"Memory,omitempty" yaml:"Memory,omitempty"`
  558. MemorySwap int64 `json:"MemorySwap,omitempty" yaml:"MemorySwap,omitempty"`
  559. MemorySwappiness int64 `json:"MemorySwappiness,omitempty" yaml:"MemorySwappiness,omitempty"`
  560. OOMKillDisable bool `json:"OomKillDisable,omitempty" yaml:"OomKillDisable"`
  561. CPUShares int64 `json:"CpuShares,omitempty" yaml:"CpuShares,omitempty"`
  562. CPUSet string `json:"Cpuset,omitempty" yaml:"Cpuset,omitempty"`
  563. CPUSetCPUs string `json:"CpusetCpus,omitempty" yaml:"CpusetCpus,omitempty"`
  564. CPUSetMEMs string `json:"CpusetMems,omitempty" yaml:"CpusetMems,omitempty"`
  565. CPUQuota int64 `json:"CpuQuota,omitempty" yaml:"CpuQuota,omitempty"`
  566. CPUPeriod int64 `json:"CpuPeriod,omitempty" yaml:"CpuPeriod,omitempty"`
  567. BlkioWeight int64 `json:"BlkioWeight,omitempty" yaml:"BlkioWeight"`
  568. BlkioWeightDevice []BlockWeight `json:"BlkioWeightDevice,omitempty" yaml:"BlkioWeightDevice"`
  569. BlkioDeviceReadBps []BlockLimit `json:"BlkioDeviceReadBps,omitempty" yaml:"BlkioDeviceReadBps"`
  570. BlkioDeviceReadIOps []BlockLimit `json:"BlkioDeviceReadIOps,omitempty" yaml:"BlkioDeviceReadIOps"`
  571. BlkioDeviceWriteBps []BlockLimit `json:"BlkioDeviceWriteBps,omitempty" yaml:"BlkioDeviceWriteBps"`
  572. BlkioDeviceWriteIOps []BlockLimit `json:"BlkioDeviceWriteIOps,omitempty" yaml:"BlkioDeviceWriteIOps"`
  573. Ulimits []ULimit `json:"Ulimits,omitempty" yaml:"Ulimits,omitempty"`
  574. VolumeDriver string `json:"VolumeDriver,omitempty" yaml:"VolumeDriver,omitempty"`
  575. OomScoreAdj int `json:"OomScoreAdj,omitempty" yaml:"OomScoreAdj,omitempty"`
  576. ShmSize int64 `json:"ShmSize,omitempty" yaml:"ShmSize,omitempty"`
  577. }
  578. // StartContainer starts a container, returning an error in case of failure.
  579. //
  580. // See https://goo.gl/MrBAJv for more details.
  581. func (c *Client) StartContainer(id string, hostConfig *HostConfig) error {
  582. path := "/containers/" + id + "/start"
  583. resp, err := c.do("POST", path, doOptions{data: hostConfig, forceJSON: true})
  584. if err != nil {
  585. if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
  586. return &NoSuchContainer{ID: id, Err: err}
  587. }
  588. return err
  589. }
  590. if resp.StatusCode == http.StatusNotModified {
  591. return &ContainerAlreadyRunning{ID: id}
  592. }
  593. resp.Body.Close()
  594. return nil
  595. }
  596. // StopContainer stops a container, killing it after the given timeout (in
  597. // seconds).
  598. //
  599. // See https://goo.gl/USqsFt for more details.
  600. func (c *Client) StopContainer(id string, timeout uint) error {
  601. path := fmt.Sprintf("/containers/%s/stop?t=%d", id, timeout)
  602. resp, err := c.do("POST", path, doOptions{})
  603. if err != nil {
  604. if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
  605. return &NoSuchContainer{ID: id}
  606. }
  607. return err
  608. }
  609. if resp.StatusCode == http.StatusNotModified {
  610. return &ContainerNotRunning{ID: id}
  611. }
  612. resp.Body.Close()
  613. return nil
  614. }
  615. // RestartContainer stops a container, killing it after the given timeout (in
  616. // seconds), during the stop process.
  617. //
  618. // See https://goo.gl/QzsDnz for more details.
  619. func (c *Client) RestartContainer(id string, timeout uint) error {
  620. path := fmt.Sprintf("/containers/%s/restart?t=%d", id, timeout)
  621. resp, err := c.do("POST", path, doOptions{})
  622. if err != nil {
  623. if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
  624. return &NoSuchContainer{ID: id}
  625. }
  626. return err
  627. }
  628. resp.Body.Close()
  629. return nil
  630. }
  631. // PauseContainer pauses the given container.
  632. //
  633. // See https://goo.gl/OF7W9X for more details.
  634. func (c *Client) PauseContainer(id string) error {
  635. path := fmt.Sprintf("/containers/%s/pause", id)
  636. resp, err := c.do("POST", path, doOptions{})
  637. if err != nil {
  638. if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
  639. return &NoSuchContainer{ID: id}
  640. }
  641. return err
  642. }
  643. resp.Body.Close()
  644. return nil
  645. }
  646. // UnpauseContainer unpauses the given container.
  647. //
  648. // See https://goo.gl/7dwyPA for more details.
  649. func (c *Client) UnpauseContainer(id string) error {
  650. path := fmt.Sprintf("/containers/%s/unpause", id)
  651. resp, err := c.do("POST", path, doOptions{})
  652. if err != nil {
  653. if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
  654. return &NoSuchContainer{ID: id}
  655. }
  656. return err
  657. }
  658. resp.Body.Close()
  659. return nil
  660. }
  661. // TopResult represents the list of processes running in a container, as
  662. // returned by /containers/<id>/top.
  663. //
  664. // See https://goo.gl/Rb46aY for more details.
  665. type TopResult struct {
  666. Titles []string
  667. Processes [][]string
  668. }
  669. // TopContainer returns processes running inside a container
  670. //
  671. // See https://goo.gl/Rb46aY for more details.
  672. func (c *Client) TopContainer(id string, psArgs string) (TopResult, error) {
  673. var args string
  674. var result TopResult
  675. if psArgs != "" {
  676. args = fmt.Sprintf("?ps_args=%s", psArgs)
  677. }
  678. path := fmt.Sprintf("/containers/%s/top%s", id, args)
  679. resp, err := c.do("GET", path, doOptions{})
  680. if err != nil {
  681. if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
  682. return result, &NoSuchContainer{ID: id}
  683. }
  684. return result, err
  685. }
  686. defer resp.Body.Close()
  687. if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
  688. return result, err
  689. }
  690. return result, nil
  691. }
  692. // Stats represents container statistics, returned by /containers/<id>/stats.
  693. //
  694. // See https://goo.gl/GNmLHb for more details.
  695. type Stats struct {
  696. Read time.Time `json:"read,omitempty" yaml:"read,omitempty"`
  697. PidsStats struct {
  698. Current uint64 `json:"current,omitempty" yaml:"current,omitempty"`
  699. } `json:"pids_stats,omitempty" yaml:"pids_stats,omitempty"`
  700. Network NetworkStats `json:"network,omitempty" yaml:"network,omitempty"`
  701. Networks map[string]NetworkStats `json:"networks,omitempty" yaml:"networks,omitempty"`
  702. MemoryStats struct {
  703. Stats struct {
  704. TotalPgmafault uint64 `json:"total_pgmafault,omitempty" yaml:"total_pgmafault,omitempty"`
  705. Cache uint64 `json:"cache,omitempty" yaml:"cache,omitempty"`
  706. MappedFile uint64 `json:"mapped_file,omitempty" yaml:"mapped_file,omitempty"`
  707. TotalInactiveFile uint64 `json:"total_inactive_file,omitempty" yaml:"total_inactive_file,omitempty"`
  708. Pgpgout uint64 `json:"pgpgout,omitempty" yaml:"pgpgout,omitempty"`
  709. Rss uint64 `json:"rss,omitempty" yaml:"rss,omitempty"`
  710. TotalMappedFile uint64 `json:"total_mapped_file,omitempty" yaml:"total_mapped_file,omitempty"`
  711. Writeback uint64 `json:"writeback,omitempty" yaml:"writeback,omitempty"`
  712. Unevictable uint64 `json:"unevictable,omitempty" yaml:"unevictable,omitempty"`
  713. Pgpgin uint64 `json:"pgpgin,omitempty" yaml:"pgpgin,omitempty"`
  714. TotalUnevictable uint64 `json:"total_unevictable,omitempty" yaml:"total_unevictable,omitempty"`
  715. Pgmajfault uint64 `json:"pgmajfault,omitempty" yaml:"pgmajfault,omitempty"`
  716. TotalRss uint64 `json:"total_rss,omitempty" yaml:"total_rss,omitempty"`
  717. TotalRssHuge uint64 `json:"total_rss_huge,omitempty" yaml:"total_rss_huge,omitempty"`
  718. TotalWriteback uint64 `json:"total_writeback,omitempty" yaml:"total_writeback,omitempty"`
  719. TotalInactiveAnon uint64 `json:"total_inactive_anon,omitempty" yaml:"total_inactive_anon,omitempty"`
  720. RssHuge uint64 `json:"rss_huge,omitempty" yaml:"rss_huge,omitempty"`
  721. HierarchicalMemoryLimit uint64 `json:"hierarchical_memory_limit,omitempty" yaml:"hierarchical_memory_limit,omitempty"`
  722. TotalPgfault uint64 `json:"total_pgfault,omitempty" yaml:"total_pgfault,omitempty"`
  723. TotalActiveFile uint64 `json:"total_active_file,omitempty" yaml:"total_active_file,omitempty"`
  724. ActiveAnon uint64 `json:"active_anon,omitempty" yaml:"active_anon,omitempty"`
  725. TotalActiveAnon uint64 `json:"total_active_anon,omitempty" yaml:"total_active_anon,omitempty"`
  726. TotalPgpgout uint64 `json:"total_pgpgout,omitempty" yaml:"total_pgpgout,omitempty"`
  727. TotalCache uint64 `json:"total_cache,omitempty" yaml:"total_cache,omitempty"`
  728. InactiveAnon uint64 `json:"inactive_anon,omitempty" yaml:"inactive_anon,omitempty"`
  729. ActiveFile uint64 `json:"active_file,omitempty" yaml:"active_file,omitempty"`
  730. Pgfault uint64 `json:"pgfault,omitempty" yaml:"pgfault,omitempty"`
  731. InactiveFile uint64 `json:"inactive_file,omitempty" yaml:"inactive_file,omitempty"`
  732. TotalPgpgin uint64 `json:"total_pgpgin,omitempty" yaml:"total_pgpgin,omitempty"`
  733. HierarchicalMemswLimit uint64 `json:"hierarchical_memsw_limit,omitempty" yaml:"hierarchical_memsw_limit,omitempty"`
  734. Swap uint64 `json:"swap,omitempty" yaml:"swap,omitempty"`
  735. } `json:"stats,omitempty" yaml:"stats,omitempty"`
  736. MaxUsage uint64 `json:"max_usage,omitempty" yaml:"max_usage,omitempty"`
  737. Usage uint64 `json:"usage,omitempty" yaml:"usage,omitempty"`
  738. Failcnt uint64 `json:"failcnt,omitempty" yaml:"failcnt,omitempty"`
  739. Limit uint64 `json:"limit,omitempty" yaml:"limit,omitempty"`
  740. } `json:"memory_stats,omitempty" yaml:"memory_stats,omitempty"`
  741. BlkioStats struct {
  742. IOServiceBytesRecursive []BlkioStatsEntry `json:"io_service_bytes_recursive,omitempty" yaml:"io_service_bytes_recursive,omitempty"`
  743. IOServicedRecursive []BlkioStatsEntry `json:"io_serviced_recursive,omitempty" yaml:"io_serviced_recursive,omitempty"`
  744. IOQueueRecursive []BlkioStatsEntry `json:"io_queue_recursive,omitempty" yaml:"io_queue_recursive,omitempty"`
  745. IOServiceTimeRecursive []BlkioStatsEntry `json:"io_service_time_recursive,omitempty" yaml:"io_service_time_recursive,omitempty"`
  746. IOWaitTimeRecursive []BlkioStatsEntry `json:"io_wait_time_recursive,omitempty" yaml:"io_wait_time_recursive,omitempty"`
  747. IOMergedRecursive []BlkioStatsEntry `json:"io_merged_recursive,omitempty" yaml:"io_merged_recursive,omitempty"`
  748. IOTimeRecursive []BlkioStatsEntry `json:"io_time_recursive,omitempty" yaml:"io_time_recursive,omitempty"`
  749. SectorsRecursive []BlkioStatsEntry `json:"sectors_recursive,omitempty" yaml:"sectors_recursive,omitempty"`
  750. } `json:"blkio_stats,omitempty" yaml:"blkio_stats,omitempty"`
  751. CPUStats CPUStats `json:"cpu_stats,omitempty" yaml:"cpu_stats,omitempty"`
  752. PreCPUStats CPUStats `json:"precpu_stats,omitempty"`
  753. }
  754. // NetworkStats is a stats entry for network stats
  755. type NetworkStats struct {
  756. RxDropped uint64 `json:"rx_dropped,omitempty" yaml:"rx_dropped,omitempty"`
  757. RxBytes uint64 `json:"rx_bytes,omitempty" yaml:"rx_bytes,omitempty"`
  758. RxErrors uint64 `json:"rx_errors,omitempty" yaml:"rx_errors,omitempty"`
  759. TxPackets uint64 `json:"tx_packets,omitempty" yaml:"tx_packets,omitempty"`
  760. TxDropped uint64 `json:"tx_dropped,omitempty" yaml:"tx_dropped,omitempty"`
  761. RxPackets uint64 `json:"rx_packets,omitempty" yaml:"rx_packets,omitempty"`
  762. TxErrors uint64 `json:"tx_errors,omitempty" yaml:"tx_errors,omitempty"`
  763. TxBytes uint64 `json:"tx_bytes,omitempty" yaml:"tx_bytes,omitempty"`
  764. }
  765. // CPUStats is a stats entry for cpu stats
  766. type CPUStats struct {
  767. CPUUsage struct {
  768. PercpuUsage []uint64 `json:"percpu_usage,omitempty" yaml:"percpu_usage,omitempty"`
  769. UsageInUsermode uint64 `json:"usage_in_usermode,omitempty" yaml:"usage_in_usermode,omitempty"`
  770. TotalUsage uint64 `json:"total_usage,omitempty" yaml:"total_usage,omitempty"`
  771. UsageInKernelmode uint64 `json:"usage_in_kernelmode,omitempty" yaml:"usage_in_kernelmode,omitempty"`
  772. } `json:"cpu_usage,omitempty" yaml:"cpu_usage,omitempty"`
  773. SystemCPUUsage uint64 `json:"system_cpu_usage,omitempty" yaml:"system_cpu_usage,omitempty"`
  774. ThrottlingData struct {
  775. Periods uint64 `json:"periods,omitempty"`
  776. ThrottledPeriods uint64 `json:"throttled_periods,omitempty"`
  777. ThrottledTime uint64 `json:"throttled_time,omitempty"`
  778. } `json:"throttling_data,omitempty" yaml:"throttling_data,omitempty"`
  779. }
  780. // BlkioStatsEntry is a stats entry for blkio_stats
  781. type BlkioStatsEntry struct {
  782. Major uint64 `json:"major,omitempty" yaml:"major,omitempty"`
  783. Minor uint64 `json:"minor,omitempty" yaml:"minor,omitempty"`
  784. Op string `json:"op,omitempty" yaml:"op,omitempty"`
  785. Value uint64 `json:"value,omitempty" yaml:"value,omitempty"`
  786. }
  787. // StatsOptions specify parameters to the Stats function.
  788. //
  789. // See https://goo.gl/GNmLHb for more details.
  790. type StatsOptions struct {
  791. ID string
  792. Stats chan<- *Stats
  793. Stream bool
  794. // A flag that enables stopping the stats operation
  795. Done <-chan bool
  796. // Initial connection timeout
  797. Timeout time.Duration
  798. // Timeout with no data is received, it's reset every time new data
  799. // arrives
  800. InactivityTimeout time.Duration `qs:"-"`
  801. }
  802. // Stats sends container statistics for the given container to the given channel.
  803. //
  804. // This function is blocking, similar to a streaming call for logs, and should be run
  805. // on a separate goroutine from the caller. Note that this function will block until
  806. // the given container is removed, not just exited. When finished, this function
  807. // will close the given channel. Alternatively, function can be stopped by
  808. // signaling on the Done channel.
  809. //
  810. // See https://goo.gl/GNmLHb for more details.
  811. func (c *Client) Stats(opts StatsOptions) (retErr error) {
  812. errC := make(chan error, 1)
  813. readCloser, writeCloser := io.Pipe()
  814. defer func() {
  815. close(opts.Stats)
  816. select {
  817. case err := <-errC:
  818. if err != nil && retErr == nil {
  819. retErr = err
  820. }
  821. default:
  822. // No errors
  823. }
  824. if err := readCloser.Close(); err != nil && retErr == nil {
  825. retErr = err
  826. }
  827. }()
  828. go func() {
  829. err := c.stream("GET", fmt.Sprintf("/containers/%s/stats?stream=%v", opts.ID, opts.Stream), streamOptions{
  830. rawJSONStream: true,
  831. useJSONDecoder: true,
  832. stdout: writeCloser,
  833. timeout: opts.Timeout,
  834. inactivityTimeout: opts.InactivityTimeout,
  835. })
  836. if err != nil {
  837. dockerError, ok := err.(*Error)
  838. if ok {
  839. if dockerError.Status == http.StatusNotFound {
  840. err = &NoSuchContainer{ID: opts.ID}
  841. }
  842. }
  843. }
  844. if closeErr := writeCloser.Close(); closeErr != nil && err == nil {
  845. err = closeErr
  846. }
  847. errC <- err
  848. close(errC)
  849. }()
  850. quit := make(chan struct{})
  851. defer close(quit)
  852. go func() {
  853. // block here waiting for the signal to stop function
  854. select {
  855. case <-opts.Done:
  856. readCloser.Close()
  857. case <-quit:
  858. return
  859. }
  860. }()
  861. decoder := json.NewDecoder(readCloser)
  862. stats := new(Stats)
  863. for err := decoder.Decode(stats); err != io.EOF; err = decoder.Decode(stats) {
  864. if err != nil {
  865. return err
  866. }
  867. opts.Stats <- stats
  868. stats = new(Stats)
  869. }
  870. return nil
  871. }
  872. // KillContainerOptions represents the set of options that can be used in a
  873. // call to KillContainer.
  874. //
  875. // See https://goo.gl/hkS9i8 for more details.
  876. type KillContainerOptions struct {
  877. // The ID of the container.
  878. ID string `qs:"-"`
  879. // The signal to send to the container. When omitted, Docker server
  880. // will assume SIGKILL.
  881. Signal Signal
  882. }
  883. // KillContainer sends a signal to a container, returning an error in case of
  884. // failure.
  885. //
  886. // See https://goo.gl/hkS9i8 for more details.
  887. func (c *Client) KillContainer(opts KillContainerOptions) error {
  888. path := "/containers/" + opts.ID + "/kill" + "?" + queryString(opts)
  889. resp, err := c.do("POST", path, doOptions{})
  890. if err != nil {
  891. if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
  892. return &NoSuchContainer{ID: opts.ID}
  893. }
  894. return err
  895. }
  896. resp.Body.Close()
  897. return nil
  898. }
  899. // RemoveContainerOptions encapsulates options to remove a container.
  900. //
  901. // See https://goo.gl/RQyX62 for more details.
  902. type RemoveContainerOptions struct {
  903. // The ID of the container.
  904. ID string `qs:"-"`
  905. // A flag that indicates whether Docker should remove the volumes
  906. // associated to the container.
  907. RemoveVolumes bool `qs:"v"`
  908. // A flag that indicates whether Docker should remove the container
  909. // even if it is currently running.
  910. Force bool
  911. }
  912. // RemoveContainer removes a container, returning an error in case of failure.
  913. //
  914. // See https://goo.gl/RQyX62 for more details.
  915. func (c *Client) RemoveContainer(opts RemoveContainerOptions) error {
  916. path := "/containers/" + opts.ID + "?" + queryString(opts)
  917. resp, err := c.do("DELETE", path, doOptions{})
  918. if err != nil {
  919. if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
  920. return &NoSuchContainer{ID: opts.ID}
  921. }
  922. return err
  923. }
  924. resp.Body.Close()
  925. return nil
  926. }
  927. // UploadToContainerOptions is the set of options that can be used when
  928. // uploading an archive into a container.
  929. //
  930. // See https://goo.gl/Ss97HW for more details.
  931. type UploadToContainerOptions struct {
  932. InputStream io.Reader `json:"-" qs:"-"`
  933. Path string `qs:"path"`
  934. NoOverwriteDirNonDir bool `qs:"noOverwriteDirNonDir"`
  935. }
  936. // UploadToContainer uploads a tar archive to be extracted to a path in the
  937. // filesystem of the container.
  938. //
  939. // See https://goo.gl/Ss97HW for more details.
  940. func (c *Client) UploadToContainer(id string, opts UploadToContainerOptions) error {
  941. url := fmt.Sprintf("/containers/%s/archive?", id) + queryString(opts)
  942. return c.stream("PUT", url, streamOptions{
  943. in: opts.InputStream,
  944. })
  945. }
  946. // DownloadFromContainerOptions is the set of options that can be used when
  947. // downloading resources from a container.
  948. //
  949. // See https://goo.gl/KnZJDX for more details.
  950. type DownloadFromContainerOptions struct {
  951. OutputStream io.Writer `json:"-" qs:"-"`
  952. Path string `qs:"path"`
  953. InactivityTimeout time.Duration `qs:"-"`
  954. }
  955. // DownloadFromContainer downloads a tar archive of files or folders in a container.
  956. //
  957. // See https://goo.gl/KnZJDX for more details.
  958. func (c *Client) DownloadFromContainer(id string, opts DownloadFromContainerOptions) error {
  959. url := fmt.Sprintf("/containers/%s/archive?", id) + queryString(opts)
  960. return c.stream("GET", url, streamOptions{
  961. setRawTerminal: true,
  962. stdout: opts.OutputStream,
  963. inactivityTimeout: opts.InactivityTimeout,
  964. })
  965. }
  966. // CopyFromContainerOptions has been DEPRECATED, please use DownloadFromContainerOptions along with DownloadFromContainer.
  967. //
  968. // See https://goo.gl/R2jevW for more details.
  969. type CopyFromContainerOptions struct {
  970. OutputStream io.Writer `json:"-"`
  971. Container string `json:"-"`
  972. Resource string
  973. }
  974. // CopyFromContainer has been DEPRECATED, please use DownloadFromContainerOptions along with DownloadFromContainer.
  975. //
  976. // See https://goo.gl/R2jevW for more details.
  977. func (c *Client) CopyFromContainer(opts CopyFromContainerOptions) error {
  978. if opts.Container == "" {
  979. return &NoSuchContainer{ID: opts.Container}
  980. }
  981. url := fmt.Sprintf("/containers/%s/copy", opts.Container)
  982. resp, err := c.do("POST", url, doOptions{data: opts})
  983. if err != nil {
  984. if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
  985. return &NoSuchContainer{ID: opts.Container}
  986. }
  987. return err
  988. }
  989. defer resp.Body.Close()
  990. _, err = io.Copy(opts.OutputStream, resp.Body)
  991. return err
  992. }
  993. // WaitContainer blocks until the given container stops, return the exit code
  994. // of the container status.
  995. //
  996. // See https://goo.gl/Gc1rge for more details.
  997. func (c *Client) WaitContainer(id string) (int, error) {
  998. resp, err := c.do("POST", "/containers/"+id+"/wait", doOptions{})
  999. if err != nil {
  1000. if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
  1001. return 0, &NoSuchContainer{ID: id}
  1002. }
  1003. return 0, err
  1004. }
  1005. defer resp.Body.Close()
  1006. var r struct{ StatusCode int }
  1007. if err := json.NewDecoder(resp.Body).Decode(&r); err != nil {
  1008. return 0, err
  1009. }
  1010. return r.StatusCode, nil
  1011. }
  1012. // CommitContainerOptions aggregates parameters to the CommitContainer method.
  1013. //
  1014. // See https://goo.gl/mqfoCw for more details.
  1015. type CommitContainerOptions struct {
  1016. Container string
  1017. Repository string `qs:"repo"`
  1018. Tag string
  1019. Message string `qs:"comment"`
  1020. Author string
  1021. Run *Config `qs:"-"`
  1022. }
  1023. // CommitContainer creates a new image from a container's changes.
  1024. //
  1025. // See https://goo.gl/mqfoCw for more details.
  1026. func (c *Client) CommitContainer(opts CommitContainerOptions) (*Image, error) {
  1027. path := "/commit?" + queryString(opts)
  1028. resp, err := c.do("POST", path, doOptions{data: opts.Run})
  1029. if err != nil {
  1030. if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
  1031. return nil, &NoSuchContainer{ID: opts.Container}
  1032. }
  1033. return nil, err
  1034. }
  1035. defer resp.Body.Close()
  1036. var image Image
  1037. if err := json.NewDecoder(resp.Body).Decode(&image); err != nil {
  1038. return nil, err
  1039. }
  1040. return &image, nil
  1041. }
  1042. // AttachToContainerOptions is the set of options that can be used when
  1043. // attaching to a container.
  1044. //
  1045. // See https://goo.gl/NKpkFk for more details.
  1046. type AttachToContainerOptions struct {
  1047. Container string `qs:"-"`
  1048. InputStream io.Reader `qs:"-"`
  1049. OutputStream io.Writer `qs:"-"`
  1050. ErrorStream io.Writer `qs:"-"`
  1051. // Get container logs, sending it to OutputStream.
  1052. Logs bool
  1053. // Stream the response?
  1054. Stream bool
  1055. // Attach to stdin, and use InputStream.
  1056. Stdin bool
  1057. // Attach to stdout, and use OutputStream.
  1058. Stdout bool
  1059. // Attach to stderr, and use ErrorStream.
  1060. Stderr bool
  1061. // If set, after a successful connect, a sentinel will be sent and then the
  1062. // client will block on receive before continuing.
  1063. //
  1064. // It must be an unbuffered channel. Using a buffered channel can lead
  1065. // to unexpected behavior.
  1066. Success chan struct{}
  1067. // Use raw terminal? Usually true when the container contains a TTY.
  1068. RawTerminal bool `qs:"-"`
  1069. }
  1070. // AttachToContainer attaches to a container, using the given options.
  1071. //
  1072. // See https://goo.gl/NKpkFk for more details.
  1073. func (c *Client) AttachToContainer(opts AttachToContainerOptions) error {
  1074. cw, err := c.AttachToContainerNonBlocking(opts)
  1075. if err != nil {
  1076. return err
  1077. }
  1078. return cw.Wait()
  1079. }
  1080. // AttachToContainerNonBlocking attaches to a container, using the given options.
  1081. // This function does not block.
  1082. //
  1083. // See https://goo.gl/NKpkFk for more details.
  1084. func (c *Client) AttachToContainerNonBlocking(opts AttachToContainerOptions) (CloseWaiter, error) {
  1085. if opts.Container == "" {
  1086. return nil, &NoSuchContainer{ID: opts.Container}
  1087. }
  1088. path := "/containers/" + opts.Container + "/attach?" + queryString(opts)
  1089. return c.hijack("POST", path, hijackOptions{
  1090. success: opts.Success,
  1091. setRawTerminal: opts.RawTerminal,
  1092. in: opts.InputStream,
  1093. stdout: opts.OutputStream,
  1094. stderr: opts.ErrorStream,
  1095. })
  1096. }
  1097. // LogsOptions represents the set of options used when getting logs from a
  1098. // container.
  1099. //
  1100. // See https://goo.gl/yl8PGm for more details.
  1101. type LogsOptions struct {
  1102. Container string `qs:"-"`
  1103. OutputStream io.Writer `qs:"-"`
  1104. ErrorStream io.Writer `qs:"-"`
  1105. InactivityTimeout time.Duration `qs:"-"`
  1106. Follow bool
  1107. Stdout bool
  1108. Stderr bool
  1109. Since int64
  1110. Timestamps bool
  1111. Tail string
  1112. // Use raw terminal? Usually true when the container contains a TTY.
  1113. RawTerminal bool `qs:"-"`
  1114. }
  1115. // Logs gets stdout and stderr logs from the specified container.
  1116. //
  1117. // See https://goo.gl/yl8PGm for more details.
  1118. func (c *Client) Logs(opts LogsOptions) error {
  1119. if opts.Container == "" {
  1120. return &NoSuchContainer{ID: opts.Container}
  1121. }
  1122. if opts.Tail == "" {
  1123. opts.Tail = "all"
  1124. }
  1125. path := "/containers/" + opts.Container + "/logs?" + queryString(opts)
  1126. return c.stream("GET", path, streamOptions{
  1127. setRawTerminal: opts.RawTerminal,
  1128. stdout: opts.OutputStream,
  1129. stderr: opts.ErrorStream,
  1130. inactivityTimeout: opts.InactivityTimeout,
  1131. })
  1132. }
  1133. // ResizeContainerTTY resizes the terminal to the given height and width.
  1134. //
  1135. // See https://goo.gl/xERhCc for more details.
  1136. func (c *Client) ResizeContainerTTY(id string, height, width int) error {
  1137. params := make(url.Values)
  1138. params.Set("h", strconv.Itoa(height))
  1139. params.Set("w", strconv.Itoa(width))
  1140. resp, err := c.do("POST", "/containers/"+id+"/resize?"+params.Encode(), doOptions{})
  1141. if err != nil {
  1142. return err
  1143. }
  1144. resp.Body.Close()
  1145. return nil
  1146. }
  1147. // ExportContainerOptions is the set of parameters to the ExportContainer
  1148. // method.
  1149. //
  1150. // See https://goo.gl/dOkTyk for more details.
  1151. type ExportContainerOptions struct {
  1152. ID string
  1153. OutputStream io.Writer
  1154. InactivityTimeout time.Duration `qs:"-"`
  1155. }
  1156. // ExportContainer export the contents of container id as tar archive
  1157. // and prints the exported contents to stdout.
  1158. //
  1159. // See https://goo.gl/dOkTyk for more details.
  1160. func (c *Client) ExportContainer(opts ExportContainerOptions) error {
  1161. if opts.ID == "" {
  1162. return &NoSuchContainer{ID: opts.ID}
  1163. }
  1164. url := fmt.Sprintf("/containers/%s/export", opts.ID)
  1165. return c.stream("GET", url, streamOptions{
  1166. setRawTerminal: true,
  1167. stdout: opts.OutputStream,
  1168. inactivityTimeout: opts.InactivityTimeout,
  1169. })
  1170. }
  1171. // NoSuchContainer is the error returned when a given container does not exist.
  1172. type NoSuchContainer struct {
  1173. ID string
  1174. Err error
  1175. }
  1176. func (err *NoSuchContainer) Error() string {
  1177. if err.Err != nil {
  1178. return err.Err.Error()
  1179. }
  1180. return "No such container: " + err.ID
  1181. }
  1182. // ContainerAlreadyRunning is the error returned when a given container is
  1183. // already running.
  1184. type ContainerAlreadyRunning struct {
  1185. ID string
  1186. }
  1187. func (err *ContainerAlreadyRunning) Error() string {
  1188. return "Container already running: " + err.ID
  1189. }
  1190. // ContainerNotRunning is the error returned when a given container is not
  1191. // running.
  1192. type ContainerNotRunning struct {
  1193. ID string
  1194. }
  1195. func (err *ContainerNotRunning) Error() string {
  1196. return "Container not running: " + err.ID
  1197. }