container.go 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415
  1. package daemon
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "io/ioutil"
  9. "os"
  10. "path"
  11. "path/filepath"
  12. "strings"
  13. "syscall"
  14. "time"
  15. "github.com/docker/libcontainer/devices"
  16. "github.com/docker/libcontainer/label"
  17. log "github.com/Sirupsen/logrus"
  18. "github.com/docker/docker/daemon/execdriver"
  19. "github.com/docker/docker/engine"
  20. "github.com/docker/docker/image"
  21. "github.com/docker/docker/links"
  22. "github.com/docker/docker/nat"
  23. "github.com/docker/docker/pkg/archive"
  24. "github.com/docker/docker/pkg/broadcastwriter"
  25. "github.com/docker/docker/pkg/ioutils"
  26. "github.com/docker/docker/pkg/networkfs/etchosts"
  27. "github.com/docker/docker/pkg/networkfs/resolvconf"
  28. "github.com/docker/docker/pkg/promise"
  29. "github.com/docker/docker/pkg/symlink"
  30. "github.com/docker/docker/runconfig"
  31. "github.com/docker/docker/utils"
  32. )
  33. const DefaultPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
  34. var (
  35. ErrNotATTY = errors.New("The PTY is not a file")
  36. ErrNoTTY = errors.New("No PTY found")
  37. ErrContainerStart = errors.New("The container failed to start. Unknown error")
  38. ErrContainerStartTimeout = errors.New("The container failed to start due to timed out.")
  39. )
  40. type StreamConfig struct {
  41. stdout *broadcastwriter.BroadcastWriter
  42. stderr *broadcastwriter.BroadcastWriter
  43. stdin io.ReadCloser
  44. stdinPipe io.WriteCloser
  45. }
  46. type Container struct {
  47. *State `json:"State"` // Needed for remote api version <= 1.11
  48. root string // Path to the "home" of the container, including metadata.
  49. basefs string // Path to the graphdriver mountpoint
  50. ID string
  51. Created time.Time
  52. Path string
  53. Args []string
  54. Config *runconfig.Config
  55. ImageID string `json:"Image"`
  56. NetworkSettings *NetworkSettings
  57. ResolvConfPath string
  58. HostnamePath string
  59. HostsPath string
  60. Name string
  61. Driver string
  62. ExecDriver string
  63. command *execdriver.Command
  64. StreamConfig
  65. daemon *Daemon
  66. MountLabel, ProcessLabel string
  67. AppArmorProfile string
  68. RestartCount int
  69. UpdateDns bool
  70. // Maps container paths to volume paths. The key in this is the path to which
  71. // the volume is being mounted inside the container. Value is the path of the
  72. // volume on disk
  73. Volumes map[string]string
  74. // Store rw/ro in a separate structure to preserve reverse-compatibility on-disk.
  75. // Easier than migrating older container configs :)
  76. VolumesRW map[string]bool
  77. hostConfig *runconfig.HostConfig
  78. activeLinks map[string]*links.Link
  79. monitor *containerMonitor
  80. execCommands *execStore
  81. }
  82. func (container *Container) FromDisk() error {
  83. pth, err := container.jsonPath()
  84. if err != nil {
  85. return err
  86. }
  87. jsonSource, err := os.Open(pth)
  88. if err != nil {
  89. return err
  90. }
  91. defer jsonSource.Close()
  92. dec := json.NewDecoder(jsonSource)
  93. // Load container settings
  94. // udp broke compat of docker.PortMapping, but it's not used when loading a container, we can skip it
  95. if err := dec.Decode(container); err != nil && !strings.Contains(err.Error(), "docker.PortMapping") {
  96. return err
  97. }
  98. if err := label.ReserveLabel(container.ProcessLabel); err != nil {
  99. return err
  100. }
  101. return container.readHostConfig()
  102. }
  103. func (container *Container) toDisk() error {
  104. data, err := json.Marshal(container)
  105. if err != nil {
  106. return err
  107. }
  108. pth, err := container.jsonPath()
  109. if err != nil {
  110. return err
  111. }
  112. err = ioutil.WriteFile(pth, data, 0666)
  113. if err != nil {
  114. return err
  115. }
  116. return container.WriteHostConfig()
  117. }
  118. func (container *Container) ToDisk() error {
  119. container.Lock()
  120. err := container.toDisk()
  121. container.Unlock()
  122. return err
  123. }
  124. func (container *Container) readHostConfig() error {
  125. container.hostConfig = &runconfig.HostConfig{}
  126. // If the hostconfig file does not exist, do not read it.
  127. // (We still have to initialize container.hostConfig,
  128. // but that's OK, since we just did that above.)
  129. pth, err := container.hostConfigPath()
  130. if err != nil {
  131. return err
  132. }
  133. _, err = os.Stat(pth)
  134. if os.IsNotExist(err) {
  135. return nil
  136. }
  137. data, err := ioutil.ReadFile(pth)
  138. if err != nil {
  139. return err
  140. }
  141. return json.Unmarshal(data, container.hostConfig)
  142. }
  143. func (container *Container) WriteHostConfig() error {
  144. data, err := json.Marshal(container.hostConfig)
  145. if err != nil {
  146. return err
  147. }
  148. pth, err := container.hostConfigPath()
  149. if err != nil {
  150. return err
  151. }
  152. return ioutil.WriteFile(pth, data, 0666)
  153. }
  154. func (container *Container) LogEvent(action string) {
  155. d := container.daemon
  156. if err := d.eng.Job("log", action, container.ID, d.Repositories().ImageName(container.ImageID)).Run(); err != nil {
  157. log.Errorf("Error logging event %s for %s: %s", action, container.ID, err)
  158. }
  159. }
  160. func (container *Container) getResourcePath(path string) (string, error) {
  161. cleanPath := filepath.Join("/", path)
  162. return symlink.FollowSymlinkInScope(filepath.Join(container.basefs, cleanPath), container.basefs)
  163. }
  164. func (container *Container) getRootResourcePath(path string) (string, error) {
  165. cleanPath := filepath.Join("/", path)
  166. return symlink.FollowSymlinkInScope(filepath.Join(container.root, cleanPath), container.root)
  167. }
  168. func populateCommand(c *Container, env []string) error {
  169. en := &execdriver.Network{
  170. Mtu: c.daemon.config.Mtu,
  171. Interface: nil,
  172. }
  173. parts := strings.SplitN(string(c.hostConfig.NetworkMode), ":", 2)
  174. switch parts[0] {
  175. case "none":
  176. case "host":
  177. en.HostNetworking = true
  178. case "bridge", "": // empty string to support existing containers
  179. if !c.Config.NetworkDisabled {
  180. network := c.NetworkSettings
  181. en.Interface = &execdriver.NetworkInterface{
  182. Gateway: network.Gateway,
  183. Bridge: network.Bridge,
  184. IPAddress: network.IPAddress,
  185. IPPrefixLen: network.IPPrefixLen,
  186. MacAddress: network.MacAddress,
  187. LinkLocalIPv6Address: network.LinkLocalIPv6Address,
  188. GlobalIPv6Address: network.GlobalIPv6Address,
  189. GlobalIPv6PrefixLen: network.GlobalIPv6PrefixLen,
  190. IPv6Gateway: network.IPv6Gateway,
  191. }
  192. }
  193. case "container":
  194. nc, err := c.getNetworkedContainer()
  195. if err != nil {
  196. return err
  197. }
  198. en.ContainerID = nc.ID
  199. default:
  200. return fmt.Errorf("invalid network mode: %s", c.hostConfig.NetworkMode)
  201. }
  202. ipc := &execdriver.Ipc{}
  203. if c.hostConfig.IpcMode.IsContainer() {
  204. ic, err := c.getIpcContainer()
  205. if err != nil {
  206. return err
  207. }
  208. ipc.ContainerID = ic.ID
  209. } else {
  210. ipc.HostIpc = c.hostConfig.IpcMode.IsHost()
  211. }
  212. pid := &execdriver.Pid{}
  213. pid.HostPid = c.hostConfig.PidMode.IsHost()
  214. // Build lists of devices allowed and created within the container.
  215. userSpecifiedDevices := make([]*devices.Device, len(c.hostConfig.Devices))
  216. for i, deviceMapping := range c.hostConfig.Devices {
  217. device, err := devices.GetDevice(deviceMapping.PathOnHost, deviceMapping.CgroupPermissions)
  218. if err != nil {
  219. return fmt.Errorf("error gathering device information while adding custom device %q: %s", deviceMapping.PathOnHost, err)
  220. }
  221. device.Path = deviceMapping.PathInContainer
  222. userSpecifiedDevices[i] = device
  223. }
  224. allowedDevices := append(devices.DefaultAllowedDevices, userSpecifiedDevices...)
  225. autoCreatedDevices := append(devices.DefaultAutoCreatedDevices, userSpecifiedDevices...)
  226. // TODO: this can be removed after lxc-conf is fully deprecated
  227. lxcConfig, err := mergeLxcConfIntoOptions(c.hostConfig)
  228. if err != nil {
  229. return err
  230. }
  231. resources := &execdriver.Resources{
  232. Memory: c.Config.Memory,
  233. MemorySwap: c.Config.MemorySwap,
  234. CpuShares: c.Config.CpuShares,
  235. Cpuset: c.Config.Cpuset,
  236. }
  237. processConfig := execdriver.ProcessConfig{
  238. Privileged: c.hostConfig.Privileged,
  239. Entrypoint: c.Path,
  240. Arguments: c.Args,
  241. Tty: c.Config.Tty,
  242. User: c.Config.User,
  243. }
  244. processConfig.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
  245. processConfig.Env = env
  246. c.command = &execdriver.Command{
  247. ID: c.ID,
  248. Rootfs: c.RootfsPath(),
  249. ReadonlyRootfs: c.hostConfig.ReadonlyRootfs,
  250. InitPath: "/.dockerinit",
  251. WorkingDir: c.Config.WorkingDir,
  252. Network: en,
  253. Ipc: ipc,
  254. Pid: pid,
  255. Resources: resources,
  256. AllowedDevices: allowedDevices,
  257. AutoCreatedDevices: autoCreatedDevices,
  258. CapAdd: c.hostConfig.CapAdd,
  259. CapDrop: c.hostConfig.CapDrop,
  260. ProcessConfig: processConfig,
  261. ProcessLabel: c.GetProcessLabel(),
  262. MountLabel: c.GetMountLabel(),
  263. LxcConfig: lxcConfig,
  264. AppArmorProfile: c.AppArmorProfile,
  265. }
  266. return nil
  267. }
  268. func (container *Container) Start() (err error) {
  269. container.Lock()
  270. defer container.Unlock()
  271. if container.Running {
  272. return nil
  273. }
  274. // if we encounter and error during start we need to ensure that any other
  275. // setup has been cleaned up properly
  276. defer func() {
  277. if err != nil {
  278. container.setError(err)
  279. // if no one else has set it, make sure we don't leave it at zero
  280. if container.ExitCode == 0 {
  281. container.ExitCode = 128
  282. }
  283. container.toDisk()
  284. container.cleanup()
  285. }
  286. }()
  287. if err := container.setupContainerDns(); err != nil {
  288. return err
  289. }
  290. if err := container.Mount(); err != nil {
  291. return err
  292. }
  293. if err := container.initializeNetworking(); err != nil {
  294. return err
  295. }
  296. if err := container.updateParentsHosts(); err != nil {
  297. return err
  298. }
  299. container.verifyDaemonSettings()
  300. if err := container.prepareVolumes(); err != nil {
  301. return err
  302. }
  303. linkedEnv, err := container.setupLinkedContainers()
  304. if err != nil {
  305. return err
  306. }
  307. if err := container.setupWorkingDirectory(); err != nil {
  308. return err
  309. }
  310. env := container.createDaemonEnvironment(linkedEnv)
  311. if err := populateCommand(container, env); err != nil {
  312. return err
  313. }
  314. if err := container.setupMounts(); err != nil {
  315. return err
  316. }
  317. return container.waitForStart()
  318. }
  319. func (container *Container) Run() error {
  320. if err := container.Start(); err != nil {
  321. return err
  322. }
  323. container.WaitStop(-1 * time.Second)
  324. return nil
  325. }
  326. func (container *Container) Output() (output []byte, err error) {
  327. pipe := container.StdoutPipe()
  328. defer pipe.Close()
  329. if err := container.Start(); err != nil {
  330. return nil, err
  331. }
  332. output, err = ioutil.ReadAll(pipe)
  333. container.WaitStop(-1 * time.Second)
  334. return output, err
  335. }
  336. // StreamConfig.StdinPipe returns a WriteCloser which can be used to feed data
  337. // to the standard input of the container's active process.
  338. // Container.StdoutPipe and Container.StderrPipe each return a ReadCloser
  339. // which can be used to retrieve the standard output (and error) generated
  340. // by the container's active process. The output (and error) are actually
  341. // copied and delivered to all StdoutPipe and StderrPipe consumers, using
  342. // a kind of "broadcaster".
  343. func (streamConfig *StreamConfig) StdinPipe() io.WriteCloser {
  344. return streamConfig.stdinPipe
  345. }
  346. func (streamConfig *StreamConfig) StdoutPipe() io.ReadCloser {
  347. reader, writer := io.Pipe()
  348. streamConfig.stdout.AddWriter(writer, "")
  349. return ioutils.NewBufReader(reader)
  350. }
  351. func (streamConfig *StreamConfig) StderrPipe() io.ReadCloser {
  352. reader, writer := io.Pipe()
  353. streamConfig.stderr.AddWriter(writer, "")
  354. return ioutils.NewBufReader(reader)
  355. }
  356. func (streamConfig *StreamConfig) StdoutLogPipe() io.ReadCloser {
  357. reader, writer := io.Pipe()
  358. streamConfig.stdout.AddWriter(writer, "stdout")
  359. return ioutils.NewBufReader(reader)
  360. }
  361. func (streamConfig *StreamConfig) StderrLogPipe() io.ReadCloser {
  362. reader, writer := io.Pipe()
  363. streamConfig.stderr.AddWriter(writer, "stderr")
  364. return ioutils.NewBufReader(reader)
  365. }
  366. func (container *Container) buildHostnameFile() error {
  367. hostnamePath, err := container.getRootResourcePath("hostname")
  368. if err != nil {
  369. return err
  370. }
  371. container.HostnamePath = hostnamePath
  372. if container.Config.Domainname != "" {
  373. return ioutil.WriteFile(container.HostnamePath, []byte(fmt.Sprintf("%s.%s\n", container.Config.Hostname, container.Config.Domainname)), 0644)
  374. }
  375. return ioutil.WriteFile(container.HostnamePath, []byte(container.Config.Hostname+"\n"), 0644)
  376. }
  377. func (container *Container) buildHostsFiles(IP string) error {
  378. hostsPath, err := container.getRootResourcePath("hosts")
  379. if err != nil {
  380. return err
  381. }
  382. container.HostsPath = hostsPath
  383. var extraContent []etchosts.Record
  384. children, err := container.daemon.Children(container.Name)
  385. if err != nil {
  386. return err
  387. }
  388. for linkAlias, child := range children {
  389. _, alias := path.Split(linkAlias)
  390. extraContent = append(extraContent, etchosts.Record{Hosts: alias, IP: child.NetworkSettings.IPAddress})
  391. }
  392. for _, extraHost := range container.hostConfig.ExtraHosts {
  393. parts := strings.Split(extraHost, ":")
  394. extraContent = append(extraContent, etchosts.Record{Hosts: parts[0], IP: parts[1]})
  395. }
  396. return etchosts.Build(container.HostsPath, IP, container.Config.Hostname, container.Config.Domainname, extraContent)
  397. }
  398. func (container *Container) buildHostnameAndHostsFiles(IP string) error {
  399. if err := container.buildHostnameFile(); err != nil {
  400. return err
  401. }
  402. return container.buildHostsFiles(IP)
  403. }
  404. func (container *Container) AllocateNetwork() error {
  405. mode := container.hostConfig.NetworkMode
  406. if container.Config.NetworkDisabled || !mode.IsPrivate() {
  407. return nil
  408. }
  409. var (
  410. env *engine.Env
  411. err error
  412. eng = container.daemon.eng
  413. )
  414. job := eng.Job("allocate_interface", container.ID)
  415. job.Setenv("RequestedMac", container.Config.MacAddress)
  416. if env, err = job.Stdout.AddEnv(); err != nil {
  417. return err
  418. }
  419. if err = job.Run(); err != nil {
  420. return err
  421. }
  422. // Error handling: At this point, the interface is allocated so we have to
  423. // make sure that it is always released in case of error, otherwise we
  424. // might leak resources.
  425. if container.Config.PortSpecs != nil {
  426. if err = migratePortMappings(container.Config, container.hostConfig); err != nil {
  427. eng.Job("release_interface", container.ID).Run()
  428. return err
  429. }
  430. container.Config.PortSpecs = nil
  431. if err = container.WriteHostConfig(); err != nil {
  432. eng.Job("release_interface", container.ID).Run()
  433. return err
  434. }
  435. }
  436. var (
  437. portSpecs = make(nat.PortSet)
  438. bindings = make(nat.PortMap)
  439. )
  440. if container.Config.ExposedPorts != nil {
  441. portSpecs = container.Config.ExposedPorts
  442. }
  443. if container.hostConfig.PortBindings != nil {
  444. for p, b := range container.hostConfig.PortBindings {
  445. bindings[p] = []nat.PortBinding{}
  446. for _, bb := range b {
  447. bindings[p] = append(bindings[p], nat.PortBinding{
  448. HostIp: bb.HostIp,
  449. HostPort: bb.HostPort,
  450. })
  451. }
  452. }
  453. }
  454. container.NetworkSettings.PortMapping = nil
  455. for port := range portSpecs {
  456. if err = container.allocatePort(eng, port, bindings); err != nil {
  457. eng.Job("release_interface", container.ID).Run()
  458. return err
  459. }
  460. }
  461. container.WriteHostConfig()
  462. container.NetworkSettings.Ports = bindings
  463. container.NetworkSettings.Bridge = env.Get("Bridge")
  464. container.NetworkSettings.IPAddress = env.Get("IP")
  465. container.NetworkSettings.IPPrefixLen = env.GetInt("IPPrefixLen")
  466. container.NetworkSettings.MacAddress = env.Get("MacAddress")
  467. container.NetworkSettings.Gateway = env.Get("Gateway")
  468. container.NetworkSettings.LinkLocalIPv6Address = env.Get("LinkLocalIPv6")
  469. container.NetworkSettings.LinkLocalIPv6PrefixLen = 64
  470. container.NetworkSettings.GlobalIPv6Address = env.Get("GlobalIPv6")
  471. container.NetworkSettings.GlobalIPv6PrefixLen = env.GetInt("GlobalIPv6PrefixLen")
  472. container.NetworkSettings.IPv6Gateway = env.Get("IPv6Gateway")
  473. return nil
  474. }
  475. func (container *Container) ReleaseNetwork() {
  476. if container.Config.NetworkDisabled || !container.hostConfig.NetworkMode.IsPrivate() {
  477. return
  478. }
  479. eng := container.daemon.eng
  480. job := eng.Job("release_interface", container.ID)
  481. job.SetenvBool("overrideShutdown", true)
  482. job.Run()
  483. container.NetworkSettings = &NetworkSettings{}
  484. }
  485. func (container *Container) isNetworkAllocated() bool {
  486. return container.NetworkSettings.IPAddress != ""
  487. }
  488. func (container *Container) RestoreNetwork() error {
  489. mode := container.hostConfig.NetworkMode
  490. // Don't attempt a restore if we previously didn't allocate networking.
  491. // This might be a legacy container with no network allocated, in which case the
  492. // allocation will happen once and for all at start.
  493. if !container.isNetworkAllocated() || container.Config.NetworkDisabled || !mode.IsPrivate() {
  494. return nil
  495. }
  496. eng := container.daemon.eng
  497. // Re-allocate the interface with the same IP and MAC address.
  498. job := eng.Job("allocate_interface", container.ID)
  499. job.Setenv("RequestedIP", container.NetworkSettings.IPAddress)
  500. job.Setenv("RequestedMac", container.NetworkSettings.MacAddress)
  501. if err := job.Run(); err != nil {
  502. return err
  503. }
  504. // Re-allocate any previously allocated ports.
  505. for port := range container.NetworkSettings.Ports {
  506. if err := container.allocatePort(eng, port, container.NetworkSettings.Ports); err != nil {
  507. return err
  508. }
  509. }
  510. return nil
  511. }
  512. // cleanup releases any network resources allocated to the container along with any rules
  513. // around how containers are linked together. It also unmounts the container's root filesystem.
  514. func (container *Container) cleanup() {
  515. container.ReleaseNetwork()
  516. // Disable all active links
  517. if container.activeLinks != nil {
  518. for _, link := range container.activeLinks {
  519. link.Disable()
  520. }
  521. }
  522. if err := container.Unmount(); err != nil {
  523. log.Errorf("%v: Failed to umount filesystem: %v", container.ID, err)
  524. }
  525. for _, eConfig := range container.execCommands.s {
  526. container.daemon.unregisterExecCommand(eConfig)
  527. }
  528. }
  529. func (container *Container) KillSig(sig int) error {
  530. log.Debugf("Sending %d to %s", sig, container.ID)
  531. container.Lock()
  532. defer container.Unlock()
  533. // We could unpause the container for them rather than returning this error
  534. if container.Paused {
  535. return fmt.Errorf("Container %s is paused. Unpause the container before stopping", container.ID)
  536. }
  537. if !container.Running {
  538. return nil
  539. }
  540. // signal to the monitor that it should not restart the container
  541. // after we send the kill signal
  542. container.monitor.ExitOnNext()
  543. // if the container is currently restarting we do not need to send the signal
  544. // to the process. Telling the monitor that it should exit on it's next event
  545. // loop is enough
  546. if container.Restarting {
  547. return nil
  548. }
  549. return container.daemon.Kill(container, sig)
  550. }
  551. func (container *Container) Pause() error {
  552. if container.IsPaused() {
  553. return fmt.Errorf("Container %s is already paused", container.ID)
  554. }
  555. if !container.IsRunning() {
  556. return fmt.Errorf("Container %s is not running", container.ID)
  557. }
  558. return container.daemon.Pause(container)
  559. }
  560. func (container *Container) Unpause() error {
  561. if !container.IsPaused() {
  562. return fmt.Errorf("Container %s is not paused", container.ID)
  563. }
  564. if !container.IsRunning() {
  565. return fmt.Errorf("Container %s is not running", container.ID)
  566. }
  567. return container.daemon.Unpause(container)
  568. }
  569. func (container *Container) Kill() error {
  570. if !container.IsRunning() {
  571. return nil
  572. }
  573. // 1. Send SIGKILL
  574. if err := container.KillSig(9); err != nil {
  575. return err
  576. }
  577. // 2. Wait for the process to die, in last resort, try to kill the process directly
  578. if _, err := container.WaitStop(10 * time.Second); err != nil {
  579. // Ensure that we don't kill ourselves
  580. if pid := container.GetPid(); pid != 0 {
  581. log.Infof("Container %s failed to exit within 10 seconds of kill - trying direct SIGKILL", utils.TruncateID(container.ID))
  582. if err := syscall.Kill(pid, 9); err != nil {
  583. return err
  584. }
  585. }
  586. }
  587. container.WaitStop(-1 * time.Second)
  588. return nil
  589. }
  590. func (container *Container) Stop(seconds int) error {
  591. if !container.IsRunning() {
  592. return nil
  593. }
  594. // 1. Send a SIGTERM
  595. if err := container.KillSig(15); err != nil {
  596. log.Infof("Failed to send SIGTERM to the process, force killing")
  597. if err := container.KillSig(9); err != nil {
  598. return err
  599. }
  600. }
  601. // 2. Wait for the process to exit on its own
  602. if _, err := container.WaitStop(time.Duration(seconds) * time.Second); err != nil {
  603. log.Infof("Container %v failed to exit within %d seconds of SIGTERM - using the force", container.ID, seconds)
  604. // 3. If it doesn't, then send SIGKILL
  605. if err := container.Kill(); err != nil {
  606. container.WaitStop(-1 * time.Second)
  607. return err
  608. }
  609. }
  610. return nil
  611. }
  612. func (container *Container) Restart(seconds int) error {
  613. // Avoid unnecessarily unmounting and then directly mounting
  614. // the container when the container stops and then starts
  615. // again
  616. if err := container.Mount(); err == nil {
  617. defer container.Unmount()
  618. }
  619. if err := container.Stop(seconds); err != nil {
  620. return err
  621. }
  622. return container.Start()
  623. }
  624. func (container *Container) Resize(h, w int) error {
  625. if !container.IsRunning() {
  626. return fmt.Errorf("Cannot resize container %s, container is not running", container.ID)
  627. }
  628. return container.command.ProcessConfig.Terminal.Resize(h, w)
  629. }
  630. func (container *Container) ExportRw() (archive.Archive, error) {
  631. if err := container.Mount(); err != nil {
  632. return nil, err
  633. }
  634. if container.daemon == nil {
  635. return nil, fmt.Errorf("Can't load storage driver for unregistered container %s", container.ID)
  636. }
  637. archive, err := container.daemon.Diff(container)
  638. if err != nil {
  639. container.Unmount()
  640. return nil, err
  641. }
  642. return ioutils.NewReadCloserWrapper(archive, func() error {
  643. err := archive.Close()
  644. container.Unmount()
  645. return err
  646. }),
  647. nil
  648. }
  649. func (container *Container) Export() (archive.Archive, error) {
  650. if err := container.Mount(); err != nil {
  651. return nil, err
  652. }
  653. archive, err := archive.Tar(container.basefs, archive.Uncompressed)
  654. if err != nil {
  655. container.Unmount()
  656. return nil, err
  657. }
  658. return ioutils.NewReadCloserWrapper(archive, func() error {
  659. err := archive.Close()
  660. container.Unmount()
  661. return err
  662. }),
  663. nil
  664. }
  665. func (container *Container) Mount() error {
  666. return container.daemon.Mount(container)
  667. }
  668. func (container *Container) changes() ([]archive.Change, error) {
  669. return container.daemon.Changes(container)
  670. }
  671. func (container *Container) Changes() ([]archive.Change, error) {
  672. container.Lock()
  673. defer container.Unlock()
  674. return container.changes()
  675. }
  676. func (container *Container) GetImage() (*image.Image, error) {
  677. if container.daemon == nil {
  678. return nil, fmt.Errorf("Can't get image of unregistered container")
  679. }
  680. return container.daemon.graph.Get(container.ImageID)
  681. }
  682. func (container *Container) Unmount() error {
  683. return container.daemon.Unmount(container)
  684. }
  685. func (container *Container) logPath(name string) (string, error) {
  686. return container.getRootResourcePath(fmt.Sprintf("%s-%s.log", container.ID, name))
  687. }
  688. func (container *Container) ReadLog(name string) (io.Reader, error) {
  689. pth, err := container.logPath(name)
  690. if err != nil {
  691. return nil, err
  692. }
  693. return os.Open(pth)
  694. }
  695. func (container *Container) hostConfigPath() (string, error) {
  696. return container.getRootResourcePath("hostconfig.json")
  697. }
  698. func (container *Container) jsonPath() (string, error) {
  699. return container.getRootResourcePath("config.json")
  700. }
  701. // This method must be exported to be used from the lxc template
  702. // This directory is only usable when the container is running
  703. func (container *Container) RootfsPath() string {
  704. return container.basefs
  705. }
  706. func validateID(id string) error {
  707. if id == "" {
  708. return fmt.Errorf("Invalid empty id")
  709. }
  710. return nil
  711. }
  712. // GetSize, return real size, virtual size
  713. func (container *Container) GetSize() (int64, int64) {
  714. var (
  715. sizeRw, sizeRootfs int64
  716. err error
  717. driver = container.daemon.driver
  718. )
  719. if err := container.Mount(); err != nil {
  720. log.Errorf("Warning: failed to compute size of container rootfs %s: %s", container.ID, err)
  721. return sizeRw, sizeRootfs
  722. }
  723. defer container.Unmount()
  724. initID := fmt.Sprintf("%s-init", container.ID)
  725. sizeRw, err = driver.DiffSize(container.ID, initID)
  726. if err != nil {
  727. log.Errorf("Warning: driver %s couldn't return diff size of container %s: %s", driver, container.ID, err)
  728. // FIXME: GetSize should return an error. Not changing it now in case
  729. // there is a side-effect.
  730. sizeRw = -1
  731. }
  732. if _, err = os.Stat(container.basefs); err != nil {
  733. if sizeRootfs, err = utils.TreeSize(container.basefs); err != nil {
  734. sizeRootfs = -1
  735. }
  736. }
  737. return sizeRw, sizeRootfs
  738. }
  739. func (container *Container) Copy(resource string) (io.ReadCloser, error) {
  740. if err := container.Mount(); err != nil {
  741. return nil, err
  742. }
  743. basePath, err := container.getResourcePath(resource)
  744. if err != nil {
  745. container.Unmount()
  746. return nil, err
  747. }
  748. // Check if this is actually in a volume
  749. for _, mnt := range container.VolumeMounts() {
  750. if len(mnt.MountToPath) > 0 && strings.HasPrefix(resource, mnt.MountToPath[1:]) {
  751. return mnt.Export(resource)
  752. }
  753. }
  754. stat, err := os.Stat(basePath)
  755. if err != nil {
  756. container.Unmount()
  757. return nil, err
  758. }
  759. var filter []string
  760. if !stat.IsDir() {
  761. d, f := path.Split(basePath)
  762. basePath = d
  763. filter = []string{f}
  764. } else {
  765. filter = []string{path.Base(basePath)}
  766. basePath = path.Dir(basePath)
  767. }
  768. archive, err := archive.TarWithOptions(basePath, &archive.TarOptions{
  769. Compression: archive.Uncompressed,
  770. IncludeFiles: filter,
  771. })
  772. if err != nil {
  773. container.Unmount()
  774. return nil, err
  775. }
  776. return ioutils.NewReadCloserWrapper(archive, func() error {
  777. err := archive.Close()
  778. container.Unmount()
  779. return err
  780. }),
  781. nil
  782. }
  783. // Returns true if the container exposes a certain port
  784. func (container *Container) Exposes(p nat.Port) bool {
  785. _, exists := container.Config.ExposedPorts[p]
  786. return exists
  787. }
  788. func (container *Container) GetPtyMaster() (*os.File, error) {
  789. ttyConsole, ok := container.command.ProcessConfig.Terminal.(execdriver.TtyTerminal)
  790. if !ok {
  791. return nil, ErrNoTTY
  792. }
  793. return ttyConsole.Master(), nil
  794. }
  795. func (container *Container) HostConfig() *runconfig.HostConfig {
  796. container.Lock()
  797. res := container.hostConfig
  798. container.Unlock()
  799. return res
  800. }
  801. func (container *Container) SetHostConfig(hostConfig *runconfig.HostConfig) {
  802. container.Lock()
  803. container.hostConfig = hostConfig
  804. container.Unlock()
  805. }
  806. func (container *Container) DisableLink(name string) {
  807. if container.activeLinks != nil {
  808. if link, exists := container.activeLinks[name]; exists {
  809. link.Disable()
  810. } else {
  811. log.Debugf("Could not find active link for %s", name)
  812. }
  813. }
  814. }
  815. func (container *Container) setupContainerDns() error {
  816. if container.ResolvConfPath != "" {
  817. // check if this is an existing container that needs DNS update:
  818. if container.UpdateDns {
  819. // read the host's resolv.conf, get the hash and call updateResolvConf
  820. log.Debugf("Check container (%s) for update to resolv.conf - UpdateDns flag was set", container.ID)
  821. latestResolvConf, latestHash := resolvconf.GetLastModified()
  822. // because the new host resolv.conf might have localhost nameservers..
  823. updatedResolvConf, modified := resolvconf.RemoveReplaceLocalDns(latestResolvConf)
  824. if modified {
  825. // changes have occurred during resolv.conf localhost cleanup: generate an updated hash
  826. newHash, err := utils.HashData(bytes.NewReader(updatedResolvConf))
  827. if err != nil {
  828. return err
  829. }
  830. latestHash = newHash
  831. }
  832. if err := container.updateResolvConf(updatedResolvConf, latestHash); err != nil {
  833. return err
  834. }
  835. // successful update of the restarting container; set the flag off
  836. container.UpdateDns = false
  837. }
  838. return nil
  839. }
  840. var (
  841. config = container.hostConfig
  842. daemon = container.daemon
  843. )
  844. resolvConf, err := resolvconf.Get()
  845. if err != nil {
  846. return err
  847. }
  848. container.ResolvConfPath, err = container.getRootResourcePath("resolv.conf")
  849. if err != nil {
  850. return err
  851. }
  852. if config.NetworkMode != "host" {
  853. // check configurations for any container/daemon dns settings
  854. if len(config.Dns) > 0 || len(daemon.config.Dns) > 0 || len(config.DnsSearch) > 0 || len(daemon.config.DnsSearch) > 0 {
  855. var (
  856. dns = resolvconf.GetNameservers(resolvConf)
  857. dnsSearch = resolvconf.GetSearchDomains(resolvConf)
  858. )
  859. if len(config.Dns) > 0 {
  860. dns = config.Dns
  861. } else if len(daemon.config.Dns) > 0 {
  862. dns = daemon.config.Dns
  863. }
  864. if len(config.DnsSearch) > 0 {
  865. dnsSearch = config.DnsSearch
  866. } else if len(daemon.config.DnsSearch) > 0 {
  867. dnsSearch = daemon.config.DnsSearch
  868. }
  869. return resolvconf.Build(container.ResolvConfPath, dns, dnsSearch)
  870. }
  871. // replace any localhost/127.* nameservers
  872. resolvConf, _ = resolvconf.RemoveReplaceLocalDns(resolvConf)
  873. }
  874. //get a sha256 hash of the resolv conf at this point so we can check
  875. //for changes when the host resolv.conf changes (e.g. network update)
  876. resolvHash, err := utils.HashData(bytes.NewReader(resolvConf))
  877. if err != nil {
  878. return err
  879. }
  880. resolvHashFile := container.ResolvConfPath + ".hash"
  881. if err = ioutil.WriteFile(resolvHashFile, []byte(resolvHash), 0644); err != nil {
  882. return err
  883. }
  884. return ioutil.WriteFile(container.ResolvConfPath, resolvConf, 0644)
  885. }
  886. // called when the host's resolv.conf changes to check whether container's resolv.conf
  887. // is unchanged by the container "user" since container start: if unchanged, the
  888. // container's resolv.conf will be updated to match the host's new resolv.conf
  889. func (container *Container) updateResolvConf(updatedResolvConf []byte, newResolvHash string) error {
  890. if container.ResolvConfPath == "" {
  891. return nil
  892. }
  893. if container.Running {
  894. //set a marker in the hostConfig to update on next start/restart
  895. container.UpdateDns = true
  896. return nil
  897. }
  898. resolvHashFile := container.ResolvConfPath + ".hash"
  899. //read the container's current resolv.conf and compute the hash
  900. resolvBytes, err := ioutil.ReadFile(container.ResolvConfPath)
  901. if err != nil {
  902. return err
  903. }
  904. curHash, err := utils.HashData(bytes.NewReader(resolvBytes))
  905. if err != nil {
  906. return err
  907. }
  908. //read the hash from the last time we wrote resolv.conf in the container
  909. hashBytes, err := ioutil.ReadFile(resolvHashFile)
  910. if err != nil {
  911. if !os.IsNotExist(err) {
  912. return err
  913. }
  914. // backwards compat: if no hash file exists, this container pre-existed from
  915. // a Docker daemon that didn't contain this update feature. Given we can't know
  916. // if the user has modified the resolv.conf since container start time, safer
  917. // to just never update the container's resolv.conf during it's lifetime which
  918. // we can control by setting hashBytes to an empty string
  919. hashBytes = []byte("")
  920. }
  921. //if the user has not modified the resolv.conf of the container since we wrote it last
  922. //we will replace it with the updated resolv.conf from the host
  923. if string(hashBytes) == curHash {
  924. log.Debugf("replacing %q with updated host resolv.conf", container.ResolvConfPath)
  925. // for atomic updates to these files, use temporary files with os.Rename:
  926. dir := path.Dir(container.ResolvConfPath)
  927. tmpHashFile, err := ioutil.TempFile(dir, "hash")
  928. if err != nil {
  929. return err
  930. }
  931. tmpResolvFile, err := ioutil.TempFile(dir, "resolv")
  932. if err != nil {
  933. return err
  934. }
  935. // write the updates to the temp files
  936. if err = ioutil.WriteFile(tmpHashFile.Name(), []byte(newResolvHash), 0644); err != nil {
  937. return err
  938. }
  939. if err = ioutil.WriteFile(tmpResolvFile.Name(), updatedResolvConf, 0644); err != nil {
  940. return err
  941. }
  942. // rename the temp files for atomic replace
  943. if err = os.Rename(tmpHashFile.Name(), resolvHashFile); err != nil {
  944. return err
  945. }
  946. return os.Rename(tmpResolvFile.Name(), container.ResolvConfPath)
  947. }
  948. return nil
  949. }
  950. func (container *Container) updateParentsHosts() error {
  951. parents, err := container.daemon.Parents(container.Name)
  952. if err != nil {
  953. return err
  954. }
  955. for _, cid := range parents {
  956. if cid == "0" {
  957. continue
  958. }
  959. c := container.daemon.Get(cid)
  960. if c != nil && !container.daemon.config.DisableNetwork && container.hostConfig.NetworkMode.IsPrivate() {
  961. if err := etchosts.Update(c.HostsPath, container.NetworkSettings.IPAddress, container.Name[1:]); err != nil {
  962. log.Errorf("Failed to update /etc/hosts in parent container: %v", err)
  963. }
  964. }
  965. }
  966. return nil
  967. }
  968. func (container *Container) initializeNetworking() error {
  969. var err error
  970. if container.hostConfig.NetworkMode.IsHost() {
  971. container.Config.Hostname, err = os.Hostname()
  972. if err != nil {
  973. return err
  974. }
  975. parts := strings.SplitN(container.Config.Hostname, ".", 2)
  976. if len(parts) > 1 {
  977. container.Config.Hostname = parts[0]
  978. container.Config.Domainname = parts[1]
  979. }
  980. content, err := ioutil.ReadFile("/etc/hosts")
  981. if os.IsNotExist(err) {
  982. return container.buildHostnameAndHostsFiles("")
  983. } else if err != nil {
  984. return err
  985. }
  986. if err := container.buildHostnameFile(); err != nil {
  987. return err
  988. }
  989. hostsPath, err := container.getRootResourcePath("hosts")
  990. if err != nil {
  991. return err
  992. }
  993. container.HostsPath = hostsPath
  994. return ioutil.WriteFile(container.HostsPath, content, 0644)
  995. }
  996. if container.hostConfig.NetworkMode.IsContainer() {
  997. // we need to get the hosts files from the container to join
  998. nc, err := container.getNetworkedContainer()
  999. if err != nil {
  1000. return err
  1001. }
  1002. container.HostsPath = nc.HostsPath
  1003. container.ResolvConfPath = nc.ResolvConfPath
  1004. container.Config.Hostname = nc.Config.Hostname
  1005. container.Config.Domainname = nc.Config.Domainname
  1006. return nil
  1007. }
  1008. if container.daemon.config.DisableNetwork {
  1009. container.Config.NetworkDisabled = true
  1010. return container.buildHostnameAndHostsFiles("127.0.1.1")
  1011. }
  1012. if err := container.AllocateNetwork(); err != nil {
  1013. return err
  1014. }
  1015. return container.buildHostnameAndHostsFiles(container.NetworkSettings.IPAddress)
  1016. }
  1017. // Make sure the config is compatible with the current kernel
  1018. func (container *Container) verifyDaemonSettings() {
  1019. if container.Config.Memory > 0 && !container.daemon.sysInfo.MemoryLimit {
  1020. log.Infof("WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.")
  1021. container.Config.Memory = 0
  1022. }
  1023. if container.Config.Memory > 0 && !container.daemon.sysInfo.SwapLimit {
  1024. log.Infof("WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.")
  1025. container.Config.MemorySwap = -1
  1026. }
  1027. if container.daemon.sysInfo.IPv4ForwardingDisabled {
  1028. log.Infof("WARNING: IPv4 forwarding is disabled. Networking will not work")
  1029. }
  1030. }
  1031. func (container *Container) setupLinkedContainers() ([]string, error) {
  1032. var (
  1033. env []string
  1034. daemon = container.daemon
  1035. )
  1036. children, err := daemon.Children(container.Name)
  1037. if err != nil {
  1038. return nil, err
  1039. }
  1040. if len(children) > 0 {
  1041. container.activeLinks = make(map[string]*links.Link, len(children))
  1042. // If we encounter an error make sure that we rollback any network
  1043. // config and ip table changes
  1044. rollback := func() {
  1045. for _, link := range container.activeLinks {
  1046. link.Disable()
  1047. }
  1048. container.activeLinks = nil
  1049. }
  1050. for linkAlias, child := range children {
  1051. if !child.IsRunning() {
  1052. return nil, fmt.Errorf("Cannot link to a non running container: %s AS %s", child.Name, linkAlias)
  1053. }
  1054. link, err := links.NewLink(
  1055. container.NetworkSettings.IPAddress,
  1056. child.NetworkSettings.IPAddress,
  1057. linkAlias,
  1058. child.Config.Env,
  1059. child.Config.ExposedPorts,
  1060. daemon.eng)
  1061. if err != nil {
  1062. rollback()
  1063. return nil, err
  1064. }
  1065. container.activeLinks[link.Alias()] = link
  1066. if err := link.Enable(); err != nil {
  1067. rollback()
  1068. return nil, err
  1069. }
  1070. for _, envVar := range link.ToEnv() {
  1071. env = append(env, envVar)
  1072. }
  1073. }
  1074. }
  1075. return env, nil
  1076. }
  1077. func (container *Container) createDaemonEnvironment(linkedEnv []string) []string {
  1078. // if a domain name was specified, append it to the hostname (see #7851)
  1079. fullHostname := container.Config.Hostname
  1080. if container.Config.Domainname != "" {
  1081. fullHostname = fmt.Sprintf("%s.%s", fullHostname, container.Config.Domainname)
  1082. }
  1083. // Setup environment
  1084. env := []string{
  1085. "PATH=" + DefaultPathEnv,
  1086. "HOSTNAME=" + fullHostname,
  1087. // Note: we don't set HOME here because it'll get autoset intelligently
  1088. // based on the value of USER inside dockerinit, but only if it isn't
  1089. // set already (ie, that can be overridden by setting HOME via -e or ENV
  1090. // in a Dockerfile).
  1091. }
  1092. if container.Config.Tty {
  1093. env = append(env, "TERM=xterm")
  1094. }
  1095. env = append(env, linkedEnv...)
  1096. // because the env on the container can override certain default values
  1097. // we need to replace the 'env' keys where they match and append anything
  1098. // else.
  1099. env = utils.ReplaceOrAppendEnvValues(env, container.Config.Env)
  1100. return env
  1101. }
  1102. func (container *Container) setupWorkingDirectory() error {
  1103. if container.Config.WorkingDir != "" {
  1104. container.Config.WorkingDir = path.Clean(container.Config.WorkingDir)
  1105. pth, err := container.getResourcePath(container.Config.WorkingDir)
  1106. if err != nil {
  1107. return err
  1108. }
  1109. pthInfo, err := os.Stat(pth)
  1110. if err != nil {
  1111. if !os.IsNotExist(err) {
  1112. return err
  1113. }
  1114. if err := os.MkdirAll(pth, 0755); err != nil {
  1115. return err
  1116. }
  1117. }
  1118. if pthInfo != nil && !pthInfo.IsDir() {
  1119. return fmt.Errorf("Cannot mkdir: %s is not a directory", container.Config.WorkingDir)
  1120. }
  1121. }
  1122. return nil
  1123. }
  1124. func (container *Container) startLoggingToDisk() error {
  1125. // Setup logging of stdout and stderr to disk
  1126. pth, err := container.logPath("json")
  1127. if err != nil {
  1128. return err
  1129. }
  1130. if err := container.daemon.LogToDisk(container.stdout, pth, "stdout"); err != nil {
  1131. return err
  1132. }
  1133. if err := container.daemon.LogToDisk(container.stderr, pth, "stderr"); err != nil {
  1134. return err
  1135. }
  1136. return nil
  1137. }
  1138. func (container *Container) waitForStart() error {
  1139. container.monitor = newContainerMonitor(container, container.hostConfig.RestartPolicy)
  1140. // block until we either receive an error from the initial start of the container's
  1141. // process or until the process is running in the container
  1142. select {
  1143. case <-container.monitor.startSignal:
  1144. case err := <-promise.Go(container.monitor.Start):
  1145. return err
  1146. }
  1147. return nil
  1148. }
  1149. func (container *Container) allocatePort(eng *engine.Engine, port nat.Port, bindings nat.PortMap) error {
  1150. binding := bindings[port]
  1151. if container.hostConfig.PublishAllPorts && len(binding) == 0 {
  1152. binding = append(binding, nat.PortBinding{})
  1153. }
  1154. for i := 0; i < len(binding); i++ {
  1155. b := binding[i]
  1156. job := eng.Job("allocate_port", container.ID)
  1157. job.Setenv("HostIP", b.HostIp)
  1158. job.Setenv("HostPort", b.HostPort)
  1159. job.Setenv("Proto", port.Proto())
  1160. job.Setenv("ContainerPort", port.Port())
  1161. portEnv, err := job.Stdout.AddEnv()
  1162. if err != nil {
  1163. return err
  1164. }
  1165. if err := job.Run(); err != nil {
  1166. return err
  1167. }
  1168. b.HostIp = portEnv.Get("HostIP")
  1169. b.HostPort = portEnv.Get("HostPort")
  1170. binding[i] = b
  1171. }
  1172. bindings[port] = binding
  1173. return nil
  1174. }
  1175. func (container *Container) GetProcessLabel() string {
  1176. // even if we have a process label return "" if we are running
  1177. // in privileged mode
  1178. if container.hostConfig.Privileged {
  1179. return ""
  1180. }
  1181. return container.ProcessLabel
  1182. }
  1183. func (container *Container) GetMountLabel() string {
  1184. if container.hostConfig.Privileged {
  1185. return ""
  1186. }
  1187. return container.MountLabel
  1188. }
  1189. func (container *Container) getIpcContainer() (*Container, error) {
  1190. containerID := container.hostConfig.IpcMode.Container()
  1191. c := container.daemon.Get(containerID)
  1192. if c == nil {
  1193. return nil, fmt.Errorf("no such container to join IPC: %s", containerID)
  1194. }
  1195. if !c.IsRunning() {
  1196. return nil, fmt.Errorf("cannot join IPC of a non running container: %s", containerID)
  1197. }
  1198. return c, nil
  1199. }
  1200. func (container *Container) getNetworkedContainer() (*Container, error) {
  1201. parts := strings.SplitN(string(container.hostConfig.NetworkMode), ":", 2)
  1202. switch parts[0] {
  1203. case "container":
  1204. if len(parts) != 2 {
  1205. return nil, fmt.Errorf("no container specified to join network")
  1206. }
  1207. nc := container.daemon.Get(parts[1])
  1208. if nc == nil {
  1209. return nil, fmt.Errorf("no such container to join network: %s", parts[1])
  1210. }
  1211. if !nc.IsRunning() {
  1212. return nil, fmt.Errorf("cannot join network of a non running container: %s", parts[1])
  1213. }
  1214. return nc, nil
  1215. default:
  1216. return nil, fmt.Errorf("network mode not set to container")
  1217. }
  1218. }