init.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "github.com/dotcloud/docker/pkg/libcontainer"
  6. "github.com/dotcloud/docker/pkg/libcontainer/capabilities"
  7. "github.com/dotcloud/docker/pkg/libcontainer/namespaces"
  8. "github.com/dotcloud/docker/pkg/system"
  9. "log"
  10. "os"
  11. "path/filepath"
  12. "syscall"
  13. )
  14. func loadContainer() (*libcontainer.Container, error) {
  15. f, err := os.Open("container.json")
  16. if err != nil {
  17. return nil, err
  18. }
  19. defer f.Close()
  20. var container *libcontainer.Container
  21. if err := json.NewDecoder(f).Decode(&container); err != nil {
  22. return nil, err
  23. }
  24. return container, nil
  25. }
  26. func main() {
  27. container, err := loadContainer()
  28. if err != nil {
  29. log.Fatal(err)
  30. }
  31. if os.Args[1] == "exec" {
  32. _, err := namespaces.ExecContainer(container)
  33. if err != nil {
  34. log.Fatal(err)
  35. }
  36. os.Exit(0)
  37. }
  38. console := os.Args[1]
  39. if err := setLogFile(container); err != nil {
  40. log.Fatal(err)
  41. }
  42. rootfs, err := resolveRootfs()
  43. if err != nil {
  44. log.Fatal(err)
  45. }
  46. // close pipes so that we can replace it with the pty
  47. os.Stdin.Close()
  48. os.Stdout.Close()
  49. os.Stderr.Close()
  50. slave, err := openTerminal(console, syscall.O_RDWR)
  51. if err != nil {
  52. log.Fatalf("open terminal %s", err)
  53. }
  54. if slave.Fd() != 0 {
  55. log.Fatalf("slave fd should be 0")
  56. }
  57. if err := dupSlave(slave); err != nil {
  58. log.Fatalf("dup2 slave %s", err)
  59. }
  60. if _, err := system.Setsid(); err != nil {
  61. log.Fatalf("setsid %s", err)
  62. }
  63. if err := system.Setctty(); err != nil {
  64. log.Fatalf("setctty %s", err)
  65. }
  66. if err := system.ParentDeathSignal(); err != nil {
  67. log.Fatalf("parent deth signal %s", err)
  68. }
  69. if err := setupNewMountNamespace(rootfs, console, container.ReadonlyFs); err != nil {
  70. log.Fatalf("setup mount namespace %s", err)
  71. }
  72. if container.Network != nil {
  73. if err := setupNetworking(container); err != nil {
  74. log.Fatalf("setup networking %s", err)
  75. }
  76. }
  77. if err := system.Sethostname(container.ID); err != nil {
  78. log.Fatalf("sethostname %s", err)
  79. }
  80. if err := capabilities.DropCapabilities(container); err != nil {
  81. log.Fatalf("drop capabilities %s", err)
  82. }
  83. if err := setupUser(container); err != nil {
  84. log.Fatalf("setup user %s", err)
  85. }
  86. if container.WorkingDir != "" {
  87. if err := system.Chdir(container.WorkingDir); err != nil {
  88. log.Fatalf("chdir to %s %s", container.WorkingDir, err)
  89. }
  90. }
  91. if err := system.Exec(container.Command.Args[0], container.Command.Args[0:], container.Command.Env); err != nil {
  92. log.Fatalf("exec %s", err)
  93. }
  94. panic("unreachable")
  95. }
  96. func resolveRootfs() (string, error) {
  97. cwd, err := os.Getwd()
  98. if err != nil {
  99. return "", err
  100. }
  101. rootfs, err := filepath.Abs(cwd)
  102. if err != nil {
  103. return "", err
  104. }
  105. return filepath.EvalSymlinks(rootfs)
  106. }
  107. func setupUser(container *libcontainer.Container) error {
  108. // TODO: honor user passed on container
  109. if err := system.Setgroups(nil); err != nil {
  110. return err
  111. }
  112. if err := system.Setresgid(0, 0, 0); err != nil {
  113. return err
  114. }
  115. if err := system.Setresuid(0, 0, 0); err != nil {
  116. return err
  117. }
  118. return nil
  119. }
  120. func dupSlave(slave *os.File) error {
  121. // we close Stdin,etc so our pty slave should have fd 0
  122. if slave.Fd() != 0 {
  123. return fmt.Errorf("slave fd not 0 %d", slave.Fd())
  124. }
  125. if err := system.Dup2(slave.Fd(), 1); err != nil {
  126. return err
  127. }
  128. if err := system.Dup2(slave.Fd(), 2); err != nil {
  129. return err
  130. }
  131. return nil
  132. }
  133. // openTerminal is a clone of os.OpenFile without the O_CLOEXEC addition.
  134. func openTerminal(name string, flag int) (*os.File, error) {
  135. r, e := syscall.Open(name, flag, 0)
  136. if e != nil {
  137. return nil, &os.PathError{"open", name, e}
  138. }
  139. return os.NewFile(uintptr(r), name), nil
  140. }
  141. func setLogFile(container *libcontainer.Container) error {
  142. f, err := os.OpenFile(container.LogFile, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0655)
  143. if err != nil {
  144. return err
  145. }
  146. log.SetOutput(f)
  147. return nil
  148. }
  149. func setupNetworking(conatiner *libcontainer.Container) error {
  150. return nil
  151. }