container.go 29 KB

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