container.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917
  1. package daemon
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "os"
  8. "path/filepath"
  9. "strings"
  10. "sync"
  11. "syscall"
  12. "time"
  13. "github.com/opencontainers/runc/libcontainer/label"
  14. "github.com/Sirupsen/logrus"
  15. "github.com/docker/docker/daemon/execdriver"
  16. "github.com/docker/docker/daemon/logger"
  17. "github.com/docker/docker/daemon/logger/jsonfilelog"
  18. "github.com/docker/docker/daemon/network"
  19. derr "github.com/docker/docker/errors"
  20. "github.com/docker/docker/pkg/archive"
  21. "github.com/docker/docker/pkg/broadcaster"
  22. "github.com/docker/docker/pkg/fileutils"
  23. "github.com/docker/docker/pkg/ioutils"
  24. "github.com/docker/docker/pkg/mount"
  25. "github.com/docker/docker/pkg/nat"
  26. "github.com/docker/docker/pkg/promise"
  27. "github.com/docker/docker/pkg/signal"
  28. "github.com/docker/docker/pkg/symlink"
  29. "github.com/docker/docker/pkg/system"
  30. "github.com/docker/docker/runconfig"
  31. "github.com/docker/docker/volume"
  32. "github.com/docker/docker/volume/store"
  33. )
  34. var (
  35. // ErrRootFSReadOnly is returned when a container
  36. // rootfs is marked readonly.
  37. ErrRootFSReadOnly = errors.New("container rootfs is marked read-only")
  38. )
  39. type streamConfig struct {
  40. stdout *broadcaster.Unbuffered
  41. stderr *broadcaster.Unbuffered
  42. stdin io.ReadCloser
  43. stdinPipe io.WriteCloser
  44. }
  45. // CommonContainer holds the fields for a container which are
  46. // applicable across all platforms supported by the daemon.
  47. type CommonContainer struct {
  48. streamConfig
  49. // embed for Container to support states directly.
  50. *State `json:"State"` // Needed for remote api version <= 1.11
  51. root string // Path to the "home" of the container, including metadata.
  52. basefs string // Path to the graphdriver mountpoint
  53. ID string
  54. Created time.Time
  55. Path string
  56. Args []string
  57. Config *runconfig.Config
  58. ImageID string `json:"Image"`
  59. NetworkSettings *network.Settings
  60. LogPath string
  61. Name string
  62. Driver string
  63. ExecDriver string
  64. // MountLabel contains the options for the 'mount' command
  65. MountLabel string
  66. ProcessLabel string
  67. RestartCount int
  68. HasBeenStartedBefore bool
  69. HasBeenManuallyStopped bool // used for unless-stopped restart policy
  70. MountPoints map[string]*volume.MountPoint
  71. hostConfig *runconfig.HostConfig
  72. command *execdriver.Command
  73. monitor *containerMonitor
  74. execCommands *execStore
  75. daemon *Daemon
  76. // logDriver for closing
  77. logDriver logger.Logger
  78. logCopier *logger.Copier
  79. }
  80. func (container *Container) fromDisk() error {
  81. pth, err := container.jsonPath()
  82. if err != nil {
  83. return err
  84. }
  85. jsonSource, err := os.Open(pth)
  86. if err != nil {
  87. return err
  88. }
  89. defer jsonSource.Close()
  90. dec := json.NewDecoder(jsonSource)
  91. // Load container settings
  92. if err := dec.Decode(container); err != nil {
  93. return err
  94. }
  95. if err := label.ReserveLabel(container.ProcessLabel); err != nil {
  96. return err
  97. }
  98. return container.readHostConfig()
  99. }
  100. func (container *Container) toDisk() error {
  101. pth, err := container.jsonPath()
  102. if err != nil {
  103. return err
  104. }
  105. jsonSource, err := os.Create(pth)
  106. if err != nil {
  107. return err
  108. }
  109. defer jsonSource.Close()
  110. enc := json.NewEncoder(jsonSource)
  111. // Save container settings
  112. if err := enc.Encode(container); err != nil {
  113. return err
  114. }
  115. return container.writeHostConfig()
  116. }
  117. func (container *Container) toDiskLocking() error {
  118. container.Lock()
  119. err := container.toDisk()
  120. container.Unlock()
  121. return err
  122. }
  123. func (container *Container) readHostConfig() error {
  124. container.hostConfig = &runconfig.HostConfig{}
  125. // If the hostconfig file does not exist, do not read it.
  126. // (We still have to initialize container.hostConfig,
  127. // but that's OK, since we just did that above.)
  128. pth, err := container.hostConfigPath()
  129. if err != nil {
  130. return err
  131. }
  132. f, err := os.Open(pth)
  133. if err != nil {
  134. if os.IsNotExist(err) {
  135. return nil
  136. }
  137. return err
  138. }
  139. defer f.Close()
  140. return json.NewDecoder(f).Decode(&container.hostConfig)
  141. }
  142. func (container *Container) writeHostConfig() error {
  143. pth, err := container.hostConfigPath()
  144. if err != nil {
  145. return err
  146. }
  147. f, err := os.Create(pth)
  148. if err != nil {
  149. return err
  150. }
  151. defer f.Close()
  152. return json.NewEncoder(f).Encode(&container.hostConfig)
  153. }
  154. func (container *Container) logEvent(action string) {
  155. d := container.daemon
  156. d.EventsService.Log(
  157. action,
  158. container.ID,
  159. container.Config.Image,
  160. )
  161. }
  162. // GetResourcePath evaluates `path` in the scope of the container's basefs, with proper path
  163. // sanitisation. Symlinks are all scoped to the basefs of the container, as
  164. // though the container's basefs was `/`.
  165. //
  166. // The basefs of a container is the host-facing path which is bind-mounted as
  167. // `/` inside the container. This method is essentially used to access a
  168. // particular path inside the container as though you were a process in that
  169. // container.
  170. //
  171. // NOTE: The returned path is *only* safely scoped inside the container's basefs
  172. // if no component of the returned path changes (such as a component
  173. // symlinking to a different path) between using this method and using the
  174. // path. See symlink.FollowSymlinkInScope for more details.
  175. func (container *Container) GetResourcePath(path string) (string, error) {
  176. // IMPORTANT - These are paths on the OS where the daemon is running, hence
  177. // any filepath operations must be done in an OS agnostic way.
  178. cleanPath := filepath.Join(string(os.PathSeparator), path)
  179. r, e := symlink.FollowSymlinkInScope(filepath.Join(container.basefs, cleanPath), container.basefs)
  180. return r, e
  181. }
  182. // Evaluates `path` in the scope of the container's root, with proper path
  183. // sanitisation. Symlinks are all scoped to the root of the container, as
  184. // though the container's root was `/`.
  185. //
  186. // The root of a container is the host-facing configuration metadata directory.
  187. // Only use this method to safely access the container's `container.json` or
  188. // other metadata files. If in doubt, use container.GetResourcePath.
  189. //
  190. // NOTE: The returned path is *only* safely scoped inside the container's root
  191. // if no component of the returned path changes (such as a component
  192. // symlinking to a different path) between using this method and using the
  193. // path. See symlink.FollowSymlinkInScope for more details.
  194. func (container *Container) getRootResourcePath(path string) (string, error) {
  195. // IMPORTANT - These are paths on the OS where the daemon is running, hence
  196. // any filepath operations must be done in an OS agnostic way.
  197. cleanPath := filepath.Join(string(os.PathSeparator), path)
  198. return symlink.FollowSymlinkInScope(filepath.Join(container.root, cleanPath), container.root)
  199. }
  200. // streamConfig.StdinPipe returns a WriteCloser which can be used to feed data
  201. // to the standard input of the container's active process.
  202. // Container.StdoutPipe and Container.StderrPipe each return a ReadCloser
  203. // which can be used to retrieve the standard output (and error) generated
  204. // by the container's active process. The output (and error) are actually
  205. // copied and delivered to all StdoutPipe and StderrPipe consumers, using
  206. // a kind of "broadcaster".
  207. func (streamConfig *streamConfig) StdinPipe() io.WriteCloser {
  208. return streamConfig.stdinPipe
  209. }
  210. func (streamConfig *streamConfig) StdoutPipe() io.ReadCloser {
  211. reader, writer := io.Pipe()
  212. streamConfig.stdout.Add(writer)
  213. return ioutils.NewBufReader(reader)
  214. }
  215. func (streamConfig *streamConfig) StderrPipe() io.ReadCloser {
  216. reader, writer := io.Pipe()
  217. streamConfig.stderr.Add(writer)
  218. return ioutils.NewBufReader(reader)
  219. }
  220. // cleanup releases any network resources allocated to the container along with any rules
  221. // around how containers are linked together. It also unmounts the container's root filesystem.
  222. func (container *Container) cleanup() {
  223. container.releaseNetwork()
  224. container.unmountIpcMounts(detachMounted)
  225. container.daemon.conditionalUnmountOnCleanup(container)
  226. for _, eConfig := range container.execCommands.s {
  227. container.daemon.unregisterExecCommand(eConfig)
  228. }
  229. if err := container.unmountVolumes(false); err != nil {
  230. logrus.Warnf("%s cleanup: Failed to umount volumes: %v", container.ID, err)
  231. }
  232. }
  233. // ExitOnNext signals to the monitor that it should not restart the container
  234. // after we send the kill signal.
  235. func (container *Container) ExitOnNext() {
  236. container.monitor.ExitOnNext()
  237. }
  238. // Resize changes the TTY of the process running inside the container
  239. // to the given height and width. The container must be running.
  240. func (container *Container) Resize(h, w int) error {
  241. if !container.IsRunning() {
  242. return derr.ErrorCodeNotRunning.WithArgs(container.ID)
  243. }
  244. if err := container.command.ProcessConfig.Terminal.Resize(h, w); err != nil {
  245. return err
  246. }
  247. container.logEvent("resize")
  248. return nil
  249. }
  250. func (container *Container) hostConfigPath() (string, error) {
  251. return container.getRootResourcePath("hostconfig.json")
  252. }
  253. func (container *Container) jsonPath() (string, error) {
  254. return container.getRootResourcePath("config.json")
  255. }
  256. // This method must be exported to be used from the lxc template
  257. // This directory is only usable when the container is running
  258. func (container *Container) rootfsPath() string {
  259. return container.basefs
  260. }
  261. func validateID(id string) error {
  262. if id == "" {
  263. return derr.ErrorCodeEmptyID
  264. }
  265. return nil
  266. }
  267. func (daemon *Daemon) containerCopy(container *Container, resource string) (rc io.ReadCloser, err error) {
  268. container.Lock()
  269. defer func() {
  270. if err != nil {
  271. // Wait to unlock the container until the archive is fully read
  272. // (see the ReadCloseWrapper func below) or if there is an error
  273. // before that occurs.
  274. container.Unlock()
  275. }
  276. }()
  277. if err := daemon.Mount(container); err != nil {
  278. return nil, err
  279. }
  280. defer func() {
  281. if err != nil {
  282. // unmount any volumes
  283. container.unmountVolumes(true)
  284. // unmount the container's rootfs
  285. daemon.Unmount(container)
  286. }
  287. }()
  288. if err := container.mountVolumes(); err != nil {
  289. return nil, err
  290. }
  291. basePath, err := container.GetResourcePath(resource)
  292. if err != nil {
  293. return nil, err
  294. }
  295. stat, err := os.Stat(basePath)
  296. if err != nil {
  297. return nil, err
  298. }
  299. var filter []string
  300. if !stat.IsDir() {
  301. d, f := filepath.Split(basePath)
  302. basePath = d
  303. filter = []string{f}
  304. } else {
  305. filter = []string{filepath.Base(basePath)}
  306. basePath = filepath.Dir(basePath)
  307. }
  308. archive, err := archive.TarWithOptions(basePath, &archive.TarOptions{
  309. Compression: archive.Uncompressed,
  310. IncludeFiles: filter,
  311. })
  312. if err != nil {
  313. return nil, err
  314. }
  315. reader := ioutils.NewReadCloserWrapper(archive, func() error {
  316. err := archive.Close()
  317. container.unmountVolumes(true)
  318. daemon.Unmount(container)
  319. container.Unlock()
  320. return err
  321. })
  322. daemon.logContainerEvent(container, "copy")
  323. return reader, nil
  324. }
  325. // Returns true if the container exposes a certain port
  326. func (container *Container) exposes(p nat.Port) bool {
  327. _, exists := container.Config.ExposedPorts[p]
  328. return exists
  329. }
  330. func (container *Container) getLogConfig() runconfig.LogConfig {
  331. cfg := container.hostConfig.LogConfig
  332. if cfg.Type != "" || len(cfg.Config) > 0 { // container has log driver configured
  333. if cfg.Type == "" {
  334. cfg.Type = jsonfilelog.Name
  335. }
  336. return cfg
  337. }
  338. // Use daemon's default log config for containers
  339. return container.daemon.defaultLogConfig
  340. }
  341. func (container *Container) getLogger() (logger.Logger, error) {
  342. if container.logDriver != nil && container.IsRunning() {
  343. return container.logDriver, nil
  344. }
  345. cfg := container.getLogConfig()
  346. if err := logger.ValidateLogOpts(cfg.Type, cfg.Config); err != nil {
  347. return nil, err
  348. }
  349. c, err := logger.GetLogDriver(cfg.Type)
  350. if err != nil {
  351. return nil, derr.ErrorCodeLoggingFactory.WithArgs(err)
  352. }
  353. ctx := logger.Context{
  354. Config: cfg.Config,
  355. ContainerID: container.ID,
  356. ContainerName: container.Name,
  357. ContainerEntrypoint: container.Path,
  358. ContainerArgs: container.Args,
  359. ContainerImageID: container.ImageID,
  360. ContainerImageName: container.Config.Image,
  361. ContainerCreated: container.Created,
  362. ContainerEnv: container.Config.Env,
  363. ContainerLabels: container.Config.Labels,
  364. }
  365. // Set logging file for "json-logger"
  366. if cfg.Type == jsonfilelog.Name {
  367. ctx.LogPath, err = container.getRootResourcePath(fmt.Sprintf("%s-json.log", container.ID))
  368. if err != nil {
  369. return nil, err
  370. }
  371. }
  372. return c(ctx)
  373. }
  374. func (container *Container) startLogging() error {
  375. cfg := container.getLogConfig()
  376. if cfg.Type == "none" {
  377. return nil // do not start logging routines
  378. }
  379. l, err := container.getLogger()
  380. if err != nil {
  381. return derr.ErrorCodeInitLogger.WithArgs(err)
  382. }
  383. copier := logger.NewCopier(container.ID, map[string]io.Reader{"stdout": container.StdoutPipe(), "stderr": container.StderrPipe()}, l)
  384. container.logCopier = copier
  385. copier.Run()
  386. container.logDriver = l
  387. // set LogPath field only for json-file logdriver
  388. if jl, ok := l.(*jsonfilelog.JSONFileLogger); ok {
  389. container.LogPath = jl.LogPath()
  390. }
  391. return nil
  392. }
  393. func (container *Container) waitForStart() error {
  394. container.monitor = newContainerMonitor(container, container.hostConfig.RestartPolicy)
  395. // block until we either receive an error from the initial start of the container's
  396. // process or until the process is running in the container
  397. select {
  398. case <-container.monitor.startSignal:
  399. case err := <-promise.Go(container.monitor.Start):
  400. return err
  401. }
  402. return nil
  403. }
  404. func (container *Container) getProcessLabel() string {
  405. // even if we have a process label return "" if we are running
  406. // in privileged mode
  407. if container.hostConfig.Privileged {
  408. return ""
  409. }
  410. return container.ProcessLabel
  411. }
  412. func (container *Container) getMountLabel() string {
  413. if container.hostConfig.Privileged {
  414. return ""
  415. }
  416. return container.MountLabel
  417. }
  418. func (container *Container) stats() (*execdriver.ResourceStats, error) {
  419. return container.daemon.stats(container)
  420. }
  421. func (container *Container) getExecIDs() []string {
  422. return container.execCommands.List()
  423. }
  424. func (container *Container) exec(ec *ExecConfig) error {
  425. container.Lock()
  426. defer container.Unlock()
  427. callback := func(processConfig *execdriver.ProcessConfig, pid int, chOOM <-chan struct{}) error {
  428. if processConfig.Tty {
  429. // The callback is called after the process Start()
  430. // so we are in the parent process. In TTY mode, stdin/out/err is the PtySlave
  431. // which we close here.
  432. if c, ok := processConfig.Stdout.(io.Closer); ok {
  433. c.Close()
  434. }
  435. }
  436. close(ec.waitStart)
  437. return nil
  438. }
  439. // We use a callback here instead of a goroutine and an chan for
  440. // synchronization purposes
  441. cErr := promise.Go(func() error { return container.monitorExec(ec, callback) })
  442. // Exec should not return until the process is actually running
  443. select {
  444. case <-ec.waitStart:
  445. case err := <-cErr:
  446. return err
  447. }
  448. return nil
  449. }
  450. func (container *Container) monitorExec(ExecConfig *ExecConfig, callback execdriver.DriverCallback) error {
  451. var (
  452. err error
  453. exitCode int
  454. )
  455. pipes := execdriver.NewPipes(ExecConfig.streamConfig.stdin, ExecConfig.streamConfig.stdout, ExecConfig.streamConfig.stderr, ExecConfig.OpenStdin)
  456. exitCode, err = container.daemon.Exec(container, ExecConfig, pipes, callback)
  457. if err != nil {
  458. logrus.Errorf("Error running command in existing container %s: %s", container.ID, err)
  459. }
  460. logrus.Debugf("Exec task in container %s exited with code %d", container.ID, exitCode)
  461. if ExecConfig.OpenStdin {
  462. if err := ExecConfig.streamConfig.stdin.Close(); err != nil {
  463. logrus.Errorf("Error closing stdin while running in %s: %s", container.ID, err)
  464. }
  465. }
  466. if err := ExecConfig.streamConfig.stdout.Clean(); err != nil {
  467. logrus.Errorf("Error closing stdout while running in %s: %s", container.ID, err)
  468. }
  469. if err := ExecConfig.streamConfig.stderr.Clean(); err != nil {
  470. logrus.Errorf("Error closing stderr while running in %s: %s", container.ID, err)
  471. }
  472. if ExecConfig.ProcessConfig.Terminal != nil {
  473. if err := ExecConfig.ProcessConfig.Terminal.Close(); err != nil {
  474. logrus.Errorf("Error closing terminal while running in container %s: %s", container.ID, err)
  475. }
  476. }
  477. // remove the exec command from the container's store only and not the
  478. // daemon's store so that the exec command can be inspected.
  479. container.execCommands.Delete(ExecConfig.ID)
  480. return err
  481. }
  482. // Attach connects to the container's TTY, delegating to standard
  483. // streams or websockets depending on the configuration.
  484. func (container *Container) Attach(stdin io.ReadCloser, stdout io.Writer, stderr io.Writer) chan error {
  485. return attach(&container.streamConfig, container.Config.OpenStdin, container.Config.StdinOnce, container.Config.Tty, stdin, stdout, stderr)
  486. }
  487. func (container *Container) attachWithLogs(stdin io.ReadCloser, stdout, stderr io.Writer, logs, stream bool) error {
  488. if logs {
  489. logDriver, err := container.getLogger()
  490. if err != nil {
  491. return err
  492. }
  493. cLog, ok := logDriver.(logger.LogReader)
  494. if !ok {
  495. return logger.ErrReadLogsNotSupported
  496. }
  497. logs := cLog.ReadLogs(logger.ReadConfig{Tail: -1})
  498. LogLoop:
  499. for {
  500. select {
  501. case msg, ok := <-logs.Msg:
  502. if !ok {
  503. break LogLoop
  504. }
  505. if msg.Source == "stdout" && stdout != nil {
  506. stdout.Write(msg.Line)
  507. }
  508. if msg.Source == "stderr" && stderr != nil {
  509. stderr.Write(msg.Line)
  510. }
  511. case err := <-logs.Err:
  512. logrus.Errorf("Error streaming logs: %v", err)
  513. break LogLoop
  514. }
  515. }
  516. }
  517. container.logEvent("attach")
  518. //stream
  519. if stream {
  520. var stdinPipe io.ReadCloser
  521. if stdin != nil {
  522. r, w := io.Pipe()
  523. go func() {
  524. defer w.Close()
  525. defer logrus.Debugf("Closing buffered stdin pipe")
  526. io.Copy(w, stdin)
  527. }()
  528. stdinPipe = r
  529. }
  530. <-container.Attach(stdinPipe, stdout, stderr)
  531. // If we are in stdinonce mode, wait for the process to end
  532. // otherwise, simply return
  533. if container.Config.StdinOnce && !container.Config.Tty {
  534. container.WaitStop(-1 * time.Second)
  535. }
  536. }
  537. return nil
  538. }
  539. func attach(streamConfig *streamConfig, openStdin, stdinOnce, tty bool, stdin io.ReadCloser, stdout io.Writer, stderr io.Writer) chan error {
  540. var (
  541. cStdout, cStderr io.ReadCloser
  542. cStdin io.WriteCloser
  543. wg sync.WaitGroup
  544. errors = make(chan error, 3)
  545. )
  546. if stdin != nil && openStdin {
  547. cStdin = streamConfig.StdinPipe()
  548. wg.Add(1)
  549. }
  550. if stdout != nil {
  551. cStdout = streamConfig.StdoutPipe()
  552. wg.Add(1)
  553. }
  554. if stderr != nil {
  555. cStderr = streamConfig.StderrPipe()
  556. wg.Add(1)
  557. }
  558. // Connect stdin of container to the http conn.
  559. go func() {
  560. if stdin == nil || !openStdin {
  561. return
  562. }
  563. logrus.Debugf("attach: stdin: begin")
  564. defer func() {
  565. if stdinOnce && !tty {
  566. cStdin.Close()
  567. } else {
  568. // No matter what, when stdin is closed (io.Copy unblock), close stdout and stderr
  569. if cStdout != nil {
  570. cStdout.Close()
  571. }
  572. if cStderr != nil {
  573. cStderr.Close()
  574. }
  575. }
  576. wg.Done()
  577. logrus.Debugf("attach: stdin: end")
  578. }()
  579. var err error
  580. if tty {
  581. _, err = copyEscapable(cStdin, stdin)
  582. } else {
  583. _, err = io.Copy(cStdin, stdin)
  584. }
  585. if err == io.ErrClosedPipe {
  586. err = nil
  587. }
  588. if err != nil {
  589. logrus.Errorf("attach: stdin: %s", err)
  590. errors <- err
  591. return
  592. }
  593. }()
  594. attachStream := func(name string, stream io.Writer, streamPipe io.ReadCloser) {
  595. if stream == nil {
  596. return
  597. }
  598. defer func() {
  599. // Make sure stdin gets closed
  600. if stdin != nil {
  601. stdin.Close()
  602. }
  603. streamPipe.Close()
  604. wg.Done()
  605. logrus.Debugf("attach: %s: end", name)
  606. }()
  607. logrus.Debugf("attach: %s: begin", name)
  608. _, err := io.Copy(stream, streamPipe)
  609. if err == io.ErrClosedPipe {
  610. err = nil
  611. }
  612. if err != nil {
  613. logrus.Errorf("attach: %s: %v", name, err)
  614. errors <- err
  615. }
  616. }
  617. go attachStream("stdout", stdout, cStdout)
  618. go attachStream("stderr", stderr, cStderr)
  619. return promise.Go(func() error {
  620. wg.Wait()
  621. close(errors)
  622. for err := range errors {
  623. if err != nil {
  624. return err
  625. }
  626. }
  627. return nil
  628. })
  629. }
  630. // Code c/c from io.Copy() modified to handle escape sequence
  631. func copyEscapable(dst io.Writer, src io.ReadCloser) (written int64, err error) {
  632. buf := make([]byte, 32*1024)
  633. for {
  634. nr, er := src.Read(buf)
  635. if nr > 0 {
  636. // ---- Docker addition
  637. // char 16 is C-p
  638. if nr == 1 && buf[0] == 16 {
  639. nr, er = src.Read(buf)
  640. // char 17 is C-q
  641. if nr == 1 && buf[0] == 17 {
  642. if err := src.Close(); err != nil {
  643. return 0, err
  644. }
  645. return 0, nil
  646. }
  647. }
  648. // ---- End of docker
  649. nw, ew := dst.Write(buf[0:nr])
  650. if nw > 0 {
  651. written += int64(nw)
  652. }
  653. if ew != nil {
  654. err = ew
  655. break
  656. }
  657. if nr != nw {
  658. err = io.ErrShortWrite
  659. break
  660. }
  661. }
  662. if er == io.EOF {
  663. break
  664. }
  665. if er != nil {
  666. err = er
  667. break
  668. }
  669. }
  670. return written, err
  671. }
  672. func (container *Container) shouldRestart() bool {
  673. return container.hostConfig.RestartPolicy.Name == "always" ||
  674. (container.hostConfig.RestartPolicy.Name == "unless-stopped" && !container.HasBeenManuallyStopped) ||
  675. (container.hostConfig.RestartPolicy.Name == "on-failure" && container.ExitCode != 0)
  676. }
  677. func (container *Container) mountVolumes() error {
  678. mounts, err := container.setupMounts()
  679. if err != nil {
  680. return err
  681. }
  682. for _, m := range mounts {
  683. dest, err := container.GetResourcePath(m.Destination)
  684. if err != nil {
  685. return err
  686. }
  687. var stat os.FileInfo
  688. stat, err = os.Stat(m.Source)
  689. if err != nil {
  690. return err
  691. }
  692. if err = fileutils.CreateIfNotExists(dest, stat.IsDir()); err != nil {
  693. return err
  694. }
  695. opts := "rbind,ro"
  696. if m.Writable {
  697. opts = "rbind,rw"
  698. }
  699. if err := mount.Mount(m.Source, dest, "bind", opts); err != nil {
  700. return err
  701. }
  702. }
  703. return nil
  704. }
  705. func (container *Container) prepareMountPoints() error {
  706. for _, config := range container.MountPoints {
  707. if len(config.Driver) > 0 {
  708. v, err := container.daemon.createVolume(config.Name, config.Driver, nil)
  709. if err != nil {
  710. return err
  711. }
  712. config.Volume = v
  713. }
  714. }
  715. return nil
  716. }
  717. func (container *Container) removeMountPoints(rm bool) error {
  718. var rmErrors []string
  719. for _, m := range container.MountPoints {
  720. if m.Volume == nil {
  721. continue
  722. }
  723. container.daemon.volumes.Decrement(m.Volume)
  724. if rm {
  725. err := container.daemon.volumes.Remove(m.Volume)
  726. // ErrVolumeInUse is ignored because having this
  727. // volume being referenced by other container is
  728. // not an error, but an implementation detail.
  729. // This prevents docker from logging "ERROR: Volume in use"
  730. // where there is another container using the volume.
  731. if err != nil && err != store.ErrVolumeInUse {
  732. rmErrors = append(rmErrors, err.Error())
  733. }
  734. }
  735. }
  736. if len(rmErrors) > 0 {
  737. return derr.ErrorCodeRemovingVolume.WithArgs(strings.Join(rmErrors, "\n"))
  738. }
  739. return nil
  740. }
  741. func (container *Container) unmountVolumes(forceSyscall bool) error {
  742. var (
  743. volumeMounts []volume.MountPoint
  744. err error
  745. )
  746. for _, mntPoint := range container.MountPoints {
  747. dest, err := container.GetResourcePath(mntPoint.Destination)
  748. if err != nil {
  749. return err
  750. }
  751. volumeMounts = append(volumeMounts, volume.MountPoint{Destination: dest, Volume: mntPoint.Volume})
  752. }
  753. // Append any network mounts to the list (this is a no-op on Windows)
  754. if volumeMounts, err = appendNetworkMounts(container, volumeMounts); err != nil {
  755. return err
  756. }
  757. for _, volumeMount := range volumeMounts {
  758. if forceSyscall {
  759. if err := system.Unmount(volumeMount.Destination); err != nil {
  760. logrus.Warnf("%s unmountVolumes: Failed to force umount %v", container.ID, err)
  761. }
  762. }
  763. if volumeMount.Volume != nil {
  764. if err := volumeMount.Volume.Unmount(); err != nil {
  765. return err
  766. }
  767. }
  768. }
  769. return nil
  770. }
  771. func (container *Container) addBindMountPoint(name, source, destination string, rw bool) {
  772. container.MountPoints[destination] = &volume.MountPoint{
  773. Name: name,
  774. Source: source,
  775. Destination: destination,
  776. RW: rw,
  777. }
  778. }
  779. func (container *Container) addLocalMountPoint(name, destination string, rw bool) {
  780. container.MountPoints[destination] = &volume.MountPoint{
  781. Name: name,
  782. Driver: volume.DefaultDriverName,
  783. Destination: destination,
  784. RW: rw,
  785. }
  786. }
  787. func (container *Container) addMountPointWithVolume(destination string, vol volume.Volume, rw bool) {
  788. container.MountPoints[destination] = &volume.MountPoint{
  789. Name: vol.Name(),
  790. Driver: vol.DriverName(),
  791. Destination: destination,
  792. RW: rw,
  793. Volume: vol,
  794. }
  795. }
  796. func (container *Container) isDestinationMounted(destination string) bool {
  797. return container.MountPoints[destination] != nil
  798. }
  799. func (container *Container) stopSignal() int {
  800. var stopSignal syscall.Signal
  801. if container.Config.StopSignal != "" {
  802. stopSignal, _ = signal.ParseSignal(container.Config.StopSignal)
  803. }
  804. if int(stopSignal) == 0 {
  805. stopSignal, _ = signal.ParseSignal(signal.DefaultStopSignal)
  806. }
  807. return int(stopSignal)
  808. }