daemon.go 5.2 KB

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