daemon.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // +build daemon
  2. package main
  3. import (
  4. "crypto/tls"
  5. "fmt"
  6. "io"
  7. "os"
  8. "path/filepath"
  9. "time"
  10. "github.com/Sirupsen/logrus"
  11. apiserver "github.com/docker/docker/api/server"
  12. "github.com/docker/docker/autogen/dockerversion"
  13. "github.com/docker/docker/cliconfig"
  14. "github.com/docker/docker/daemon"
  15. flag "github.com/docker/docker/pkg/mflag"
  16. "github.com/docker/docker/pkg/pidfile"
  17. "github.com/docker/docker/pkg/signal"
  18. "github.com/docker/docker/pkg/system"
  19. "github.com/docker/docker/pkg/timeutils"
  20. "github.com/docker/docker/pkg/tlsconfig"
  21. "github.com/docker/docker/registry"
  22. "github.com/docker/docker/utils"
  23. )
  24. var (
  25. daemonCfg = &daemon.Config{}
  26. registryCfg = &registry.Options{}
  27. )
  28. func init() {
  29. if daemonCfg.LogConfig.Config == nil {
  30. daemonCfg.LogConfig.Config = make(map[string]string)
  31. }
  32. daemonCfg.InstallFlags()
  33. registryCfg.InstallFlags()
  34. }
  35. func migrateKey() (err error) {
  36. // Migrate trust key if exists at ~/.docker/key.json and owned by current user
  37. oldPath := filepath.Join(cliconfig.ConfigDir(), defaultTrustKeyFile)
  38. newPath := filepath.Join(getDaemonConfDir(), defaultTrustKeyFile)
  39. if _, statErr := os.Stat(newPath); os.IsNotExist(statErr) && currentUserIsOwner(oldPath) {
  40. defer func() {
  41. // Ensure old path is removed if no error occurred
  42. if err == nil {
  43. err = os.Remove(oldPath)
  44. } else {
  45. logrus.Warnf("Key migration failed, key file not removed at %s", oldPath)
  46. }
  47. }()
  48. if err := system.MkdirAll(getDaemonConfDir(), os.FileMode(0644)); err != nil {
  49. return fmt.Errorf("Unable to create daemon configuration directory: %s", err)
  50. }
  51. newFile, err := os.OpenFile(newPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
  52. if err != nil {
  53. return fmt.Errorf("error creating key file %q: %s", newPath, err)
  54. }
  55. defer newFile.Close()
  56. oldFile, err := os.Open(oldPath)
  57. if err != nil {
  58. return fmt.Errorf("error opening key file %q: %s", oldPath, err)
  59. }
  60. defer oldFile.Close()
  61. if _, err := io.Copy(newFile, oldFile); err != nil {
  62. return fmt.Errorf("error copying key: %s", err)
  63. }
  64. logrus.Infof("Migrated key from %s to %s", oldPath, newPath)
  65. }
  66. return nil
  67. }
  68. func mainDaemon() {
  69. if utils.ExperimentalBuild() {
  70. logrus.Warn("Running experimental build")
  71. }
  72. if flag.NArg() != 0 {
  73. flag.Usage()
  74. return
  75. }
  76. logrus.SetFormatter(&logrus.TextFormatter{TimestampFormat: timeutils.RFC3339NanoFixed})
  77. if err := setDefaultUmask(); err != nil {
  78. logrus.Fatalf("Failed to set umask: %v", err)
  79. }
  80. var pfile *pidfile.PidFile
  81. if daemonCfg.Pidfile != "" {
  82. pf, err := pidfile.New(daemonCfg.Pidfile)
  83. if err != nil {
  84. logrus.Fatalf("Error starting daemon: %v", err)
  85. }
  86. pfile = pf
  87. defer func() {
  88. if err := pfile.Remove(); err != nil {
  89. logrus.Error(err)
  90. }
  91. }()
  92. }
  93. serverConfig := &apiserver.ServerConfig{
  94. Logging: true,
  95. EnableCors: daemonCfg.EnableCors,
  96. CorsHeaders: daemonCfg.CorsHeaders,
  97. Version: dockerversion.VERSION,
  98. }
  99. serverConfig = setPlatformServerConfig(serverConfig, daemonCfg)
  100. if *flTls {
  101. if *flTlsVerify {
  102. tlsOptions.ClientAuth = tls.RequireAndVerifyClientCert
  103. }
  104. tlsConfig, err := tlsconfig.Server(tlsOptions)
  105. if err != nil {
  106. logrus.Fatal(err)
  107. }
  108. serverConfig.TLSConfig = tlsConfig
  109. }
  110. api := apiserver.New(serverConfig)
  111. // The serve API routine never exits unless an error occurs
  112. // We need to start it as a goroutine and wait on it so
  113. // daemon doesn't exit
  114. serveAPIWait := make(chan error)
  115. go func() {
  116. if err := api.ServeApi(flHosts); err != nil {
  117. logrus.Errorf("ServeAPI error: %v", err)
  118. serveAPIWait <- err
  119. return
  120. }
  121. serveAPIWait <- nil
  122. }()
  123. if err := migrateKey(); err != nil {
  124. logrus.Fatal(err)
  125. }
  126. daemonCfg.TrustKeyPath = *flTrustKey
  127. registryService := registry.NewService(registryCfg)
  128. d, err := daemon.NewDaemon(daemonCfg, registryService)
  129. if err != nil {
  130. if pfile != nil {
  131. if err := pfile.Remove(); err != nil {
  132. logrus.Error(err)
  133. }
  134. }
  135. logrus.Fatalf("Error starting daemon: %v", err)
  136. }
  137. logrus.Info("Daemon has completed initialization")
  138. logrus.WithFields(logrus.Fields{
  139. "version": dockerversion.VERSION,
  140. "commit": dockerversion.GITCOMMIT,
  141. "execdriver": d.ExecutionDriver().Name(),
  142. "graphdriver": d.GraphDriver().String(),
  143. }).Info("Docker daemon")
  144. signal.Trap(func() {
  145. api.Close()
  146. <-serveAPIWait
  147. shutdownDaemon(d, 15)
  148. if pfile != nil {
  149. if err := pfile.Remove(); err != nil {
  150. logrus.Error(err)
  151. }
  152. }
  153. })
  154. // after the daemon is done setting up we can tell the api to start
  155. // accepting connections with specified daemon
  156. api.AcceptConnections(d)
  157. // Daemon is fully initialized and handling API traffic
  158. // Wait for serve API to complete
  159. errAPI := <-serveAPIWait
  160. shutdownDaemon(d, 15)
  161. if errAPI != nil {
  162. if pfile != nil {
  163. if err := pfile.Remove(); err != nil {
  164. logrus.Error(err)
  165. }
  166. }
  167. logrus.Fatalf("Shutting down due to ServeAPI error: %v", errAPI)
  168. }
  169. }
  170. // shutdownDaemon just wraps daemon.Shutdown() to handle a timeout in case
  171. // d.Shutdown() is waiting too long to kill container or worst it's
  172. // blocked there
  173. func shutdownDaemon(d *daemon.Daemon, timeout time.Duration) {
  174. ch := make(chan struct{})
  175. go func() {
  176. d.Shutdown()
  177. close(ch)
  178. }()
  179. select {
  180. case <-ch:
  181. logrus.Debug("Clean shutdown succeded")
  182. case <-time.After(timeout * time.Second):
  183. logrus.Error("Force shutdown daemon")
  184. }
  185. }