container.go 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559
  1. package docker
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "github.com/dotcloud/docker/archive"
  8. "github.com/dotcloud/docker/graphdriver"
  9. "github.com/dotcloud/docker/mount"
  10. "github.com/dotcloud/docker/pkg/term"
  11. "github.com/dotcloud/docker/utils"
  12. "github.com/kr/pty"
  13. "io"
  14. "io/ioutil"
  15. "log"
  16. "net"
  17. "os"
  18. "os/exec"
  19. "path"
  20. "strconv"
  21. "strings"
  22. "sync"
  23. "syscall"
  24. "time"
  25. )
  26. var (
  27. ErrNotATTY = errors.New("The PTY is not a file")
  28. ErrNoTTY = errors.New("No PTY found")
  29. )
  30. type Container struct {
  31. sync.Mutex
  32. root string // Path to the "home" of the container, including metadata.
  33. rootfs string // Path to the root filesystem of the container.
  34. ID string
  35. Created time.Time
  36. Path string
  37. Args []string
  38. Config *Config
  39. State State
  40. Image string
  41. network *NetworkInterface
  42. NetworkSettings *NetworkSettings
  43. ResolvConfPath string
  44. HostnamePath string
  45. HostsPath string
  46. Name string
  47. Driver string
  48. cmd *exec.Cmd
  49. stdout *utils.WriteBroadcaster
  50. stderr *utils.WriteBroadcaster
  51. stdin io.ReadCloser
  52. stdinPipe io.WriteCloser
  53. ptyMaster io.Closer
  54. runtime *Runtime
  55. waitLock chan struct{}
  56. Volumes map[string]string
  57. // Store rw/ro in a separate structure to preserve reverse-compatibility on-disk.
  58. // Easier than migrating older container configs :)
  59. VolumesRW map[string]bool
  60. hostConfig *HostConfig
  61. activeLinks map[string]*Link
  62. }
  63. // Note: the Config structure should hold only portable information about the container.
  64. // Here, "portable" means "independent from the host we are running on".
  65. // Non-portable information *should* appear in HostConfig.
  66. type Config struct {
  67. Hostname string
  68. Domainname string
  69. User string
  70. Memory int64 // Memory limit (in bytes)
  71. MemorySwap int64 // Total memory usage (memory + swap); set `-1' to disable swap
  72. CpuShares int64 // CPU shares (relative weight vs. other containers)
  73. AttachStdin bool
  74. AttachStdout bool
  75. AttachStderr bool
  76. PortSpecs []string // Deprecated - Can be in the format of 8080/tcp
  77. ExposedPorts map[Port]struct{}
  78. Tty bool // Attach standard streams to a tty, including stdin if it is not closed.
  79. OpenStdin bool // Open stdin
  80. StdinOnce bool // If true, close stdin after the 1 attached client disconnects.
  81. Env []string
  82. Cmd []string
  83. Dns []string
  84. Image string // Name of the image as it was passed by the operator (eg. could be symbolic)
  85. Volumes map[string]struct{}
  86. VolumesFrom string
  87. WorkingDir string
  88. Entrypoint []string
  89. NetworkDisabled bool
  90. }
  91. type HostConfig struct {
  92. Binds []string
  93. ContainerIDFile string
  94. LxcConf []KeyValuePair
  95. Privileged bool
  96. PortBindings map[Port][]PortBinding
  97. Links []string
  98. PublishAllPorts bool
  99. }
  100. type BindMap struct {
  101. SrcPath string
  102. DstPath string
  103. Mode string
  104. }
  105. var (
  106. ErrContainerStart = errors.New("The container failed to start. Unknown error")
  107. ErrContainerStartTimeout = errors.New("The container failed to start due to timed out.")
  108. ErrInvalidWorikingDirectory = errors.New("The working directory is invalid. It needs to be an absolute path.")
  109. ErrConflictAttachDetach = errors.New("Conflicting options: -a and -d")
  110. ErrConflictDetachAutoRemove = errors.New("Conflicting options: -rm and -d")
  111. )
  112. type KeyValuePair struct {
  113. Key string
  114. Value string
  115. }
  116. type PortBinding struct {
  117. HostIp string
  118. HostPort string
  119. }
  120. // 80/tcp
  121. type Port string
  122. func (p Port) Proto() string {
  123. parts := strings.Split(string(p), "/")
  124. if len(parts) == 1 {
  125. return "tcp"
  126. }
  127. return parts[1]
  128. }
  129. func (p Port) Port() string {
  130. return strings.Split(string(p), "/")[0]
  131. }
  132. func (p Port) Int() int {
  133. i, err := parsePort(p.Port())
  134. if err != nil {
  135. panic(err)
  136. }
  137. return i
  138. }
  139. func NewPort(proto, port string) Port {
  140. return Port(fmt.Sprintf("%s/%s", port, proto))
  141. }
  142. type PortMapping map[string]string // Deprecated
  143. type NetworkSettings struct {
  144. IPAddress string
  145. IPPrefixLen int
  146. Gateway string
  147. Bridge string
  148. PortMapping map[string]PortMapping // Deprecated
  149. Ports map[Port][]PortBinding
  150. }
  151. func (settings *NetworkSettings) PortMappingAPI() []APIPort {
  152. var mapping []APIPort
  153. for port, bindings := range settings.Ports {
  154. p, _ := parsePort(port.Port())
  155. if len(bindings) == 0 {
  156. mapping = append(mapping, APIPort{
  157. PublicPort: int64(p),
  158. Type: port.Proto(),
  159. })
  160. continue
  161. }
  162. for _, binding := range bindings {
  163. p, _ := parsePort(port.Port())
  164. h, _ := parsePort(binding.HostPort)
  165. mapping = append(mapping, APIPort{
  166. PrivatePort: int64(p),
  167. PublicPort: int64(h),
  168. Type: port.Proto(),
  169. IP: binding.HostIp,
  170. })
  171. }
  172. }
  173. return mapping
  174. }
  175. // Inject the io.Reader at the given path. Note: do not close the reader
  176. func (container *Container) Inject(file io.Reader, pth string) error {
  177. if err := container.EnsureMounted(); err != nil {
  178. return fmt.Errorf("inject: error mounting container %s: %s", container.ID, err)
  179. }
  180. // Return error if path exists
  181. destPath := path.Join(container.RootfsPath(), pth)
  182. if _, err := os.Stat(destPath); err == nil {
  183. // Since err is nil, the path could be stat'd and it exists
  184. return fmt.Errorf("%s exists", pth)
  185. } else if !os.IsNotExist(err) {
  186. // Expect err might be that the file doesn't exist, so
  187. // if it's some other error, return that.
  188. return err
  189. }
  190. // Make sure the directory exists
  191. if err := os.MkdirAll(path.Join(container.RootfsPath(), path.Dir(pth)), 0755); err != nil {
  192. return err
  193. }
  194. dest, err := os.Create(destPath)
  195. if err != nil {
  196. return err
  197. }
  198. defer dest.Close()
  199. if _, err := io.Copy(dest, file); err != nil {
  200. return err
  201. }
  202. return nil
  203. }
  204. func (container *Container) Cmd() *exec.Cmd {
  205. return container.cmd
  206. }
  207. func (container *Container) When() time.Time {
  208. return container.Created
  209. }
  210. func (container *Container) FromDisk() error {
  211. data, err := ioutil.ReadFile(container.jsonPath())
  212. if err != nil {
  213. return err
  214. }
  215. // Load container settings
  216. // udp broke compat of docker.PortMapping, but it's not used when loading a container, we can skip it
  217. if err := json.Unmarshal(data, container); err != nil && !strings.Contains(err.Error(), "docker.PortMapping") {
  218. return err
  219. }
  220. return container.readHostConfig()
  221. }
  222. func (container *Container) ToDisk() (err error) {
  223. data, err := json.Marshal(container)
  224. if err != nil {
  225. return
  226. }
  227. err = ioutil.WriteFile(container.jsonPath(), data, 0666)
  228. if err != nil {
  229. return
  230. }
  231. return container.writeHostConfig()
  232. }
  233. func (container *Container) readHostConfig() error {
  234. container.hostConfig = &HostConfig{}
  235. // If the hostconfig file does not exist, do not read it.
  236. // (We still have to initialize container.hostConfig,
  237. // but that's OK, since we just did that above.)
  238. _, err := os.Stat(container.hostConfigPath())
  239. if os.IsNotExist(err) {
  240. return nil
  241. }
  242. data, err := ioutil.ReadFile(container.hostConfigPath())
  243. if err != nil {
  244. return err
  245. }
  246. return json.Unmarshal(data, container.hostConfig)
  247. }
  248. func (container *Container) writeHostConfig() (err error) {
  249. data, err := json.Marshal(container.hostConfig)
  250. if err != nil {
  251. return
  252. }
  253. return ioutil.WriteFile(container.hostConfigPath(), data, 0666)
  254. }
  255. func (container *Container) generateEnvConfig(env []string) error {
  256. data, err := json.Marshal(env)
  257. if err != nil {
  258. return err
  259. }
  260. p, err := container.EnvConfigPath()
  261. if err != nil {
  262. return err
  263. }
  264. ioutil.WriteFile(p, data, 0600)
  265. return nil
  266. }
  267. func (container *Container) generateLXCConfig() error {
  268. fo, err := os.Create(container.lxcConfigPath())
  269. if err != nil {
  270. return err
  271. }
  272. defer fo.Close()
  273. return LxcTemplateCompiled.Execute(fo, container)
  274. }
  275. func (container *Container) startPty() error {
  276. ptyMaster, ptySlave, err := pty.Open()
  277. if err != nil {
  278. return err
  279. }
  280. container.ptyMaster = ptyMaster
  281. container.cmd.Stdout = ptySlave
  282. container.cmd.Stderr = ptySlave
  283. // Copy the PTYs to our broadcasters
  284. go func() {
  285. defer container.stdout.CloseWriters()
  286. utils.Debugf("startPty: begin of stdout pipe")
  287. io.Copy(container.stdout, ptyMaster)
  288. utils.Debugf("startPty: end of stdout pipe")
  289. }()
  290. // stdin
  291. if container.Config.OpenStdin {
  292. container.cmd.Stdin = ptySlave
  293. container.cmd.SysProcAttr.Setctty = true
  294. go func() {
  295. defer container.stdin.Close()
  296. utils.Debugf("startPty: begin of stdin pipe")
  297. io.Copy(ptyMaster, container.stdin)
  298. utils.Debugf("startPty: end of stdin pipe")
  299. }()
  300. }
  301. if err := container.cmd.Start(); err != nil {
  302. return err
  303. }
  304. ptySlave.Close()
  305. return nil
  306. }
  307. func (container *Container) start() error {
  308. container.cmd.Stdout = container.stdout
  309. container.cmd.Stderr = container.stderr
  310. if container.Config.OpenStdin {
  311. stdin, err := container.cmd.StdinPipe()
  312. if err != nil {
  313. return err
  314. }
  315. go func() {
  316. defer stdin.Close()
  317. utils.Debugf("start: begin of stdin pipe")
  318. io.Copy(stdin, container.stdin)
  319. utils.Debugf("start: end of stdin pipe")
  320. }()
  321. }
  322. return container.cmd.Start()
  323. }
  324. func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, stdout io.Writer, stderr io.Writer) chan error {
  325. var cStdout, cStderr io.ReadCloser
  326. var nJobs int
  327. errors := make(chan error, 3)
  328. if stdin != nil && container.Config.OpenStdin {
  329. nJobs += 1
  330. if cStdin, err := container.StdinPipe(); err != nil {
  331. errors <- err
  332. } else {
  333. go func() {
  334. utils.Debugf("attach: stdin: begin")
  335. defer utils.Debugf("attach: stdin: end")
  336. // No matter what, when stdin is closed (io.Copy unblock), close stdout and stderr
  337. if container.Config.StdinOnce && !container.Config.Tty {
  338. defer cStdin.Close()
  339. } else {
  340. if cStdout != nil {
  341. defer cStdout.Close()
  342. }
  343. if cStderr != nil {
  344. defer cStderr.Close()
  345. }
  346. }
  347. if container.Config.Tty {
  348. _, err = utils.CopyEscapable(cStdin, stdin)
  349. } else {
  350. _, err = io.Copy(cStdin, stdin)
  351. }
  352. if err == io.ErrClosedPipe {
  353. err = nil
  354. }
  355. if err != nil {
  356. utils.Errorf("attach: stdin: %s", err)
  357. }
  358. errors <- err
  359. }()
  360. }
  361. }
  362. if stdout != nil {
  363. nJobs += 1
  364. if p, err := container.StdoutPipe(); err != nil {
  365. errors <- err
  366. } else {
  367. cStdout = p
  368. go func() {
  369. utils.Debugf("attach: stdout: begin")
  370. defer utils.Debugf("attach: stdout: end")
  371. // If we are in StdinOnce mode, then close stdin
  372. if container.Config.StdinOnce && stdin != nil {
  373. defer stdin.Close()
  374. }
  375. if stdinCloser != nil {
  376. defer stdinCloser.Close()
  377. }
  378. _, err := io.Copy(stdout, cStdout)
  379. if err == io.ErrClosedPipe {
  380. err = nil
  381. }
  382. if err != nil {
  383. utils.Errorf("attach: stdout: %s", err)
  384. }
  385. errors <- err
  386. }()
  387. }
  388. } else {
  389. go func() {
  390. if stdinCloser != nil {
  391. defer stdinCloser.Close()
  392. }
  393. if cStdout, err := container.StdoutPipe(); err != nil {
  394. utils.Errorf("attach: stdout pipe: %s", err)
  395. } else {
  396. io.Copy(&utils.NopWriter{}, cStdout)
  397. }
  398. }()
  399. }
  400. if stderr != nil {
  401. nJobs += 1
  402. if p, err := container.StderrPipe(); err != nil {
  403. errors <- err
  404. } else {
  405. cStderr = p
  406. go func() {
  407. utils.Debugf("attach: stderr: begin")
  408. defer utils.Debugf("attach: stderr: end")
  409. // If we are in StdinOnce mode, then close stdin
  410. if container.Config.StdinOnce && stdin != nil {
  411. defer stdin.Close()
  412. }
  413. if stdinCloser != nil {
  414. defer stdinCloser.Close()
  415. }
  416. _, err := io.Copy(stderr, cStderr)
  417. if err == io.ErrClosedPipe {
  418. err = nil
  419. }
  420. if err != nil {
  421. utils.Errorf("attach: stderr: %s", err)
  422. }
  423. errors <- err
  424. }()
  425. }
  426. } else {
  427. go func() {
  428. if stdinCloser != nil {
  429. defer stdinCloser.Close()
  430. }
  431. if cStderr, err := container.StderrPipe(); err != nil {
  432. utils.Errorf("attach: stdout pipe: %s", err)
  433. } else {
  434. io.Copy(&utils.NopWriter{}, cStderr)
  435. }
  436. }()
  437. }
  438. return utils.Go(func() error {
  439. if cStdout != nil {
  440. defer cStdout.Close()
  441. }
  442. if cStderr != nil {
  443. defer cStderr.Close()
  444. }
  445. // FIXME: how to clean up the stdin goroutine without the unwanted side effect
  446. // of closing the passed stdin? Add an intermediary io.Pipe?
  447. for i := 0; i < nJobs; i += 1 {
  448. utils.Debugf("attach: waiting for job %d/%d", i+1, nJobs)
  449. if err := <-errors; err != nil {
  450. utils.Errorf("attach: job %d returned error %s, aborting all jobs", i+1, err)
  451. return err
  452. }
  453. utils.Debugf("attach: job %d completed successfully", i+1)
  454. }
  455. utils.Debugf("attach: all jobs completed successfully")
  456. return nil
  457. })
  458. }
  459. func (container *Container) Start() (err error) {
  460. container.Lock()
  461. defer container.Unlock()
  462. if container.State.IsRunning() {
  463. return fmt.Errorf("The container %s is already running.", container.ID)
  464. }
  465. defer func() {
  466. if err != nil {
  467. container.cleanup()
  468. }
  469. }()
  470. if err := container.EnsureMounted(); err != nil {
  471. return err
  472. }
  473. if container.runtime.networkManager.disabled {
  474. container.Config.NetworkDisabled = true
  475. container.buildHostnameAndHostsFiles("127.0.1.1")
  476. } else {
  477. if err := container.allocateNetwork(); err != nil {
  478. return err
  479. }
  480. container.buildHostnameAndHostsFiles(container.NetworkSettings.IPAddress)
  481. }
  482. // Make sure the config is compatible with the current kernel
  483. if container.Config.Memory > 0 && !container.runtime.capabilities.MemoryLimit {
  484. log.Printf("WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.\n")
  485. container.Config.Memory = 0
  486. }
  487. if container.Config.Memory > 0 && !container.runtime.capabilities.SwapLimit {
  488. log.Printf("WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.\n")
  489. container.Config.MemorySwap = -1
  490. }
  491. if container.runtime.capabilities.IPv4ForwardingDisabled {
  492. log.Printf("WARNING: IPv4 forwarding is disabled. Networking will not work")
  493. }
  494. if container.Volumes == nil || len(container.Volumes) == 0 {
  495. container.Volumes = make(map[string]string)
  496. container.VolumesRW = make(map[string]bool)
  497. }
  498. // Apply volumes from another container if requested
  499. if err := container.applyExternalVolumes(); err != nil {
  500. return err
  501. }
  502. if err := container.createVolumes(); err != nil {
  503. return err
  504. }
  505. if err := container.generateLXCConfig(); err != nil {
  506. return err
  507. }
  508. var lxcStart string = "lxc-start"
  509. if container.hostConfig.Privileged && container.runtime.capabilities.AppArmor {
  510. lxcStart = path.Join(container.runtime.config.Root, "lxc-start-unconfined")
  511. }
  512. params := []string{
  513. lxcStart,
  514. "-n", container.ID,
  515. "-f", container.lxcConfigPath(),
  516. "--",
  517. "/.dockerinit",
  518. }
  519. // Networking
  520. if !container.Config.NetworkDisabled {
  521. network := container.NetworkSettings
  522. params = append(params,
  523. "-g", network.Gateway,
  524. "-i", fmt.Sprintf("%s/%d", network.IPAddress, network.IPPrefixLen),
  525. "-mtu", strconv.Itoa(container.runtime.config.Mtu),
  526. )
  527. }
  528. // User
  529. if container.Config.User != "" {
  530. params = append(params, "-u", container.Config.User)
  531. }
  532. // Setup environment
  533. env := []string{
  534. "HOME=/",
  535. "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
  536. "HOSTNAME=" + container.Config.Hostname,
  537. }
  538. if container.Config.Tty {
  539. env = append(env, "TERM=xterm")
  540. }
  541. if container.hostConfig.Privileged {
  542. params = append(params, "-privileged")
  543. }
  544. // Init any links between the parent and children
  545. runtime := container.runtime
  546. children, err := runtime.Children(container.Name)
  547. if err != nil {
  548. return err
  549. }
  550. if len(children) > 0 {
  551. container.activeLinks = make(map[string]*Link, len(children))
  552. // If we encounter an error make sure that we rollback any network
  553. // config and ip table changes
  554. rollback := func() {
  555. for _, link := range container.activeLinks {
  556. link.Disable()
  557. }
  558. container.activeLinks = nil
  559. }
  560. for p, child := range children {
  561. link, err := NewLink(container, child, p, runtime.networkManager.bridgeIface)
  562. if err != nil {
  563. rollback()
  564. return err
  565. }
  566. container.activeLinks[link.Alias()] = link
  567. if err := link.Enable(); err != nil {
  568. rollback()
  569. return err
  570. }
  571. for _, envVar := range link.ToEnv() {
  572. env = append(env, envVar)
  573. }
  574. }
  575. }
  576. for _, elem := range container.Config.Env {
  577. env = append(env, elem)
  578. }
  579. if err := container.generateEnvConfig(env); err != nil {
  580. return err
  581. }
  582. if container.Config.WorkingDir != "" {
  583. workingDir := path.Clean(container.Config.WorkingDir)
  584. utils.Debugf("[working dir] working dir is %s", workingDir)
  585. if err := os.MkdirAll(path.Join(container.RootfsPath(), workingDir), 0755); err != nil {
  586. return nil
  587. }
  588. params = append(params,
  589. "-w", workingDir,
  590. )
  591. }
  592. // Program
  593. params = append(params, "--", container.Path)
  594. params = append(params, container.Args...)
  595. if RootIsShared() {
  596. // lxc-start really needs / to be non-shared, or all kinds of stuff break
  597. // when lxc-start unmount things and those unmounts propagate to the main
  598. // mount namespace.
  599. // What we really want is to clone into a new namespace and then
  600. // mount / MS_REC|MS_SLAVE, but since we can't really clone or fork
  601. // without exec in go we have to do this horrible shell hack...
  602. shellString :=
  603. "mount --make-rslave /; exec " +
  604. utils.ShellQuoteArguments(params)
  605. params = []string{
  606. "unshare", "-m", "--", "/bin/sh", "-c", shellString,
  607. }
  608. }
  609. root := container.RootfsPath()
  610. envPath, err := container.EnvConfigPath()
  611. if err != nil {
  612. return err
  613. }
  614. // Mount docker specific files into the containers root fs
  615. if err := mount.Mount(runtime.sysInitPath, path.Join(root, "/.dockerinit"), "none", "bind,ro"); err != nil {
  616. return err
  617. }
  618. if err := mount.Mount(envPath, path.Join(root, "/.dockerenv"), "none", "bind,ro"); err != nil {
  619. return err
  620. }
  621. if err := mount.Mount(container.ResolvConfPath, path.Join(root, "/etc/resolv.conf"), "none", "bind,ro"); err != nil {
  622. return err
  623. }
  624. if container.HostnamePath != "" && container.HostsPath != "" {
  625. if err := mount.Mount(container.HostnamePath, path.Join(root, "/etc/hostname"), "none", "bind,ro"); err != nil {
  626. return err
  627. }
  628. if err := mount.Mount(container.HostsPath, path.Join(root, "/etc/hosts"), "none", "bind,ro"); err != nil {
  629. return err
  630. }
  631. }
  632. // Mount user specified volumes
  633. for r, v := range container.Volumes {
  634. mountAs := "ro"
  635. if container.VolumesRW[v] {
  636. mountAs = "rw"
  637. }
  638. if err := mount.Mount(v, path.Join(root, r), "none", fmt.Sprintf("bind,%s", mountAs)); err != nil {
  639. return err
  640. }
  641. }
  642. container.cmd = exec.Command(params[0], params[1:]...)
  643. // Setup logging of stdout and stderr to disk
  644. if err := container.runtime.LogToDisk(container.stdout, container.logPath("json"), "stdout"); err != nil {
  645. return err
  646. }
  647. if err := container.runtime.LogToDisk(container.stderr, container.logPath("json"), "stderr"); err != nil {
  648. return err
  649. }
  650. container.cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
  651. if container.Config.Tty {
  652. err = container.startPty()
  653. } else {
  654. err = container.start()
  655. }
  656. if err != nil {
  657. return err
  658. }
  659. // FIXME: save state on disk *first*, then converge
  660. // this way disk state is used as a journal, eg. we can restore after crash etc.
  661. container.State.SetRunning(container.cmd.Process.Pid)
  662. // Init the lock
  663. container.waitLock = make(chan struct{})
  664. container.ToDisk()
  665. go container.monitor()
  666. defer utils.Debugf("Container running: %v", container.State.IsRunning())
  667. // We wait for the container to be fully running.
  668. // Timeout after 5 seconds. In case of broken pipe, just retry.
  669. // Note: The container can run and finish correctly before
  670. // the end of this loop
  671. for now := time.Now(); time.Since(now) < 5*time.Second; {
  672. // If the container dies while waiting for it, just return
  673. if !container.State.IsRunning() {
  674. return nil
  675. }
  676. output, err := exec.Command("lxc-info", "-s", "-n", container.ID).CombinedOutput()
  677. if err != nil {
  678. utils.Debugf("Error with lxc-info: %s (%s)", err, output)
  679. output, err = exec.Command("lxc-info", "-s", "-n", container.ID).CombinedOutput()
  680. if err != nil {
  681. utils.Debugf("Second Error with lxc-info: %s (%s)", err, output)
  682. return err
  683. }
  684. }
  685. if strings.Contains(string(output), "RUNNING") {
  686. return nil
  687. }
  688. utils.Debugf("Waiting for the container to start (running: %v): %s", container.State.IsRunning(), bytes.TrimSpace(output))
  689. time.Sleep(50 * time.Millisecond)
  690. }
  691. if container.State.IsRunning() {
  692. return ErrContainerStartTimeout
  693. }
  694. return ErrContainerStart
  695. }
  696. func (container *Container) getBindMap() (map[string]BindMap, error) {
  697. // Create the requested bind mounts
  698. binds := make(map[string]BindMap)
  699. // Define illegal container destinations
  700. illegalDsts := []string{"/", "."}
  701. for _, bind := range container.hostConfig.Binds {
  702. // FIXME: factorize bind parsing in parseBind
  703. var src, dst, mode string
  704. arr := strings.Split(bind, ":")
  705. if len(arr) == 2 {
  706. src = arr[0]
  707. dst = arr[1]
  708. mode = "rw"
  709. } else if len(arr) == 3 {
  710. src = arr[0]
  711. dst = arr[1]
  712. mode = arr[2]
  713. } else {
  714. return nil, fmt.Errorf("Invalid bind specification: %s", bind)
  715. }
  716. // Bail if trying to mount to an illegal destination
  717. for _, illegal := range illegalDsts {
  718. if dst == illegal {
  719. return nil, fmt.Errorf("Illegal bind destination: %s", dst)
  720. }
  721. }
  722. bindMap := BindMap{
  723. SrcPath: src,
  724. DstPath: dst,
  725. Mode: mode,
  726. }
  727. binds[path.Clean(dst)] = bindMap
  728. }
  729. return binds, nil
  730. }
  731. func (container *Container) createVolumes() error {
  732. binds, err := container.getBindMap()
  733. if err != nil {
  734. return err
  735. }
  736. volumesDriver := container.runtime.volumes.driver
  737. // Create the requested volumes if they don't exist
  738. for volPath := range container.Config.Volumes {
  739. volPath = path.Clean(volPath)
  740. volIsDir := true
  741. // Skip existing volumes
  742. if _, exists := container.Volumes[volPath]; exists {
  743. continue
  744. }
  745. var srcPath string
  746. var isBindMount bool
  747. srcRW := false
  748. // If an external bind is defined for this volume, use that as a source
  749. if bindMap, exists := binds[volPath]; exists {
  750. isBindMount = true
  751. srcPath = bindMap.SrcPath
  752. if strings.ToLower(bindMap.Mode) == "rw" {
  753. srcRW = true
  754. }
  755. if stat, err := os.Lstat(bindMap.SrcPath); err != nil {
  756. return err
  757. } else {
  758. volIsDir = stat.IsDir()
  759. }
  760. // Otherwise create an directory in $ROOT/volumes/ and use that
  761. } else {
  762. // Do not pass a container as the parameter for the volume creation.
  763. // The graph driver using the container's information ( Image ) to
  764. // create the parent.
  765. c, err := container.runtime.volumes.Create(nil, nil, "", "", nil)
  766. if err != nil {
  767. return err
  768. }
  769. srcPath, err = volumesDriver.Get(c.ID)
  770. if err != nil {
  771. return fmt.Errorf("Driver %s failed to get volume rootfs %s: %s", volumesDriver, c.ID, err)
  772. }
  773. srcRW = true // RW by default
  774. }
  775. container.Volumes[volPath] = srcPath
  776. container.VolumesRW[volPath] = srcRW
  777. // Create the mountpoint
  778. volPath = path.Join(container.RootfsPath(), volPath)
  779. rootVolPath, err := utils.FollowSymlinkInScope(volPath, container.RootfsPath())
  780. if err != nil {
  781. return err
  782. }
  783. if _, err := os.Stat(rootVolPath); err != nil {
  784. if os.IsNotExist(err) {
  785. if volIsDir {
  786. if err := os.MkdirAll(rootVolPath, 0755); err != nil {
  787. return err
  788. }
  789. } else {
  790. if err := os.MkdirAll(path.Dir(rootVolPath), 0755); err != nil {
  791. return err
  792. }
  793. if f, err := os.OpenFile(rootVolPath, os.O_CREATE, 0755); err != nil {
  794. return err
  795. } else {
  796. f.Close()
  797. }
  798. }
  799. }
  800. }
  801. // Do not copy or change permissions if we are mounting from the host
  802. if srcRW && !isBindMount {
  803. volList, err := ioutil.ReadDir(rootVolPath)
  804. if err != nil {
  805. return err
  806. }
  807. if len(volList) > 0 {
  808. srcList, err := ioutil.ReadDir(srcPath)
  809. if err != nil {
  810. return err
  811. }
  812. if len(srcList) == 0 {
  813. // If the source volume is empty copy files from the root into the volume
  814. if err := archive.CopyWithTar(rootVolPath, srcPath); err != nil {
  815. return err
  816. }
  817. var stat syscall.Stat_t
  818. if err := syscall.Stat(rootVolPath, &stat); err != nil {
  819. return err
  820. }
  821. var srcStat syscall.Stat_t
  822. if err := syscall.Stat(srcPath, &srcStat); err != nil {
  823. return err
  824. }
  825. // Change the source volume's ownership if it differs from the root
  826. // files that where just copied
  827. if stat.Uid != srcStat.Uid || stat.Gid != srcStat.Gid {
  828. if err := os.Chown(srcPath, int(stat.Uid), int(stat.Gid)); err != nil {
  829. return err
  830. }
  831. }
  832. }
  833. }
  834. }
  835. }
  836. return nil
  837. }
  838. func (container *Container) applyExternalVolumes() error {
  839. if container.Config.VolumesFrom != "" {
  840. containerSpecs := strings.Split(container.Config.VolumesFrom, ",")
  841. for _, containerSpec := range containerSpecs {
  842. mountRW := true
  843. specParts := strings.SplitN(containerSpec, ":", 2)
  844. switch len(specParts) {
  845. case 0:
  846. return fmt.Errorf("Malformed volumes-from specification: %s", container.Config.VolumesFrom)
  847. case 2:
  848. switch specParts[1] {
  849. case "ro":
  850. mountRW = false
  851. case "rw": // mountRW is already true
  852. default:
  853. return fmt.Errorf("Malformed volumes-from speficication: %s", containerSpec)
  854. }
  855. }
  856. c := container.runtime.Get(specParts[0])
  857. if c == nil {
  858. return fmt.Errorf("Container %s not found. Impossible to mount its volumes", container.ID)
  859. }
  860. for volPath, id := range c.Volumes {
  861. if _, exists := container.Volumes[volPath]; exists {
  862. continue
  863. }
  864. if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil {
  865. return err
  866. }
  867. container.Volumes[volPath] = id
  868. if isRW, exists := c.VolumesRW[volPath]; exists {
  869. container.VolumesRW[volPath] = isRW && mountRW
  870. }
  871. }
  872. }
  873. }
  874. return nil
  875. }
  876. func (container *Container) Run() error {
  877. if err := container.Start(); err != nil {
  878. return err
  879. }
  880. container.Wait()
  881. return nil
  882. }
  883. func (container *Container) Output() (output []byte, err error) {
  884. pipe, err := container.StdoutPipe()
  885. if err != nil {
  886. return nil, err
  887. }
  888. defer pipe.Close()
  889. if err := container.Start(); err != nil {
  890. return nil, err
  891. }
  892. output, err = ioutil.ReadAll(pipe)
  893. container.Wait()
  894. return output, err
  895. }
  896. // Container.StdinPipe returns a WriteCloser which can be used to feed data
  897. // to the standard input of the container's active process.
  898. // Container.StdoutPipe and Container.StderrPipe each return a ReadCloser
  899. // which can be used to retrieve the standard output (and error) generated
  900. // by the container's active process. The output (and error) are actually
  901. // copied and delivered to all StdoutPipe and StderrPipe consumers, using
  902. // a kind of "broadcaster".
  903. func (container *Container) StdinPipe() (io.WriteCloser, error) {
  904. return container.stdinPipe, nil
  905. }
  906. func (container *Container) StdoutPipe() (io.ReadCloser, error) {
  907. reader, writer := io.Pipe()
  908. container.stdout.AddWriter(writer, "")
  909. return utils.NewBufReader(reader), nil
  910. }
  911. func (container *Container) StderrPipe() (io.ReadCloser, error) {
  912. reader, writer := io.Pipe()
  913. container.stderr.AddWriter(writer, "")
  914. return utils.NewBufReader(reader), nil
  915. }
  916. func (container *Container) buildHostnameAndHostsFiles(IP string) {
  917. container.HostnamePath = path.Join(container.root, "hostname")
  918. ioutil.WriteFile(container.HostnamePath, []byte(container.Config.Hostname+"\n"), 0644)
  919. hostsContent := []byte(`
  920. 127.0.0.1 localhost
  921. ::1 localhost ip6-localhost ip6-loopback
  922. fe00::0 ip6-localnet
  923. ff00::0 ip6-mcastprefix
  924. ff02::1 ip6-allnodes
  925. ff02::2 ip6-allrouters
  926. `)
  927. container.HostsPath = path.Join(container.root, "hosts")
  928. if container.Config.Domainname != "" {
  929. hostsContent = append([]byte(fmt.Sprintf("%s\t%s.%s %s\n", IP, container.Config.Hostname, container.Config.Domainname, container.Config.Hostname)), hostsContent...)
  930. } else if !container.Config.NetworkDisabled {
  931. hostsContent = append([]byte(fmt.Sprintf("%s\t%s\n", IP, container.Config.Hostname)), hostsContent...)
  932. }
  933. ioutil.WriteFile(container.HostsPath, hostsContent, 0644)
  934. }
  935. func (container *Container) allocateNetwork() error {
  936. if container.Config.NetworkDisabled {
  937. return nil
  938. }
  939. var (
  940. iface *NetworkInterface
  941. err error
  942. )
  943. if container.State.IsGhost() {
  944. if manager := container.runtime.networkManager; manager.disabled {
  945. iface = &NetworkInterface{disabled: true}
  946. } else {
  947. iface = &NetworkInterface{
  948. IPNet: net.IPNet{IP: net.ParseIP(container.NetworkSettings.IPAddress), Mask: manager.bridgeNetwork.Mask},
  949. Gateway: manager.bridgeNetwork.IP,
  950. manager: manager,
  951. }
  952. if iface != nil && iface.IPNet.IP != nil {
  953. ipNum := ipToInt(iface.IPNet.IP)
  954. manager.ipAllocator.inUse[ipNum] = struct{}{}
  955. } else {
  956. iface, err = container.runtime.networkManager.Allocate()
  957. if err != nil {
  958. return err
  959. }
  960. }
  961. }
  962. } else {
  963. iface, err = container.runtime.networkManager.Allocate()
  964. if err != nil {
  965. return err
  966. }
  967. }
  968. if container.Config.PortSpecs != nil {
  969. utils.Debugf("Migrating port mappings for container: %s", strings.Join(container.Config.PortSpecs, ", "))
  970. if err := migratePortMappings(container.Config, container.hostConfig); err != nil {
  971. return err
  972. }
  973. container.Config.PortSpecs = nil
  974. if err := container.writeHostConfig(); err != nil {
  975. return err
  976. }
  977. }
  978. var (
  979. portSpecs = make(map[Port]struct{})
  980. bindings = make(map[Port][]PortBinding)
  981. )
  982. if !container.State.IsGhost() {
  983. if container.Config.ExposedPorts != nil {
  984. portSpecs = container.Config.ExposedPorts
  985. }
  986. if container.hostConfig.PortBindings != nil {
  987. bindings = container.hostConfig.PortBindings
  988. }
  989. } else {
  990. if container.NetworkSettings.Ports != nil {
  991. for port, binding := range container.NetworkSettings.Ports {
  992. portSpecs[port] = struct{}{}
  993. bindings[port] = binding
  994. }
  995. }
  996. }
  997. container.NetworkSettings.PortMapping = nil
  998. for port := range portSpecs {
  999. binding := bindings[port]
  1000. if container.hostConfig.PublishAllPorts && len(binding) == 0 {
  1001. binding = append(binding, PortBinding{})
  1002. }
  1003. for i := 0; i < len(binding); i++ {
  1004. b := binding[i]
  1005. nat, err := iface.AllocatePort(port, b)
  1006. if err != nil {
  1007. iface.Release()
  1008. return err
  1009. }
  1010. utils.Debugf("Allocate port: %s:%s->%s", nat.Binding.HostIp, port, nat.Binding.HostPort)
  1011. binding[i] = nat.Binding
  1012. }
  1013. bindings[port] = binding
  1014. }
  1015. container.writeHostConfig()
  1016. container.NetworkSettings.Ports = bindings
  1017. container.network = iface
  1018. container.NetworkSettings.Bridge = container.runtime.networkManager.bridgeIface
  1019. container.NetworkSettings.IPAddress = iface.IPNet.IP.String()
  1020. container.NetworkSettings.IPPrefixLen, _ = iface.IPNet.Mask.Size()
  1021. container.NetworkSettings.Gateway = iface.Gateway.String()
  1022. return nil
  1023. }
  1024. func (container *Container) releaseNetwork() {
  1025. if container.Config.NetworkDisabled || container.network == nil {
  1026. return
  1027. }
  1028. container.network.Release()
  1029. container.network = nil
  1030. container.NetworkSettings = &NetworkSettings{}
  1031. }
  1032. // FIXME: replace this with a control socket within dockerinit
  1033. func (container *Container) waitLxc() error {
  1034. for {
  1035. output, err := exec.Command("lxc-info", "-n", container.ID).CombinedOutput()
  1036. if err != nil {
  1037. return err
  1038. }
  1039. if !strings.Contains(string(output), "RUNNING") {
  1040. return nil
  1041. }
  1042. time.Sleep(500 * time.Millisecond)
  1043. }
  1044. }
  1045. func (container *Container) monitor() {
  1046. // Wait for the program to exit
  1047. // If the command does not exist, try to wait via lxc
  1048. // (This probably happens only for ghost containers, i.e. containers that were running when Docker started)
  1049. if container.cmd == nil {
  1050. utils.Debugf("monitor: waiting for container %s using waitLxc", container.ID)
  1051. if err := container.waitLxc(); err != nil {
  1052. utils.Errorf("monitor: while waiting for container %s, waitLxc had a problem: %s", container.ID, err)
  1053. }
  1054. } else {
  1055. utils.Debugf("monitor: waiting for container %s using cmd.Wait", container.ID)
  1056. if err := container.cmd.Wait(); err != nil {
  1057. // Since non-zero exit status and signal terminations will cause err to be non-nil,
  1058. // we have to actually discard it. Still, log it anyway, just in case.
  1059. utils.Debugf("monitor: cmd.Wait reported exit status %s for container %s", err, container.ID)
  1060. }
  1061. }
  1062. utils.Debugf("monitor: container %s finished", container.ID)
  1063. exitCode := -1
  1064. if container.cmd != nil {
  1065. exitCode = container.cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
  1066. }
  1067. if container.runtime != nil && container.runtime.srv != nil {
  1068. container.runtime.srv.LogEvent("die", container.ID, container.runtime.repositories.ImageName(container.Image))
  1069. }
  1070. // Cleanup
  1071. container.cleanup()
  1072. // Re-create a brand new stdin pipe once the container exited
  1073. if container.Config.OpenStdin {
  1074. container.stdin, container.stdinPipe = io.Pipe()
  1075. }
  1076. // Report status back
  1077. container.State.SetStopped(exitCode)
  1078. // Release the lock
  1079. close(container.waitLock)
  1080. if err := container.ToDisk(); err != nil {
  1081. // FIXME: there is a race condition here which causes this to fail during the unit tests.
  1082. // If another goroutine was waiting for Wait() to return before removing the container's root
  1083. // from the filesystem... At this point it may already have done so.
  1084. // This is because State.setStopped() has already been called, and has caused Wait()
  1085. // to return.
  1086. // FIXME: why are we serializing running state to disk in the first place?
  1087. //log.Printf("%s: Failed to dump configuration to the disk: %s", container.ID, err)
  1088. }
  1089. }
  1090. func (container *Container) cleanup() {
  1091. container.releaseNetwork()
  1092. // Disable all active links
  1093. if container.activeLinks != nil {
  1094. for _, link := range container.activeLinks {
  1095. link.Disable()
  1096. }
  1097. }
  1098. if container.Config.OpenStdin {
  1099. if err := container.stdin.Close(); err != nil {
  1100. utils.Errorf("%s: Error close stdin: %s", container.ID, err)
  1101. }
  1102. }
  1103. if err := container.stdout.CloseWriters(); err != nil {
  1104. utils.Errorf("%s: Error close stdout: %s", container.ID, err)
  1105. }
  1106. if err := container.stderr.CloseWriters(); err != nil {
  1107. utils.Errorf("%s: Error close stderr: %s", container.ID, err)
  1108. }
  1109. if container.ptyMaster != nil {
  1110. if err := container.ptyMaster.Close(); err != nil {
  1111. utils.Errorf("%s: Error closing Pty master: %s", container.ID, err)
  1112. }
  1113. }
  1114. if err := container.Unmount(); err != nil {
  1115. log.Printf("%v: Failed to umount filesystem: %v", container.ID, err)
  1116. }
  1117. }
  1118. func (container *Container) kill(sig int) error {
  1119. container.Lock()
  1120. defer container.Unlock()
  1121. if !container.State.IsRunning() {
  1122. return nil
  1123. }
  1124. if output, err := exec.Command("lxc-kill", "-n", container.ID, strconv.Itoa(sig)).CombinedOutput(); err != nil {
  1125. log.Printf("error killing container %s (%s, %s)", utils.TruncateID(container.ID), output, err)
  1126. return err
  1127. }
  1128. return nil
  1129. }
  1130. func (container *Container) Kill() error {
  1131. if !container.State.IsRunning() {
  1132. return nil
  1133. }
  1134. // 1. Send SIGKILL
  1135. if err := container.kill(9); err != nil {
  1136. return err
  1137. }
  1138. // 2. Wait for the process to die, in last resort, try to kill the process directly
  1139. if err := container.WaitTimeout(10 * time.Second); err != nil {
  1140. if container.cmd == nil {
  1141. return fmt.Errorf("lxc-kill failed, impossible to kill the container %s", utils.TruncateID(container.ID))
  1142. }
  1143. log.Printf("Container %s failed to exit within 10 seconds of lxc-kill %s - trying direct SIGKILL", "SIGKILL", utils.TruncateID(container.ID))
  1144. if err := container.cmd.Process.Kill(); err != nil {
  1145. return err
  1146. }
  1147. }
  1148. container.Wait()
  1149. return nil
  1150. }
  1151. func (container *Container) Stop(seconds int) error {
  1152. if !container.State.IsRunning() {
  1153. return nil
  1154. }
  1155. // 1. Send a SIGTERM
  1156. if err := container.kill(15); err != nil {
  1157. utils.Debugf("Error sending kill SIGTERM: %s", err)
  1158. log.Print("Failed to send SIGTERM to the process, force killing")
  1159. if err := container.kill(9); err != nil {
  1160. return err
  1161. }
  1162. }
  1163. // 2. Wait for the process to exit on its own
  1164. if err := container.WaitTimeout(time.Duration(seconds) * time.Second); err != nil {
  1165. log.Printf("Container %v failed to exit within %d seconds of SIGTERM - using the force", container.ID, seconds)
  1166. // 3. If it doesn't, then send SIGKILL
  1167. if err := container.Kill(); err != nil {
  1168. return err
  1169. }
  1170. }
  1171. return nil
  1172. }
  1173. func (container *Container) Restart(seconds int) error {
  1174. if err := container.Stop(seconds); err != nil {
  1175. return err
  1176. }
  1177. return container.Start()
  1178. }
  1179. // Wait blocks until the container stops running, then returns its exit code.
  1180. func (container *Container) Wait() int {
  1181. <-container.waitLock
  1182. return container.State.GetExitCode()
  1183. }
  1184. func (container *Container) Resize(h, w int) error {
  1185. pty, ok := container.ptyMaster.(*os.File)
  1186. if !ok {
  1187. return fmt.Errorf("ptyMaster does not have Fd() method")
  1188. }
  1189. return term.SetWinsize(pty.Fd(), &term.Winsize{Height: uint16(h), Width: uint16(w)})
  1190. }
  1191. func (container *Container) ExportRw() (archive.Archive, error) {
  1192. if err := container.EnsureMounted(); err != nil {
  1193. return nil, err
  1194. }
  1195. if container.runtime == nil {
  1196. return nil, fmt.Errorf("Can't load storage driver for unregistered container %s", container.ID)
  1197. }
  1198. return container.runtime.Diff(container)
  1199. }
  1200. func (container *Container) Export() (archive.Archive, error) {
  1201. if err := container.EnsureMounted(); err != nil {
  1202. return nil, err
  1203. }
  1204. return archive.Tar(container.RootfsPath(), archive.Uncompressed)
  1205. }
  1206. func (container *Container) WaitTimeout(timeout time.Duration) error {
  1207. done := make(chan bool)
  1208. go func() {
  1209. container.Wait()
  1210. done <- true
  1211. }()
  1212. select {
  1213. case <-time.After(timeout):
  1214. return fmt.Errorf("Timed Out")
  1215. case <-done:
  1216. return nil
  1217. }
  1218. }
  1219. func (container *Container) EnsureMounted() error {
  1220. // FIXME: EnsureMounted is deprecated because drivers are now responsible
  1221. // for re-entrant mounting in their Get() method.
  1222. return container.Mount()
  1223. }
  1224. func (container *Container) Mount() error {
  1225. return container.runtime.Mount(container)
  1226. }
  1227. func (container *Container) Changes() ([]archive.Change, error) {
  1228. return container.runtime.Changes(container)
  1229. }
  1230. func (container *Container) GetImage() (*Image, error) {
  1231. if container.runtime == nil {
  1232. return nil, fmt.Errorf("Can't get image of unregistered container")
  1233. }
  1234. return container.runtime.graph.Get(container.Image)
  1235. }
  1236. func (container *Container) Unmount() error {
  1237. var (
  1238. err error
  1239. root = container.RootfsPath()
  1240. mounts = []string{
  1241. path.Join(root, "/.dockerinit"),
  1242. path.Join(root, "/.dockerenv"),
  1243. path.Join(root, "/etc/resolv.conf"),
  1244. }
  1245. )
  1246. if container.HostnamePath != "" && container.HostsPath != "" {
  1247. mounts = append(mounts, path.Join(root, "/etc/hostname"), path.Join(root, "/etc/hosts"))
  1248. }
  1249. for r := range container.Volumes {
  1250. mounts = append(mounts, path.Join(root, r))
  1251. }
  1252. for _, m := range mounts {
  1253. if lastError := mount.Unmount(m); lastError != nil {
  1254. err = lastError
  1255. }
  1256. }
  1257. if err != nil {
  1258. return err
  1259. }
  1260. return container.runtime.Unmount(container)
  1261. }
  1262. func (container *Container) logPath(name string) string {
  1263. return path.Join(container.root, fmt.Sprintf("%s-%s.log", container.ID, name))
  1264. }
  1265. func (container *Container) ReadLog(name string) (io.Reader, error) {
  1266. return os.Open(container.logPath(name))
  1267. }
  1268. func (container *Container) hostConfigPath() string {
  1269. return path.Join(container.root, "hostconfig.json")
  1270. }
  1271. func (container *Container) jsonPath() string {
  1272. return path.Join(container.root, "config.json")
  1273. }
  1274. func (container *Container) EnvConfigPath() (string, error) {
  1275. p := path.Join(container.root, "config.env")
  1276. if _, err := os.Stat(p); err != nil {
  1277. if os.IsNotExist(err) {
  1278. f, err := os.Create(p)
  1279. if err != nil {
  1280. return "", err
  1281. }
  1282. f.Close()
  1283. } else {
  1284. return "", err
  1285. }
  1286. }
  1287. return p, nil
  1288. }
  1289. func (container *Container) lxcConfigPath() string {
  1290. return path.Join(container.root, "config.lxc")
  1291. }
  1292. // This method must be exported to be used from the lxc template
  1293. func (container *Container) RootfsPath() string {
  1294. return container.rootfs
  1295. }
  1296. func validateID(id string) error {
  1297. if id == "" {
  1298. return fmt.Errorf("Invalid empty id")
  1299. }
  1300. return nil
  1301. }
  1302. // GetSize, return real size, virtual size
  1303. func (container *Container) GetSize() (int64, int64) {
  1304. var (
  1305. sizeRw, sizeRootfs int64
  1306. err error
  1307. driver = container.runtime.driver
  1308. )
  1309. if err := container.EnsureMounted(); err != nil {
  1310. utils.Errorf("Warning: failed to compute size of container rootfs %s: %s", container.ID, err)
  1311. return sizeRw, sizeRootfs
  1312. }
  1313. if differ, ok := container.runtime.driver.(graphdriver.Differ); ok {
  1314. sizeRw, err = differ.DiffSize(container.ID)
  1315. if err != nil {
  1316. utils.Errorf("Warning: driver %s couldn't return diff size of container %s: %s", driver, container.ID, err)
  1317. // FIXME: GetSize should return an error. Not changing it now in case
  1318. // there is a side-effect.
  1319. sizeRw = -1
  1320. }
  1321. } else {
  1322. changes, _ := container.Changes()
  1323. if changes != nil {
  1324. sizeRw = archive.ChangesSize(container.RootfsPath(), changes)
  1325. } else {
  1326. sizeRw = -1
  1327. }
  1328. }
  1329. if _, err = os.Stat(container.RootfsPath()); err != nil {
  1330. if sizeRootfs, err = utils.TreeSize(container.RootfsPath()); err != nil {
  1331. sizeRootfs = -1
  1332. }
  1333. }
  1334. return sizeRw, sizeRootfs
  1335. }
  1336. func (container *Container) Copy(resource string) (archive.Archive, error) {
  1337. if err := container.EnsureMounted(); err != nil {
  1338. return nil, err
  1339. }
  1340. var filter []string
  1341. basePath := path.Join(container.RootfsPath(), resource)
  1342. stat, err := os.Stat(basePath)
  1343. if err != nil {
  1344. return nil, err
  1345. }
  1346. if !stat.IsDir() {
  1347. d, f := path.Split(basePath)
  1348. basePath = d
  1349. filter = []string{f}
  1350. } else {
  1351. filter = []string{path.Base(basePath)}
  1352. basePath = path.Dir(basePath)
  1353. }
  1354. return archive.TarFilter(basePath, &archive.TarOptions{
  1355. Compression: archive.Uncompressed,
  1356. Includes: filter,
  1357. Recursive: true,
  1358. })
  1359. }
  1360. // Returns true if the container exposes a certain port
  1361. func (container *Container) Exposes(p Port) bool {
  1362. _, exists := container.Config.ExposedPorts[p]
  1363. return exists
  1364. }
  1365. func (container *Container) GetPtyMaster() (*os.File, error) {
  1366. if container.ptyMaster == nil {
  1367. return nil, ErrNoTTY
  1368. }
  1369. if pty, ok := container.ptyMaster.(*os.File); ok {
  1370. return pty, nil
  1371. }
  1372. return nil, ErrNotATTY
  1373. }