container.go 44 KB

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