container.go 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203
  1. package daemon
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "io/ioutil"
  8. "os"
  9. "path/filepath"
  10. "strings"
  11. "sync"
  12. "syscall"
  13. "time"
  14. "github.com/opencontainers/runc/libcontainer/label"
  15. "github.com/Sirupsen/logrus"
  16. "github.com/docker/docker/daemon/execdriver"
  17. "github.com/docker/docker/daemon/logger"
  18. "github.com/docker/docker/daemon/logger/jsonfilelog"
  19. "github.com/docker/docker/daemon/network"
  20. "github.com/docker/docker/image"
  21. "github.com/docker/docker/pkg/archive"
  22. "github.com/docker/docker/pkg/broadcastwriter"
  23. "github.com/docker/docker/pkg/fileutils"
  24. "github.com/docker/docker/pkg/ioutils"
  25. "github.com/docker/docker/pkg/mount"
  26. "github.com/docker/docker/pkg/nat"
  27. "github.com/docker/docker/pkg/promise"
  28. "github.com/docker/docker/pkg/symlink"
  29. "github.com/docker/docker/runconfig"
  30. "github.com/docker/docker/volume"
  31. )
  32. var (
  33. ErrNotATTY = errors.New("The PTY is not a file")
  34. ErrNoTTY = errors.New("No PTY found")
  35. ErrContainerStart = errors.New("The container failed to start. Unknown error")
  36. ErrContainerStartTimeout = errors.New("The container failed to start due to timed out.")
  37. )
  38. type StreamConfig struct {
  39. stdout *broadcastwriter.BroadcastWriter
  40. stderr *broadcastwriter.BroadcastWriter
  41. stdin io.ReadCloser
  42. stdinPipe io.WriteCloser
  43. }
  44. // CommonContainer holds the settings for a container which are applicable
  45. // across all platforms supported by the daemon.
  46. type CommonContainer struct {
  47. StreamConfig
  48. *State `json:"State"` // Needed for remote api version <= 1.11
  49. root string // Path to the "home" of the container, including metadata.
  50. basefs string // Path to the graphdriver mountpoint
  51. ID string
  52. Created time.Time
  53. Path string
  54. Args []string
  55. Config *runconfig.Config
  56. ImageID string `json:"Image"`
  57. NetworkSettings *network.Settings
  58. ResolvConfPath string
  59. HostnamePath string
  60. HostsPath string
  61. LogPath string
  62. Name string
  63. Driver string
  64. ExecDriver string
  65. MountLabel, ProcessLabel string
  66. RestartCount int
  67. UpdateDns bool
  68. HasBeenStartedBefore bool
  69. MountPoints map[string]*mountPoint
  70. Volumes map[string]string // Deprecated since 1.7, kept for backwards compatibility
  71. VolumesRW map[string]bool // Deprecated since 1.7, kept for backwards compatibility
  72. hostConfig *runconfig.HostConfig
  73. command *execdriver.Command
  74. monitor *containerMonitor
  75. execCommands *execStore
  76. daemon *Daemon
  77. // logDriver for closing
  78. logDriver logger.Logger
  79. logCopier *logger.Copier
  80. }
  81. func (container *Container) FromDisk() error {
  82. pth, err := container.jsonPath()
  83. if err != nil {
  84. return err
  85. }
  86. jsonSource, err := os.Open(pth)
  87. if err != nil {
  88. return err
  89. }
  90. defer jsonSource.Close()
  91. dec := json.NewDecoder(jsonSource)
  92. // Load container settings
  93. // udp broke compat of docker.PortMapping, but it's not used when loading a container, we can skip it
  94. if err := dec.Decode(container); err != nil && !strings.Contains(err.Error(), "docker.PortMapping") {
  95. return err
  96. }
  97. if err := label.ReserveLabel(container.ProcessLabel); err != nil {
  98. return err
  99. }
  100. return container.readHostConfig()
  101. }
  102. func (container *Container) toDisk() error {
  103. data, err := json.Marshal(container)
  104. if err != nil {
  105. return err
  106. }
  107. pth, err := container.jsonPath()
  108. if err != nil {
  109. return err
  110. }
  111. if err := ioutil.WriteFile(pth, data, 0666); err != nil {
  112. return err
  113. }
  114. return container.WriteHostConfig()
  115. }
  116. func (container *Container) ToDisk() error {
  117. container.Lock()
  118. err := container.toDisk()
  119. container.Unlock()
  120. return err
  121. }
  122. func (container *Container) readHostConfig() error {
  123. container.hostConfig = &runconfig.HostConfig{}
  124. // If the hostconfig file does not exist, do not read it.
  125. // (We still have to initialize container.hostConfig,
  126. // but that's OK, since we just did that above.)
  127. pth, err := container.hostConfigPath()
  128. if err != nil {
  129. return err
  130. }
  131. _, err = os.Stat(pth)
  132. if os.IsNotExist(err) {
  133. return nil
  134. }
  135. f, err := os.Open(pth)
  136. if err != nil {
  137. return err
  138. }
  139. defer f.Close()
  140. return json.NewDecoder(f).Decode(&container.hostConfig)
  141. }
  142. func (container *Container) WriteHostConfig() error {
  143. data, err := json.Marshal(container.hostConfig)
  144. if err != nil {
  145. return err
  146. }
  147. pth, err := container.hostConfigPath()
  148. if err != nil {
  149. return err
  150. }
  151. return ioutil.WriteFile(pth, data, 0666)
  152. }
  153. func (container *Container) LogEvent(action string) {
  154. d := container.daemon
  155. d.EventsService.Log(
  156. action,
  157. container.ID,
  158. container.Config.Image,
  159. )
  160. }
  161. // Evaluates `path` in the scope of the container's basefs, with proper path
  162. // sanitisation. Symlinks are all scoped to the basefs of the container, as
  163. // though the container's basefs was `/`.
  164. //
  165. // The basefs of a container is the host-facing path which is bind-mounted as
  166. // `/` inside the container. This method is essentially used to access a
  167. // particular path inside the container as though you were a process in that
  168. // container.
  169. //
  170. // NOTE: The returned path is *only* safely scoped inside the container's basefs
  171. // if no component of the returned path changes (such as a component
  172. // symlinking to a different path) between using this method and using the
  173. // path. See symlink.FollowSymlinkInScope for more details.
  174. func (container *Container) GetResourcePath(path string) (string, error) {
  175. // IMPORTANT - These are paths on the OS where the daemon is running, hence
  176. // any filepath operations must be done in an OS agnostic way.
  177. cleanPath := filepath.Join(string(os.PathSeparator), path)
  178. r, e := symlink.FollowSymlinkInScope(filepath.Join(container.basefs, cleanPath), container.basefs)
  179. return r, e
  180. }
  181. // Evaluates `path` in the scope of the container's root, with proper path
  182. // sanitisation. Symlinks are all scoped to the root of the container, as
  183. // though the container's root was `/`.
  184. //
  185. // The root of a container is the host-facing configuration metadata directory.
  186. // Only use this method to safely access the container's `container.json` or
  187. // other metadata files. If in doubt, use container.GetResourcePath.
  188. //
  189. // NOTE: The returned path is *only* safely scoped inside the container's root
  190. // if no component of the returned path changes (such as a component
  191. // symlinking to a different path) between using this method and using the
  192. // path. See symlink.FollowSymlinkInScope for more details.
  193. func (container *Container) GetRootResourcePath(path string) (string, error) {
  194. // IMPORTANT - These are paths on the OS where the daemon is running, hence
  195. // any filepath operations must be done in an OS agnostic way.
  196. cleanPath := filepath.Join(string(os.PathSeparator), path)
  197. return symlink.FollowSymlinkInScope(filepath.Join(container.root, cleanPath), container.root)
  198. }
  199. func (container *Container) Start() (err error) {
  200. container.Lock()
  201. defer container.Unlock()
  202. if container.Running {
  203. return nil
  204. }
  205. if container.removalInProgress || container.Dead {
  206. return fmt.Errorf("Container is marked for removal and cannot be started.")
  207. }
  208. // if we encounter an error during start we need to ensure that any other
  209. // setup has been cleaned up properly
  210. defer func() {
  211. if err != nil {
  212. container.setError(err)
  213. // if no one else has set it, make sure we don't leave it at zero
  214. if container.ExitCode == 0 {
  215. container.ExitCode = 128
  216. }
  217. container.toDisk()
  218. container.cleanup()
  219. container.LogEvent("die")
  220. }
  221. }()
  222. if err := container.Mount(); err != nil {
  223. return err
  224. }
  225. // No-op if non-Windows. Once the container filesystem is mounted,
  226. // prepare the layer to boot using the Windows driver.
  227. if err := container.PrepareStorage(); err != nil {
  228. return err
  229. }
  230. if err := container.initializeNetworking(); err != nil {
  231. return err
  232. }
  233. linkedEnv, err := container.setupLinkedContainers()
  234. if err != nil {
  235. return err
  236. }
  237. if err := container.setupWorkingDirectory(); err != nil {
  238. return err
  239. }
  240. env := container.createDaemonEnvironment(linkedEnv)
  241. if err := populateCommand(container, env); err != nil {
  242. return err
  243. }
  244. mounts, err := container.setupMounts()
  245. if err != nil {
  246. return err
  247. }
  248. container.command.Mounts = mounts
  249. return container.waitForStart()
  250. }
  251. func (container *Container) Run() error {
  252. if err := container.Start(); err != nil {
  253. return err
  254. }
  255. container.HasBeenStartedBefore = true
  256. container.WaitStop(-1 * time.Second)
  257. return nil
  258. }
  259. func (container *Container) Output() (output []byte, err error) {
  260. pipe := container.StdoutPipe()
  261. defer pipe.Close()
  262. if err := container.Start(); err != nil {
  263. return nil, err
  264. }
  265. output, err = ioutil.ReadAll(pipe)
  266. container.WaitStop(-1 * time.Second)
  267. return output, err
  268. }
  269. // StreamConfig.StdinPipe returns a WriteCloser which can be used to feed data
  270. // to the standard input of the container's active process.
  271. // Container.StdoutPipe and Container.StderrPipe each return a ReadCloser
  272. // which can be used to retrieve the standard output (and error) generated
  273. // by the container's active process. The output (and error) are actually
  274. // copied and delivered to all StdoutPipe and StderrPipe consumers, using
  275. // a kind of "broadcaster".
  276. func (streamConfig *StreamConfig) StdinPipe() io.WriteCloser {
  277. return streamConfig.stdinPipe
  278. }
  279. func (streamConfig *StreamConfig) StdoutPipe() io.ReadCloser {
  280. reader, writer := io.Pipe()
  281. streamConfig.stdout.AddWriter(writer)
  282. return ioutils.NewBufReader(reader)
  283. }
  284. func (streamConfig *StreamConfig) StderrPipe() io.ReadCloser {
  285. reader, writer := io.Pipe()
  286. streamConfig.stderr.AddWriter(writer)
  287. return ioutils.NewBufReader(reader)
  288. }
  289. func (container *Container) isNetworkAllocated() bool {
  290. return container.NetworkSettings.IPAddress != ""
  291. }
  292. // cleanup releases any network resources allocated to the container along with any rules
  293. // around how containers are linked together. It also unmounts the container's root filesystem.
  294. func (container *Container) cleanup() {
  295. container.ReleaseNetwork()
  296. disableAllActiveLinks(container)
  297. if err := container.CleanupStorage(); err != nil {
  298. logrus.Errorf("%v: Failed to cleanup storage: %v", container.ID, err)
  299. }
  300. if err := container.Unmount(); err != nil {
  301. logrus.Errorf("%v: Failed to umount filesystem: %v", container.ID, err)
  302. }
  303. for _, eConfig := range container.execCommands.s {
  304. container.daemon.unregisterExecCommand(eConfig)
  305. }
  306. container.UnmountVolumes(false)
  307. }
  308. func (container *Container) KillSig(sig int) error {
  309. logrus.Debugf("Sending %d to %s", sig, container.ID)
  310. container.Lock()
  311. defer container.Unlock()
  312. // We could unpause the container for them rather than returning this error
  313. if container.Paused {
  314. return fmt.Errorf("Container %s is paused. Unpause the container before stopping", container.ID)
  315. }
  316. if !container.Running {
  317. return fmt.Errorf("Container %s is not running", container.ID)
  318. }
  319. // signal to the monitor that it should not restart the container
  320. // after we send the kill signal
  321. container.monitor.ExitOnNext()
  322. // if the container is currently restarting we do not need to send the signal
  323. // to the process. Telling the monitor that it should exit on it's next event
  324. // loop is enough
  325. if container.Restarting {
  326. return nil
  327. }
  328. if err := container.daemon.Kill(container, sig); err != nil {
  329. return err
  330. }
  331. container.LogEvent("kill")
  332. return nil
  333. }
  334. // Wrapper aroung KillSig() suppressing "no such process" error.
  335. func (container *Container) killPossiblyDeadProcess(sig int) error {
  336. err := container.KillSig(sig)
  337. if err == syscall.ESRCH {
  338. logrus.Debugf("Cannot kill process (pid=%d) with signal %d: no such process.", container.GetPid(), sig)
  339. return nil
  340. }
  341. return err
  342. }
  343. func (container *Container) Pause() error {
  344. container.Lock()
  345. defer container.Unlock()
  346. // We cannot Pause the container which is not running
  347. if !container.Running {
  348. return fmt.Errorf("Container %s is not running, cannot pause a non-running container", container.ID)
  349. }
  350. // We cannot Pause the container which is already paused
  351. if container.Paused {
  352. return fmt.Errorf("Container %s is already paused", container.ID)
  353. }
  354. if err := container.daemon.execDriver.Pause(container.command); err != nil {
  355. return err
  356. }
  357. container.Paused = true
  358. container.LogEvent("pause")
  359. return nil
  360. }
  361. func (container *Container) Unpause() error {
  362. container.Lock()
  363. defer container.Unlock()
  364. // We cannot unpause the container which is not running
  365. if !container.Running {
  366. return fmt.Errorf("Container %s is not running, cannot unpause a non-running container", container.ID)
  367. }
  368. // We cannot unpause the container which is not paused
  369. if !container.Paused {
  370. return fmt.Errorf("Container %s is not paused", container.ID)
  371. }
  372. if err := container.daemon.execDriver.Unpause(container.command); err != nil {
  373. return err
  374. }
  375. container.Paused = false
  376. container.LogEvent("unpause")
  377. return nil
  378. }
  379. func (container *Container) Kill() error {
  380. if !container.IsRunning() {
  381. return fmt.Errorf("Container %s is not running", container.ID)
  382. }
  383. // 1. Send SIGKILL
  384. if err := container.killPossiblyDeadProcess(9); err != nil {
  385. // While normally we might "return err" here we're not going to
  386. // because if we can't stop the container by this point then
  387. // its probably because its already stopped. Meaning, between
  388. // the time of the IsRunning() call above and now it stopped.
  389. // Also, since the err return will be exec driver specific we can't
  390. // look for any particular (common) error that would indicate
  391. // that the process is already dead vs something else going wrong.
  392. // So, instead we'll give it up to 2 more seconds to complete and if
  393. // by that time the container is still running, then the error
  394. // we got is probably valid and so we return it to the caller.
  395. if container.IsRunning() {
  396. container.WaitStop(2 * time.Second)
  397. if container.IsRunning() {
  398. return err
  399. }
  400. }
  401. }
  402. // 2. Wait for the process to die, in last resort, try to kill the process directly
  403. if err := killProcessDirectly(container); err != nil {
  404. return err
  405. }
  406. container.WaitStop(-1 * time.Second)
  407. return nil
  408. }
  409. func (container *Container) Stop(seconds int) error {
  410. if !container.IsRunning() {
  411. return nil
  412. }
  413. // 1. Send a SIGTERM
  414. if err := container.killPossiblyDeadProcess(15); err != nil {
  415. logrus.Infof("Failed to send SIGTERM to the process, force killing")
  416. if err := container.killPossiblyDeadProcess(9); err != nil {
  417. return err
  418. }
  419. }
  420. // 2. Wait for the process to exit on its own
  421. if _, err := container.WaitStop(time.Duration(seconds) * time.Second); err != nil {
  422. logrus.Infof("Container %v failed to exit within %d seconds of SIGTERM - using the force", container.ID, seconds)
  423. // 3. If it doesn't, then send SIGKILL
  424. if err := container.Kill(); err != nil {
  425. container.WaitStop(-1 * time.Second)
  426. return err
  427. }
  428. }
  429. container.LogEvent("stop")
  430. return nil
  431. }
  432. func (container *Container) Restart(seconds int) error {
  433. // Avoid unnecessarily unmounting and then directly mounting
  434. // the container when the container stops and then starts
  435. // again
  436. if err := container.Mount(); err == nil {
  437. defer container.Unmount()
  438. }
  439. if err := container.Stop(seconds); err != nil {
  440. return err
  441. }
  442. if err := container.Start(); err != nil {
  443. return err
  444. }
  445. container.LogEvent("restart")
  446. return nil
  447. }
  448. func (container *Container) Resize(h, w int) error {
  449. if !container.IsRunning() {
  450. return fmt.Errorf("Cannot resize container %s, container is not running", container.ID)
  451. }
  452. if err := container.command.ProcessConfig.Terminal.Resize(h, w); err != nil {
  453. return err
  454. }
  455. container.LogEvent("resize")
  456. return nil
  457. }
  458. func (container *Container) Export() (archive.Archive, error) {
  459. if err := container.Mount(); err != nil {
  460. return nil, err
  461. }
  462. archive, err := archive.Tar(container.basefs, archive.Uncompressed)
  463. if err != nil {
  464. container.Unmount()
  465. return nil, err
  466. }
  467. arch := ioutils.NewReadCloserWrapper(archive, func() error {
  468. err := archive.Close()
  469. container.Unmount()
  470. return err
  471. })
  472. container.LogEvent("export")
  473. return arch, err
  474. }
  475. func (container *Container) Mount() error {
  476. return container.daemon.Mount(container)
  477. }
  478. func (container *Container) changes() ([]archive.Change, error) {
  479. return container.daemon.Changes(container)
  480. }
  481. func (container *Container) Changes() ([]archive.Change, error) {
  482. container.Lock()
  483. defer container.Unlock()
  484. return container.changes()
  485. }
  486. func (container *Container) GetImage() (*image.Image, error) {
  487. if container.daemon == nil {
  488. return nil, fmt.Errorf("Can't get image of unregistered container")
  489. }
  490. return container.daemon.graph.Get(container.ImageID)
  491. }
  492. func (container *Container) Unmount() error {
  493. return container.daemon.Unmount(container)
  494. }
  495. func (container *Container) hostConfigPath() (string, error) {
  496. return container.GetRootResourcePath("hostconfig.json")
  497. }
  498. func (container *Container) jsonPath() (string, error) {
  499. return container.GetRootResourcePath("config.json")
  500. }
  501. // This method must be exported to be used from the lxc template
  502. // This directory is only usable when the container is running
  503. func (container *Container) RootfsPath() string {
  504. return container.basefs
  505. }
  506. func validateID(id string) error {
  507. if id == "" {
  508. return fmt.Errorf("Invalid empty id")
  509. }
  510. return nil
  511. }
  512. func (container *Container) Copy(resource string) (io.ReadCloser, error) {
  513. container.Lock()
  514. defer container.Unlock()
  515. var err error
  516. if err := container.Mount(); err != nil {
  517. return nil, err
  518. }
  519. defer func() {
  520. if err != nil {
  521. // unmount any volumes
  522. container.UnmountVolumes(true)
  523. // unmount the container's rootfs
  524. container.Unmount()
  525. }
  526. }()
  527. mounts, err := container.setupMounts()
  528. if err != nil {
  529. return nil, err
  530. }
  531. for _, m := range mounts {
  532. var dest string
  533. dest, err = container.GetResourcePath(m.Destination)
  534. if err != nil {
  535. return nil, err
  536. }
  537. var stat os.FileInfo
  538. stat, err = os.Stat(m.Source)
  539. if err != nil {
  540. return nil, err
  541. }
  542. if err = fileutils.CreateIfNotExists(dest, stat.IsDir()); err != nil {
  543. return nil, err
  544. }
  545. if err = mount.Mount(m.Source, dest, "bind", "rbind,ro"); err != nil {
  546. return nil, err
  547. }
  548. }
  549. basePath, err := container.GetResourcePath(resource)
  550. if err != nil {
  551. return nil, err
  552. }
  553. stat, err := os.Stat(basePath)
  554. if err != nil {
  555. return nil, err
  556. }
  557. var filter []string
  558. if !stat.IsDir() {
  559. d, f := filepath.Split(basePath)
  560. basePath = d
  561. filter = []string{f}
  562. } else {
  563. filter = []string{filepath.Base(basePath)}
  564. basePath = filepath.Dir(basePath)
  565. }
  566. archive, err := archive.TarWithOptions(basePath, &archive.TarOptions{
  567. Compression: archive.Uncompressed,
  568. IncludeFiles: filter,
  569. })
  570. if err != nil {
  571. return nil, err
  572. }
  573. if err := container.PrepareStorage(); err != nil {
  574. container.Unmount()
  575. return nil, err
  576. }
  577. reader := ioutils.NewReadCloserWrapper(archive, func() error {
  578. err := archive.Close()
  579. container.CleanupStorage()
  580. container.UnmountVolumes(true)
  581. container.Unmount()
  582. return err
  583. })
  584. container.LogEvent("copy")
  585. return reader, nil
  586. }
  587. // Returns true if the container exposes a certain port
  588. func (container *Container) Exposes(p nat.Port) bool {
  589. _, exists := container.Config.ExposedPorts[p]
  590. return exists
  591. }
  592. func (container *Container) HostConfig() *runconfig.HostConfig {
  593. return container.hostConfig
  594. }
  595. func (container *Container) SetHostConfig(hostConfig *runconfig.HostConfig) {
  596. container.hostConfig = hostConfig
  597. }
  598. func (container *Container) getLogConfig() runconfig.LogConfig {
  599. cfg := container.hostConfig.LogConfig
  600. if cfg.Type != "" || len(cfg.Config) > 0 { // container has log driver configured
  601. if cfg.Type == "" {
  602. cfg.Type = jsonfilelog.Name
  603. }
  604. return cfg
  605. }
  606. // Use daemon's default log config for containers
  607. return container.daemon.defaultLogConfig
  608. }
  609. func (container *Container) getLogger() (logger.Logger, error) {
  610. if container.logDriver != nil && container.IsRunning() {
  611. return container.logDriver, nil
  612. }
  613. cfg := container.getLogConfig()
  614. if err := logger.ValidateLogOpts(cfg.Type, cfg.Config); err != nil {
  615. return nil, err
  616. }
  617. c, err := logger.GetLogDriver(cfg.Type)
  618. if err != nil {
  619. return nil, fmt.Errorf("Failed to get logging factory: %v", err)
  620. }
  621. ctx := logger.Context{
  622. Config: cfg.Config,
  623. ContainerID: container.ID,
  624. ContainerName: container.Name,
  625. ContainerEntrypoint: container.Path,
  626. ContainerArgs: container.Args,
  627. ContainerImageID: container.ImageID,
  628. ContainerImageName: container.Config.Image,
  629. ContainerCreated: container.Created,
  630. }
  631. // Set logging file for "json-logger"
  632. if cfg.Type == jsonfilelog.Name {
  633. ctx.LogPath, err = container.GetRootResourcePath(fmt.Sprintf("%s-json.log", container.ID))
  634. if err != nil {
  635. return nil, err
  636. }
  637. }
  638. return c(ctx)
  639. }
  640. func (container *Container) startLogging() error {
  641. cfg := container.getLogConfig()
  642. if cfg.Type == "none" {
  643. return nil // do not start logging routines
  644. }
  645. l, err := container.getLogger()
  646. if err != nil {
  647. return fmt.Errorf("Failed to initialize logging driver: %v", err)
  648. }
  649. copier, err := logger.NewCopier(container.ID, map[string]io.Reader{"stdout": container.StdoutPipe(), "stderr": container.StderrPipe()}, l)
  650. if err != nil {
  651. return err
  652. }
  653. container.logCopier = copier
  654. copier.Run()
  655. container.logDriver = l
  656. // set LogPath field only for json-file logdriver
  657. if jl, ok := l.(*jsonfilelog.JSONFileLogger); ok {
  658. container.LogPath = jl.LogPath()
  659. }
  660. return nil
  661. }
  662. func (container *Container) waitForStart() error {
  663. container.monitor = newContainerMonitor(container, container.hostConfig.RestartPolicy)
  664. // block until we either receive an error from the initial start of the container's
  665. // process or until the process is running in the container
  666. select {
  667. case <-container.monitor.startSignal:
  668. case err := <-promise.Go(container.monitor.Start):
  669. return err
  670. }
  671. return nil
  672. }
  673. func (container *Container) GetProcessLabel() string {
  674. // even if we have a process label return "" if we are running
  675. // in privileged mode
  676. if container.hostConfig.Privileged {
  677. return ""
  678. }
  679. return container.ProcessLabel
  680. }
  681. func (container *Container) GetMountLabel() string {
  682. if container.hostConfig.Privileged {
  683. return ""
  684. }
  685. return container.MountLabel
  686. }
  687. func (container *Container) Stats() (*execdriver.ResourceStats, error) {
  688. return container.daemon.Stats(container)
  689. }
  690. func (c *Container) LogDriverType() string {
  691. c.Lock()
  692. defer c.Unlock()
  693. if c.hostConfig.LogConfig.Type == "" {
  694. return c.daemon.defaultLogConfig.Type
  695. }
  696. return c.hostConfig.LogConfig.Type
  697. }
  698. func (container *Container) GetExecIDs() []string {
  699. return container.execCommands.List()
  700. }
  701. func (container *Container) Exec(execConfig *execConfig) error {
  702. container.Lock()
  703. defer container.Unlock()
  704. waitStart := make(chan struct{})
  705. callback := func(processConfig *execdriver.ProcessConfig, pid int) {
  706. if processConfig.Tty {
  707. // The callback is called after the process Start()
  708. // so we are in the parent process. In TTY mode, stdin/out/err is the PtySlave
  709. // which we close here.
  710. if c, ok := processConfig.Stdout.(io.Closer); ok {
  711. c.Close()
  712. }
  713. }
  714. close(waitStart)
  715. }
  716. // We use a callback here instead of a goroutine and an chan for
  717. // syncronization purposes
  718. cErr := promise.Go(func() error { return container.monitorExec(execConfig, callback) })
  719. // Exec should not return until the process is actually running
  720. select {
  721. case <-waitStart:
  722. case err := <-cErr:
  723. return err
  724. }
  725. return nil
  726. }
  727. func (container *Container) monitorExec(execConfig *execConfig, callback execdriver.StartCallback) error {
  728. var (
  729. err error
  730. exitCode int
  731. )
  732. pipes := execdriver.NewPipes(execConfig.StreamConfig.stdin, execConfig.StreamConfig.stdout, execConfig.StreamConfig.stderr, execConfig.OpenStdin)
  733. exitCode, err = container.daemon.Exec(container, execConfig, pipes, callback)
  734. if err != nil {
  735. logrus.Errorf("Error running command in existing container %s: %s", container.ID, err)
  736. }
  737. logrus.Debugf("Exec task in container %s exited with code %d", container.ID, exitCode)
  738. if execConfig.OpenStdin {
  739. if err := execConfig.StreamConfig.stdin.Close(); err != nil {
  740. logrus.Errorf("Error closing stdin while running in %s: %s", container.ID, err)
  741. }
  742. }
  743. if err := execConfig.StreamConfig.stdout.Clean(); err != nil {
  744. logrus.Errorf("Error closing stdout while running in %s: %s", container.ID, err)
  745. }
  746. if err := execConfig.StreamConfig.stderr.Clean(); err != nil {
  747. logrus.Errorf("Error closing stderr while running in %s: %s", container.ID, err)
  748. }
  749. if execConfig.ProcessConfig.Terminal != nil {
  750. if err := execConfig.ProcessConfig.Terminal.Close(); err != nil {
  751. logrus.Errorf("Error closing terminal while running in container %s: %s", container.ID, err)
  752. }
  753. }
  754. // remove the exec command from the container's store only and not the
  755. // daemon's store so that the exec command can be inspected.
  756. container.execCommands.Delete(execConfig.ID)
  757. return err
  758. }
  759. func (c *Container) Attach(stdin io.ReadCloser, stdout io.Writer, stderr io.Writer) chan error {
  760. return attach(&c.StreamConfig, c.Config.OpenStdin, c.Config.StdinOnce, c.Config.Tty, stdin, stdout, stderr)
  761. }
  762. func (c *Container) AttachWithLogs(stdin io.ReadCloser, stdout, stderr io.Writer, logs, stream bool) error {
  763. if logs {
  764. logDriver, err := c.getLogger()
  765. if err != nil {
  766. return err
  767. }
  768. cLog, ok := logDriver.(logger.LogReader)
  769. if !ok {
  770. return logger.ErrReadLogsNotSupported
  771. }
  772. logs := cLog.ReadLogs(logger.ReadConfig{Tail: -1})
  773. LogLoop:
  774. for {
  775. select {
  776. case msg, ok := <-logs.Msg:
  777. if !ok {
  778. break LogLoop
  779. }
  780. if msg.Source == "stdout" && stdout != nil {
  781. stdout.Write(msg.Line)
  782. }
  783. if msg.Source == "stderr" && stderr != nil {
  784. stderr.Write(msg.Line)
  785. }
  786. case err := <-logs.Err:
  787. logrus.Errorf("Error streaming logs: %v", err)
  788. break LogLoop
  789. }
  790. }
  791. }
  792. c.LogEvent("attach")
  793. //stream
  794. if stream {
  795. var stdinPipe io.ReadCloser
  796. if stdin != nil {
  797. r, w := io.Pipe()
  798. go func() {
  799. defer w.Close()
  800. defer logrus.Debugf("Closing buffered stdin pipe")
  801. io.Copy(w, stdin)
  802. }()
  803. stdinPipe = r
  804. }
  805. <-c.Attach(stdinPipe, stdout, stderr)
  806. // If we are in stdinonce mode, wait for the process to end
  807. // otherwise, simply return
  808. if c.Config.StdinOnce && !c.Config.Tty {
  809. c.WaitStop(-1 * time.Second)
  810. }
  811. }
  812. return nil
  813. }
  814. func attach(streamConfig *StreamConfig, openStdin, stdinOnce, tty bool, stdin io.ReadCloser, stdout io.Writer, stderr io.Writer) chan error {
  815. var (
  816. cStdout, cStderr io.ReadCloser
  817. cStdin io.WriteCloser
  818. wg sync.WaitGroup
  819. errors = make(chan error, 3)
  820. )
  821. if stdin != nil && openStdin {
  822. cStdin = streamConfig.StdinPipe()
  823. wg.Add(1)
  824. }
  825. if stdout != nil {
  826. cStdout = streamConfig.StdoutPipe()
  827. wg.Add(1)
  828. }
  829. if stderr != nil {
  830. cStderr = streamConfig.StderrPipe()
  831. wg.Add(1)
  832. }
  833. // Connect stdin of container to the http conn.
  834. go func() {
  835. if stdin == nil || !openStdin {
  836. return
  837. }
  838. logrus.Debugf("attach: stdin: begin")
  839. defer func() {
  840. if stdinOnce && !tty {
  841. cStdin.Close()
  842. } else {
  843. // No matter what, when stdin is closed (io.Copy unblock), close stdout and stderr
  844. if cStdout != nil {
  845. cStdout.Close()
  846. }
  847. if cStderr != nil {
  848. cStderr.Close()
  849. }
  850. }
  851. wg.Done()
  852. logrus.Debugf("attach: stdin: end")
  853. }()
  854. var err error
  855. if tty {
  856. _, err = copyEscapable(cStdin, stdin)
  857. } else {
  858. _, err = io.Copy(cStdin, stdin)
  859. }
  860. if err == io.ErrClosedPipe {
  861. err = nil
  862. }
  863. if err != nil {
  864. logrus.Errorf("attach: stdin: %s", err)
  865. errors <- err
  866. return
  867. }
  868. }()
  869. attachStream := func(name string, stream io.Writer, streamPipe io.ReadCloser) {
  870. if stream == nil {
  871. return
  872. }
  873. defer func() {
  874. // Make sure stdin gets closed
  875. if stdin != nil {
  876. stdin.Close()
  877. }
  878. streamPipe.Close()
  879. wg.Done()
  880. logrus.Debugf("attach: %s: end", name)
  881. }()
  882. logrus.Debugf("attach: %s: begin", name)
  883. _, err := io.Copy(stream, streamPipe)
  884. if err == io.ErrClosedPipe {
  885. err = nil
  886. }
  887. if err != nil {
  888. logrus.Errorf("attach: %s: %v", name, err)
  889. errors <- err
  890. }
  891. }
  892. go attachStream("stdout", stdout, cStdout)
  893. go attachStream("stderr", stderr, cStderr)
  894. return promise.Go(func() error {
  895. wg.Wait()
  896. close(errors)
  897. for err := range errors {
  898. if err != nil {
  899. return err
  900. }
  901. }
  902. return nil
  903. })
  904. }
  905. // Code c/c from io.Copy() modified to handle escape sequence
  906. func copyEscapable(dst io.Writer, src io.ReadCloser) (written int64, err error) {
  907. buf := make([]byte, 32*1024)
  908. for {
  909. nr, er := src.Read(buf)
  910. if nr > 0 {
  911. // ---- Docker addition
  912. // char 16 is C-p
  913. if nr == 1 && buf[0] == 16 {
  914. nr, er = src.Read(buf)
  915. // char 17 is C-q
  916. if nr == 1 && buf[0] == 17 {
  917. if err := src.Close(); err != nil {
  918. return 0, err
  919. }
  920. return 0, nil
  921. }
  922. }
  923. // ---- End of docker
  924. nw, ew := dst.Write(buf[0:nr])
  925. if nw > 0 {
  926. written += int64(nw)
  927. }
  928. if ew != nil {
  929. err = ew
  930. break
  931. }
  932. if nr != nw {
  933. err = io.ErrShortWrite
  934. break
  935. }
  936. }
  937. if er == io.EOF {
  938. break
  939. }
  940. if er != nil {
  941. err = er
  942. break
  943. }
  944. }
  945. return written, err
  946. }
  947. func (container *Container) networkMounts() []execdriver.Mount {
  948. var mounts []execdriver.Mount
  949. if container.ResolvConfPath != "" {
  950. label.SetFileLabel(container.ResolvConfPath, container.MountLabel)
  951. mounts = append(mounts, execdriver.Mount{
  952. Source: container.ResolvConfPath,
  953. Destination: "/etc/resolv.conf",
  954. Writable: !container.hostConfig.ReadonlyRootfs,
  955. Private: true,
  956. })
  957. }
  958. if container.HostnamePath != "" {
  959. label.SetFileLabel(container.HostnamePath, container.MountLabel)
  960. mounts = append(mounts, execdriver.Mount{
  961. Source: container.HostnamePath,
  962. Destination: "/etc/hostname",
  963. Writable: !container.hostConfig.ReadonlyRootfs,
  964. Private: true,
  965. })
  966. }
  967. if container.HostsPath != "" {
  968. label.SetFileLabel(container.HostsPath, container.MountLabel)
  969. mounts = append(mounts, execdriver.Mount{
  970. Source: container.HostsPath,
  971. Destination: "/etc/hosts",
  972. Writable: !container.hostConfig.ReadonlyRootfs,
  973. Private: true,
  974. })
  975. }
  976. return mounts
  977. }
  978. func (container *Container) addBindMountPoint(name, source, destination string, rw bool) {
  979. container.MountPoints[destination] = &mountPoint{
  980. Name: name,
  981. Source: source,
  982. Destination: destination,
  983. RW: rw,
  984. }
  985. }
  986. func (container *Container) addLocalMountPoint(name, destination string, rw bool) {
  987. container.MountPoints[destination] = &mountPoint{
  988. Name: name,
  989. Driver: volume.DefaultDriverName,
  990. Destination: destination,
  991. RW: rw,
  992. }
  993. }
  994. func (container *Container) addMountPointWithVolume(destination string, vol volume.Volume, rw bool) {
  995. container.MountPoints[destination] = &mountPoint{
  996. Name: vol.Name(),
  997. Driver: vol.DriverName(),
  998. Destination: destination,
  999. RW: rw,
  1000. Volume: vol,
  1001. }
  1002. }
  1003. func (container *Container) isDestinationMounted(destination string) bool {
  1004. return container.MountPoints[destination] != nil
  1005. }
  1006. func (container *Container) prepareMountPoints() error {
  1007. for _, config := range container.MountPoints {
  1008. if len(config.Driver) > 0 {
  1009. v, err := createVolume(config.Name, config.Driver)
  1010. if err != nil {
  1011. return err
  1012. }
  1013. config.Volume = v
  1014. }
  1015. }
  1016. return nil
  1017. }
  1018. func (container *Container) removeMountPoints() error {
  1019. for _, m := range container.MountPoints {
  1020. if m.Volume != nil {
  1021. if err := removeVolume(m.Volume); err != nil {
  1022. return err
  1023. }
  1024. }
  1025. }
  1026. return nil
  1027. }
  1028. func (container *Container) shouldRestart() bool {
  1029. return container.hostConfig.RestartPolicy.Name == "always" ||
  1030. (container.hostConfig.RestartPolicy.Name == "on-failure" && container.ExitCode != 0)
  1031. }
  1032. func (container *Container) copyImagePathContent(v volume.Volume, destination string) error {
  1033. rootfs, err := symlink.FollowSymlinkInScope(filepath.Join(container.basefs, destination), container.basefs)
  1034. if err != nil {
  1035. return err
  1036. }
  1037. if _, err = ioutil.ReadDir(rootfs); err != nil {
  1038. if os.IsNotExist(err) {
  1039. return nil
  1040. }
  1041. return err
  1042. }
  1043. path, err := v.Mount()
  1044. if err != nil {
  1045. return err
  1046. }
  1047. if err := copyExistingContents(rootfs, path); err != nil {
  1048. return err
  1049. }
  1050. return v.Unmount()
  1051. }