daemon.go 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301
  1. // Package daemon exposes the functions that occur on the host server
  2. // that the Docker daemon is running.
  3. //
  4. // In implementing the various functions of the daemon, there is often
  5. // a method-specific struct for configuring the runtime behavior.
  6. package daemon
  7. import (
  8. "errors"
  9. "fmt"
  10. "io"
  11. "io/ioutil"
  12. "os"
  13. "path/filepath"
  14. "runtime"
  15. "strings"
  16. "sync"
  17. "time"
  18. "github.com/Sirupsen/logrus"
  19. "github.com/docker/docker/api"
  20. "github.com/docker/docker/api/types"
  21. "github.com/docker/docker/cliconfig"
  22. "github.com/docker/docker/daemon/events"
  23. "github.com/docker/docker/daemon/execdriver"
  24. "github.com/docker/docker/daemon/execdriver/execdrivers"
  25. "github.com/docker/docker/daemon/graphdriver"
  26. _ "github.com/docker/docker/daemon/graphdriver/vfs" // register vfs
  27. "github.com/docker/docker/daemon/logger"
  28. "github.com/docker/docker/daemon/network"
  29. derr "github.com/docker/docker/errors"
  30. "github.com/docker/docker/graph"
  31. "github.com/docker/docker/image"
  32. "github.com/docker/docker/pkg/archive"
  33. "github.com/docker/docker/pkg/broadcaster"
  34. "github.com/docker/docker/pkg/discovery"
  35. "github.com/docker/docker/pkg/fileutils"
  36. "github.com/docker/docker/pkg/graphdb"
  37. "github.com/docker/docker/pkg/idtools"
  38. "github.com/docker/docker/pkg/ioutils"
  39. "github.com/docker/docker/pkg/jsonmessage"
  40. "github.com/docker/docker/pkg/mount"
  41. "github.com/docker/docker/pkg/namesgenerator"
  42. "github.com/docker/docker/pkg/nat"
  43. "github.com/docker/docker/pkg/parsers/filters"
  44. "github.com/docker/docker/pkg/signal"
  45. "github.com/docker/docker/pkg/stringid"
  46. "github.com/docker/docker/pkg/stringutils"
  47. "github.com/docker/docker/pkg/sysinfo"
  48. "github.com/docker/docker/pkg/system"
  49. "github.com/docker/docker/pkg/truncindex"
  50. "github.com/docker/docker/registry"
  51. "github.com/docker/docker/runconfig"
  52. "github.com/docker/docker/utils"
  53. volumedrivers "github.com/docker/docker/volume/drivers"
  54. "github.com/docker/docker/volume/local"
  55. "github.com/docker/docker/volume/store"
  56. "github.com/docker/libnetwork"
  57. )
  58. var (
  59. validContainerNameChars = utils.RestrictedNameChars
  60. validContainerNamePattern = utils.RestrictedNamePattern
  61. errSystemNotSupported = errors.New("The Docker daemon is not supported on this platform.")
  62. )
  63. type contStore struct {
  64. s map[string]*Container
  65. sync.Mutex
  66. }
  67. func (c *contStore) Add(id string, cont *Container) {
  68. c.Lock()
  69. c.s[id] = cont
  70. c.Unlock()
  71. }
  72. func (c *contStore) Get(id string) *Container {
  73. c.Lock()
  74. res := c.s[id]
  75. c.Unlock()
  76. return res
  77. }
  78. func (c *contStore) Delete(id string) {
  79. c.Lock()
  80. delete(c.s, id)
  81. c.Unlock()
  82. }
  83. func (c *contStore) List() []*Container {
  84. containers := new(History)
  85. c.Lock()
  86. for _, cont := range c.s {
  87. containers.Add(cont)
  88. }
  89. c.Unlock()
  90. containers.sort()
  91. return *containers
  92. }
  93. // Daemon holds information about the Docker daemon.
  94. type Daemon struct {
  95. ID string
  96. repository string
  97. sysInitPath string
  98. containers *contStore
  99. execCommands *execStore
  100. graph *graph.Graph
  101. repositories *graph.TagStore
  102. idIndex *truncindex.TruncIndex
  103. configStore *Config
  104. containerGraphDB *graphdb.Database
  105. driver graphdriver.Driver
  106. execDriver execdriver.Driver
  107. statsCollector *statsCollector
  108. defaultLogConfig runconfig.LogConfig
  109. RegistryService *registry.Service
  110. EventsService *events.Events
  111. netController libnetwork.NetworkController
  112. volumes *store.VolumeStore
  113. discoveryWatcher discovery.Watcher
  114. root string
  115. shutdown bool
  116. uidMaps []idtools.IDMap
  117. gidMaps []idtools.IDMap
  118. }
  119. // Get looks for a container using the provided information, which could be
  120. // one of the following inputs from the caller:
  121. // - A full container ID, which will exact match a container in daemon's list
  122. // - A container name, which will only exact match via the GetByName() function
  123. // - A partial container ID prefix (e.g. short ID) of any length that is
  124. // unique enough to only return a single container object
  125. // If none of these searches succeed, an error is returned
  126. func (daemon *Daemon) Get(prefixOrName string) (*Container, error) {
  127. if containerByID := daemon.containers.Get(prefixOrName); containerByID != nil {
  128. // prefix is an exact match to a full container ID
  129. return containerByID, nil
  130. }
  131. // GetByName will match only an exact name provided; we ignore errors
  132. if containerByName, _ := daemon.GetByName(prefixOrName); containerByName != nil {
  133. // prefix is an exact match to a full container Name
  134. return containerByName, nil
  135. }
  136. containerID, indexError := daemon.idIndex.Get(prefixOrName)
  137. if indexError != nil {
  138. // When truncindex defines an error type, use that instead
  139. if indexError == truncindex.ErrNotExist {
  140. return nil, derr.ErrorCodeNoSuchContainer.WithArgs(prefixOrName)
  141. }
  142. return nil, indexError
  143. }
  144. return daemon.containers.Get(containerID), nil
  145. }
  146. // Exists returns a true if a container of the specified ID or name exists,
  147. // false otherwise.
  148. func (daemon *Daemon) Exists(id string) bool {
  149. c, _ := daemon.Get(id)
  150. return c != nil
  151. }
  152. // IsPaused returns a bool indicating if the specified container is paused.
  153. func (daemon *Daemon) IsPaused(id string) bool {
  154. c, _ := daemon.Get(id)
  155. return c.State.isPaused()
  156. }
  157. func (daemon *Daemon) containerRoot(id string) string {
  158. return filepath.Join(daemon.repository, id)
  159. }
  160. // Load reads the contents of a container from disk
  161. // This is typically done at startup.
  162. func (daemon *Daemon) load(id string) (*Container, error) {
  163. container := daemon.newBaseContainer(id)
  164. if err := container.fromDisk(); err != nil {
  165. return nil, err
  166. }
  167. if container.ID != id {
  168. return container, fmt.Errorf("Container %s is stored at %s", container.ID, id)
  169. }
  170. return container, nil
  171. }
  172. // Register makes a container object usable by the daemon as <container.ID>
  173. func (daemon *Daemon) Register(container *Container) error {
  174. if container.daemon != nil || daemon.Exists(container.ID) {
  175. return fmt.Errorf("Container is already loaded")
  176. }
  177. if err := validateID(container.ID); err != nil {
  178. return err
  179. }
  180. if err := daemon.ensureName(container); err != nil {
  181. return err
  182. }
  183. container.daemon = daemon
  184. // Attach to stdout and stderr
  185. container.stderr = new(broadcaster.Unbuffered)
  186. container.stdout = new(broadcaster.Unbuffered)
  187. // Attach to stdin
  188. if container.Config.OpenStdin {
  189. container.stdin, container.stdinPipe = io.Pipe()
  190. } else {
  191. container.stdinPipe = ioutils.NopWriteCloser(ioutil.Discard) // Silently drop stdin
  192. }
  193. // done
  194. daemon.containers.Add(container.ID, container)
  195. // don't update the Suffixarray if we're starting up
  196. // we'll waste time if we update it for every container
  197. daemon.idIndex.Add(container.ID)
  198. if container.IsRunning() {
  199. logrus.Debugf("killing old running container %s", container.ID)
  200. // Set exit code to 128 + SIGKILL (9) to properly represent unsuccessful exit
  201. container.setStoppedLocking(&execdriver.ExitStatus{ExitCode: 137})
  202. // use the current driver and ensure that the container is dead x.x
  203. cmd := &execdriver.Command{
  204. CommonCommand: execdriver.CommonCommand{
  205. ID: container.ID,
  206. },
  207. }
  208. daemon.execDriver.Terminate(cmd)
  209. container.unmountIpcMounts(mount.Unmount)
  210. if err := container.Unmount(); err != nil {
  211. logrus.Debugf("unmount error %s", err)
  212. }
  213. if err := container.toDiskLocking(); err != nil {
  214. logrus.Errorf("Error saving stopped state to disk: %v", err)
  215. }
  216. }
  217. if err := daemon.verifyVolumesInfo(container); err != nil {
  218. return err
  219. }
  220. if err := container.prepareMountPoints(); err != nil {
  221. return err
  222. }
  223. return nil
  224. }
  225. func (daemon *Daemon) ensureName(container *Container) error {
  226. if container.Name == "" {
  227. name, err := daemon.generateNewName(container.ID)
  228. if err != nil {
  229. return err
  230. }
  231. container.Name = name
  232. if err := container.toDiskLocking(); err != nil {
  233. logrus.Errorf("Error saving container name to disk: %v", err)
  234. }
  235. }
  236. return nil
  237. }
  238. func (daemon *Daemon) restore() error {
  239. type cr struct {
  240. container *Container
  241. registered bool
  242. }
  243. var (
  244. debug = os.Getenv("DEBUG") != ""
  245. currentDriver = daemon.driver.String()
  246. containers = make(map[string]*cr)
  247. )
  248. if !debug {
  249. logrus.Info("Loading containers: start.")
  250. }
  251. dir, err := ioutil.ReadDir(daemon.repository)
  252. if err != nil {
  253. return err
  254. }
  255. for _, v := range dir {
  256. id := v.Name()
  257. container, err := daemon.load(id)
  258. if !debug && logrus.GetLevel() == logrus.InfoLevel {
  259. fmt.Print(".")
  260. }
  261. if err != nil {
  262. logrus.Errorf("Failed to load container %v: %v", id, err)
  263. continue
  264. }
  265. // Ignore the container if it does not support the current driver being used by the graph
  266. if (container.Driver == "" && currentDriver == "aufs") || container.Driver == currentDriver {
  267. logrus.Debugf("Loaded container %v", container.ID)
  268. containers[container.ID] = &cr{container: container}
  269. } else {
  270. logrus.Debugf("Cannot load container %s because it was created with another graph driver.", container.ID)
  271. }
  272. }
  273. if entities := daemon.containerGraphDB.List("/", -1); entities != nil {
  274. for _, p := range entities.Paths() {
  275. if !debug && logrus.GetLevel() == logrus.InfoLevel {
  276. fmt.Print(".")
  277. }
  278. e := entities[p]
  279. if c, ok := containers[e.ID()]; ok {
  280. c.registered = true
  281. }
  282. }
  283. }
  284. group := sync.WaitGroup{}
  285. for _, c := range containers {
  286. group.Add(1)
  287. go func(container *Container, registered bool) {
  288. defer group.Done()
  289. if !registered {
  290. // Try to set the default name for a container if it exists prior to links
  291. container.Name, err = daemon.generateNewName(container.ID)
  292. if err != nil {
  293. logrus.Debugf("Setting default id - %s", err)
  294. }
  295. }
  296. if err := daemon.Register(container); err != nil {
  297. logrus.Errorf("Failed to register container %s: %s", container.ID, err)
  298. // The container register failed should not be started.
  299. return
  300. }
  301. // check the restart policy on the containers and restart any container with
  302. // the restart policy of "always"
  303. if daemon.configStore.AutoRestart && container.shouldRestart() {
  304. logrus.Debugf("Starting container %s", container.ID)
  305. if err := container.Start(); err != nil {
  306. logrus.Errorf("Failed to start container %s: %s", container.ID, err)
  307. }
  308. }
  309. }(c.container, c.registered)
  310. }
  311. group.Wait()
  312. if !debug {
  313. if logrus.GetLevel() == logrus.InfoLevel {
  314. fmt.Println()
  315. }
  316. logrus.Info("Loading containers: done.")
  317. }
  318. return nil
  319. }
  320. func (daemon *Daemon) mergeAndVerifyConfig(config *runconfig.Config, img *image.Image) error {
  321. if img != nil && img.Config != nil {
  322. if err := runconfig.Merge(config, img.Config); err != nil {
  323. return err
  324. }
  325. }
  326. if config.Entrypoint.Len() == 0 && config.Cmd.Len() == 0 {
  327. return fmt.Errorf("No command specified")
  328. }
  329. return nil
  330. }
  331. func (daemon *Daemon) generateIDAndName(name string) (string, string, error) {
  332. var (
  333. err error
  334. id = stringid.GenerateNonCryptoID()
  335. )
  336. if name == "" {
  337. if name, err = daemon.generateNewName(id); err != nil {
  338. return "", "", err
  339. }
  340. return id, name, nil
  341. }
  342. if name, err = daemon.reserveName(id, name); err != nil {
  343. return "", "", err
  344. }
  345. return id, name, nil
  346. }
  347. func (daemon *Daemon) reserveName(id, name string) (string, error) {
  348. if !validContainerNamePattern.MatchString(name) {
  349. return "", fmt.Errorf("Invalid container name (%s), only %s are allowed", name, validContainerNameChars)
  350. }
  351. if name[0] != '/' {
  352. name = "/" + name
  353. }
  354. if _, err := daemon.containerGraphDB.Set(name, id); err != nil {
  355. if !graphdb.IsNonUniqueNameError(err) {
  356. return "", err
  357. }
  358. conflictingContainer, err := daemon.GetByName(name)
  359. if err != nil {
  360. return "", err
  361. }
  362. return "", fmt.Errorf(
  363. "Conflict. The name %q is already in use by container %s. You have to remove (or rename) that container to be able to reuse that name.", strings.TrimPrefix(name, "/"),
  364. stringid.TruncateID(conflictingContainer.ID))
  365. }
  366. return name, nil
  367. }
  368. func (daemon *Daemon) generateNewName(id string) (string, error) {
  369. var name string
  370. for i := 0; i < 6; i++ {
  371. name = namesgenerator.GetRandomName(i)
  372. if name[0] != '/' {
  373. name = "/" + name
  374. }
  375. if _, err := daemon.containerGraphDB.Set(name, id); err != nil {
  376. if !graphdb.IsNonUniqueNameError(err) {
  377. return "", err
  378. }
  379. continue
  380. }
  381. return name, nil
  382. }
  383. name = "/" + stringid.TruncateID(id)
  384. if _, err := daemon.containerGraphDB.Set(name, id); err != nil {
  385. return "", err
  386. }
  387. return name, nil
  388. }
  389. func (daemon *Daemon) generateHostname(id string, config *runconfig.Config) {
  390. // Generate default hostname
  391. // FIXME: the lxc template no longer needs to set a default hostname
  392. if config.Hostname == "" {
  393. config.Hostname = id[:12]
  394. }
  395. }
  396. func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint *stringutils.StrSlice, configCmd *stringutils.StrSlice) (string, []string) {
  397. cmdSlice := configCmd.Slice()
  398. if configEntrypoint.Len() != 0 {
  399. eSlice := configEntrypoint.Slice()
  400. return eSlice[0], append(eSlice[1:], cmdSlice...)
  401. }
  402. return cmdSlice[0], cmdSlice[1:]
  403. }
  404. func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID string) (*Container, error) {
  405. var (
  406. id string
  407. err error
  408. noExplicitName = name == ""
  409. )
  410. id, name, err = daemon.generateIDAndName(name)
  411. if err != nil {
  412. return nil, err
  413. }
  414. daemon.generateHostname(id, config)
  415. entrypoint, args := daemon.getEntrypointAndArgs(config.Entrypoint, config.Cmd)
  416. base := daemon.newBaseContainer(id)
  417. base.Created = time.Now().UTC()
  418. base.Path = entrypoint
  419. base.Args = args //FIXME: de-duplicate from config
  420. base.Config = config
  421. base.hostConfig = &runconfig.HostConfig{}
  422. base.ImageID = imgID
  423. base.NetworkSettings = &network.Settings{IsAnonymousEndpoint: noExplicitName}
  424. base.Name = name
  425. base.Driver = daemon.driver.String()
  426. base.ExecDriver = daemon.execDriver.Name()
  427. return base, err
  428. }
  429. // GetFullContainerName returns a constructed container name. I think
  430. // it has to do with the fact that a container is a file on disk and
  431. // this is sort of just creating a file name.
  432. func GetFullContainerName(name string) (string, error) {
  433. if name == "" {
  434. return "", fmt.Errorf("Container name cannot be empty")
  435. }
  436. if name[0] != '/' {
  437. name = "/" + name
  438. }
  439. return name, nil
  440. }
  441. // GetByName returns a container given a name.
  442. func (daemon *Daemon) GetByName(name string) (*Container, error) {
  443. fullName, err := GetFullContainerName(name)
  444. if err != nil {
  445. return nil, err
  446. }
  447. entity := daemon.containerGraphDB.Get(fullName)
  448. if entity == nil {
  449. return nil, fmt.Errorf("Could not find entity for %s", name)
  450. }
  451. e := daemon.containers.Get(entity.ID())
  452. if e == nil {
  453. return nil, fmt.Errorf("Could not find container for entity id %s", entity.ID())
  454. }
  455. return e, nil
  456. }
  457. // GetEventFilter returns a filters.Filter for a set of filters
  458. func (daemon *Daemon) GetEventFilter(filter filters.Args) *events.Filter {
  459. // incoming container filter can be name, id or partial id, convert to
  460. // a full container id
  461. for i, cn := range filter["container"] {
  462. c, err := daemon.Get(cn)
  463. if err != nil {
  464. filter["container"][i] = ""
  465. } else {
  466. filter["container"][i] = c.ID
  467. }
  468. }
  469. return events.NewFilter(filter, daemon.GetLabels)
  470. }
  471. // SubscribeToEvents returns the currently record of events, a channel to stream new events from, and a function to cancel the stream of events.
  472. func (daemon *Daemon) SubscribeToEvents() ([]*jsonmessage.JSONMessage, chan interface{}, func()) {
  473. return daemon.EventsService.Subscribe()
  474. }
  475. // GetLabels for a container or image id
  476. func (daemon *Daemon) GetLabels(id string) map[string]string {
  477. // TODO: TestCase
  478. container := daemon.containers.Get(id)
  479. if container != nil {
  480. return container.Config.Labels
  481. }
  482. img, err := daemon.repositories.LookupImage(id)
  483. if err == nil {
  484. return img.ContainerConfig.Labels
  485. }
  486. return nil
  487. }
  488. // children returns all child containers of the container with the
  489. // given name. The containers are returned as a map from the container
  490. // name to a pointer to Container.
  491. func (daemon *Daemon) children(name string) (map[string]*Container, error) {
  492. name, err := GetFullContainerName(name)
  493. if err != nil {
  494. return nil, err
  495. }
  496. children := make(map[string]*Container)
  497. err = daemon.containerGraphDB.Walk(name, func(p string, e *graphdb.Entity) error {
  498. c, err := daemon.Get(e.ID())
  499. if err != nil {
  500. return err
  501. }
  502. children[p] = c
  503. return nil
  504. }, 0)
  505. if err != nil {
  506. return nil, err
  507. }
  508. return children, nil
  509. }
  510. // parents returns the names of the parent containers of the container
  511. // with the given name.
  512. func (daemon *Daemon) parents(name string) ([]string, error) {
  513. name, err := GetFullContainerName(name)
  514. if err != nil {
  515. return nil, err
  516. }
  517. return daemon.containerGraphDB.Parents(name)
  518. }
  519. func (daemon *Daemon) registerLink(parent, child *Container, alias string) error {
  520. fullName := filepath.Join(parent.Name, alias)
  521. if !daemon.containerGraphDB.Exists(fullName) {
  522. _, err := daemon.containerGraphDB.Set(fullName, child.ID)
  523. return err
  524. }
  525. return nil
  526. }
  527. // NewDaemon sets up everything for the daemon to be able to service
  528. // requests from the webserver.
  529. func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemon, err error) {
  530. setDefaultMtu(config)
  531. // Ensure we have compatible configuration options
  532. if err := checkConfigOptions(config); err != nil {
  533. return nil, err
  534. }
  535. // Do we have a disabled network?
  536. config.DisableBridge = isBridgeNetworkDisabled(config)
  537. // Verify the platform is supported as a daemon
  538. if !platformSupported {
  539. return nil, errSystemNotSupported
  540. }
  541. // Validate platform-specific requirements
  542. if err := checkSystem(); err != nil {
  543. return nil, err
  544. }
  545. // set up SIGUSR1 handler on Unix-like systems, or a Win32 global event
  546. // on Windows to dump Go routine stacks
  547. setupDumpStackTrap()
  548. uidMaps, gidMaps, err := setupRemappedRoot(config)
  549. if err != nil {
  550. return nil, err
  551. }
  552. rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
  553. if err != nil {
  554. return nil, err
  555. }
  556. // get the canonical path to the Docker root directory
  557. var realRoot string
  558. if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) {
  559. realRoot = config.Root
  560. } else {
  561. realRoot, err = fileutils.ReadSymlinkedDirectory(config.Root)
  562. if err != nil {
  563. return nil, fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err)
  564. }
  565. }
  566. if err = setupDaemonRoot(config, realRoot, rootUID, rootGID); err != nil {
  567. return nil, err
  568. }
  569. // set up the tmpDir to use a canonical path
  570. tmp, err := tempDir(config.Root, rootUID, rootGID)
  571. if err != nil {
  572. return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err)
  573. }
  574. realTmp, err := fileutils.ReadSymlinkedDirectory(tmp)
  575. if err != nil {
  576. return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err)
  577. }
  578. os.Setenv("TMPDIR", realTmp)
  579. // Set the default driver
  580. graphdriver.DefaultDriver = config.GraphDriver
  581. // Load storage driver
  582. driver, err := graphdriver.New(config.Root, config.GraphOptions, uidMaps, gidMaps)
  583. if err != nil {
  584. return nil, fmt.Errorf("error initializing graphdriver: %v", err)
  585. }
  586. logrus.Debugf("Using graph driver %s", driver)
  587. d := &Daemon{}
  588. d.driver = driver
  589. // Ensure the graph driver is shutdown at a later point
  590. defer func() {
  591. if err != nil {
  592. if err := d.Shutdown(); err != nil {
  593. logrus.Error(err)
  594. }
  595. }
  596. }()
  597. // Verify logging driver type
  598. if config.LogConfig.Type != "none" {
  599. if _, err := logger.GetLogDriver(config.LogConfig.Type); err != nil {
  600. return nil, fmt.Errorf("error finding the logging driver: %v", err)
  601. }
  602. }
  603. logrus.Debugf("Using default logging driver %s", config.LogConfig.Type)
  604. // Configure and validate the kernels security support
  605. if err := configureKernelSecuritySupport(config, d.driver.String()); err != nil {
  606. return nil, err
  607. }
  608. daemonRepo := filepath.Join(config.Root, "containers")
  609. if err := idtools.MkdirAllAs(daemonRepo, 0700, rootUID, rootGID); err != nil && !os.IsExist(err) {
  610. return nil, err
  611. }
  612. // Migrate the container if it is aufs and aufs is enabled
  613. if err := migrateIfDownlevel(d.driver, config.Root); err != nil {
  614. return nil, err
  615. }
  616. logrus.Debug("Creating images graph")
  617. g, err := graph.NewGraph(filepath.Join(config.Root, "graph"), d.driver, uidMaps, gidMaps)
  618. if err != nil {
  619. return nil, err
  620. }
  621. // Configure the volumes driver
  622. volStore, err := configureVolumes(config, rootUID, rootGID)
  623. if err != nil {
  624. return nil, err
  625. }
  626. trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath)
  627. if err != nil {
  628. return nil, err
  629. }
  630. trustDir := filepath.Join(config.Root, "trust")
  631. if err := system.MkdirAll(trustDir, 0700); err != nil {
  632. return nil, err
  633. }
  634. eventsService := events.New()
  635. logrus.Debug("Creating repository list")
  636. tagCfg := &graph.TagStoreConfig{
  637. Graph: g,
  638. Key: trustKey,
  639. Registry: registryService,
  640. Events: eventsService,
  641. }
  642. repositories, err := graph.NewTagStore(filepath.Join(config.Root, "repositories-"+d.driver.String()), tagCfg)
  643. if err != nil {
  644. return nil, fmt.Errorf("Couldn't create Tag store repositories-%s: %s", d.driver.String(), err)
  645. }
  646. if restorer, ok := d.driver.(graphdriver.ImageRestorer); ok {
  647. if _, err := restorer.RestoreCustomImages(repositories, g); err != nil {
  648. return nil, fmt.Errorf("Couldn't restore custom images: %s", err)
  649. }
  650. }
  651. // Discovery is only enabled when the daemon is launched with an address to advertise. When
  652. // initialized, the daemon is registered and we can store the discovery backend as its read-only
  653. // DiscoveryWatcher version.
  654. if config.ClusterStore != "" && config.ClusterAdvertise != "" {
  655. advertise, err := discovery.ParseAdvertise(config.ClusterStore, config.ClusterAdvertise)
  656. if err != nil {
  657. return nil, fmt.Errorf("discovery advertise parsing failed (%v)", err)
  658. }
  659. config.ClusterAdvertise = advertise
  660. d.discoveryWatcher, err = initDiscovery(config.ClusterStore, config.ClusterAdvertise, config.ClusterOpts)
  661. if err != nil {
  662. return nil, fmt.Errorf("discovery initialization failed (%v)", err)
  663. }
  664. } else if config.ClusterAdvertise != "" {
  665. return nil, fmt.Errorf("invalid cluster configuration. --cluster-advertise must be accompanied by --cluster-store configuration")
  666. }
  667. d.netController, err = d.initNetworkController(config)
  668. if err != nil {
  669. return nil, fmt.Errorf("Error initializing network controller: %v", err)
  670. }
  671. graphdbPath := filepath.Join(config.Root, "linkgraph.db")
  672. graph, err := graphdb.NewSqliteConn(graphdbPath)
  673. if err != nil {
  674. return nil, err
  675. }
  676. d.containerGraphDB = graph
  677. var sysInitPath string
  678. if config.ExecDriver == "lxc" {
  679. initPath, err := configureSysInit(config, rootUID, rootGID)
  680. if err != nil {
  681. return nil, err
  682. }
  683. sysInitPath = initPath
  684. }
  685. sysInfo := sysinfo.New(false)
  686. // Check if Devices cgroup is mounted, it is hard requirement for container security,
  687. // on Linux/FreeBSD.
  688. if runtime.GOOS != "windows" && !sysInfo.CgroupDevicesEnabled {
  689. return nil, fmt.Errorf("Devices cgroup isn't mounted")
  690. }
  691. ed, err := execdrivers.NewDriver(config.ExecDriver, config.ExecOptions, config.ExecRoot, config.Root, sysInitPath, sysInfo)
  692. if err != nil {
  693. return nil, err
  694. }
  695. d.ID = trustKey.PublicKey().KeyID()
  696. d.repository = daemonRepo
  697. d.containers = &contStore{s: make(map[string]*Container)}
  698. d.execCommands = newExecStore()
  699. d.graph = g
  700. d.repositories = repositories
  701. d.idIndex = truncindex.NewTruncIndex([]string{})
  702. d.configStore = config
  703. d.sysInitPath = sysInitPath
  704. d.execDriver = ed
  705. d.statsCollector = newStatsCollector(1 * time.Second)
  706. d.defaultLogConfig = config.LogConfig
  707. d.RegistryService = registryService
  708. d.EventsService = eventsService
  709. d.volumes = volStore
  710. d.root = config.Root
  711. d.uidMaps = uidMaps
  712. d.gidMaps = gidMaps
  713. if err := d.cleanupMounts(); err != nil {
  714. return nil, err
  715. }
  716. go d.execCommandGC()
  717. if err := d.restore(); err != nil {
  718. return nil, err
  719. }
  720. return d, nil
  721. }
  722. func stopContainer(c *Container) error {
  723. // TODO(windows): Handle docker restart with paused containers
  724. if c.isPaused() {
  725. // To terminate a process in freezer cgroup, we should send
  726. // SIGTERM to this process then unfreeze it, and the process will
  727. // force to terminate immediately.
  728. logrus.Debugf("Found container %s is paused, sending SIGTERM before unpause it", c.ID)
  729. sig, ok := signal.SignalMap["TERM"]
  730. if !ok {
  731. return fmt.Errorf("System doesn not support SIGTERM")
  732. }
  733. if err := c.daemon.kill(c, int(sig)); err != nil {
  734. return fmt.Errorf("sending SIGTERM to container %s with error: %v", c.ID, err)
  735. }
  736. if err := c.unpause(); err != nil {
  737. return fmt.Errorf("Failed to unpause container %s with error: %v", c.ID, err)
  738. }
  739. if _, err := c.WaitStop(10 * time.Second); err != nil {
  740. logrus.Debugf("container %s failed to exit in 10 second of SIGTERM, sending SIGKILL to force", c.ID)
  741. sig, ok := signal.SignalMap["KILL"]
  742. if !ok {
  743. return fmt.Errorf("System does not support SIGKILL")
  744. }
  745. if err := c.daemon.kill(c, int(sig)); err != nil {
  746. logrus.Errorf("Failed to SIGKILL container %s", c.ID)
  747. }
  748. c.WaitStop(-1 * time.Second)
  749. return err
  750. }
  751. }
  752. // If container failed to exit in 10 seconds of SIGTERM, then using the force
  753. if err := c.Stop(10); err != nil {
  754. return fmt.Errorf("Stop container %s with error: %v", c.ID, err)
  755. }
  756. c.WaitStop(-1 * time.Second)
  757. return nil
  758. }
  759. // Shutdown stops the daemon.
  760. func (daemon *Daemon) Shutdown() error {
  761. daemon.shutdown = true
  762. if daemon.containers != nil {
  763. group := sync.WaitGroup{}
  764. logrus.Debug("starting clean shutdown of all containers...")
  765. for _, container := range daemon.List() {
  766. if !container.IsRunning() {
  767. continue
  768. }
  769. logrus.Debugf("stopping %s", container.ID)
  770. group.Add(1)
  771. go func(c *Container) {
  772. defer group.Done()
  773. if err := stopContainer(c); err != nil {
  774. logrus.Errorf("Stop container error: %v", err)
  775. return
  776. }
  777. logrus.Debugf("container stopped %s", c.ID)
  778. }(container)
  779. }
  780. group.Wait()
  781. }
  782. // trigger libnetwork Stop only if it's initialized
  783. if daemon.netController != nil {
  784. daemon.netController.Stop()
  785. }
  786. if daemon.containerGraphDB != nil {
  787. if err := daemon.containerGraphDB.Close(); err != nil {
  788. logrus.Errorf("Error during container graph.Close(): %v", err)
  789. }
  790. }
  791. if daemon.driver != nil {
  792. if err := daemon.driver.Cleanup(); err != nil {
  793. logrus.Errorf("Error during graph storage driver.Cleanup(): %v", err)
  794. }
  795. }
  796. if err := daemon.cleanupMounts(); err != nil {
  797. return err
  798. }
  799. return nil
  800. }
  801. // Mount sets container.basefs
  802. // (is it not set coming in? why is it unset?)
  803. func (daemon *Daemon) Mount(container *Container) error {
  804. dir, err := daemon.driver.Get(container.ID, container.getMountLabel())
  805. if err != nil {
  806. return fmt.Errorf("Error getting container %s from driver %s: %s", container.ID, daemon.driver, err)
  807. }
  808. if container.basefs != dir {
  809. // The mount path reported by the graph driver should always be trusted on Windows, since the
  810. // volume path for a given mounted layer may change over time. This should only be an error
  811. // on non-Windows operating systems.
  812. if container.basefs != "" && runtime.GOOS != "windows" {
  813. daemon.driver.Put(container.ID)
  814. return fmt.Errorf("Error: driver %s is returning inconsistent paths for container %s ('%s' then '%s')",
  815. daemon.driver, container.ID, container.basefs, dir)
  816. }
  817. }
  818. container.basefs = dir
  819. return nil
  820. }
  821. func (daemon *Daemon) unmount(container *Container) error {
  822. return daemon.driver.Put(container.ID)
  823. }
  824. func (daemon *Daemon) run(c *Container, pipes *execdriver.Pipes, startCallback execdriver.DriverCallback) (execdriver.ExitStatus, error) {
  825. hooks := execdriver.Hooks{
  826. Start: startCallback,
  827. }
  828. hooks.PreStart = append(hooks.PreStart, func(processConfig *execdriver.ProcessConfig, pid int, chOOM <-chan struct{}) error {
  829. return c.setNetworkNamespaceKey(pid)
  830. })
  831. return daemon.execDriver.Run(c.command, pipes, hooks)
  832. }
  833. func (daemon *Daemon) kill(c *Container, sig int) error {
  834. return daemon.execDriver.Kill(c.command, sig)
  835. }
  836. func (daemon *Daemon) stats(c *Container) (*execdriver.ResourceStats, error) {
  837. return daemon.execDriver.Stats(c.ID)
  838. }
  839. func (daemon *Daemon) subscribeToContainerStats(c *Container) chan interface{} {
  840. return daemon.statsCollector.collect(c)
  841. }
  842. func (daemon *Daemon) unsubscribeToContainerStats(c *Container, ch chan interface{}) {
  843. daemon.statsCollector.unsubscribe(c, ch)
  844. }
  845. func (daemon *Daemon) changes(container *Container) ([]archive.Change, error) {
  846. initID := fmt.Sprintf("%s-init", container.ID)
  847. return daemon.driver.Changes(container.ID, initID)
  848. }
  849. func (daemon *Daemon) diff(container *Container) (archive.Archive, error) {
  850. initID := fmt.Sprintf("%s-init", container.ID)
  851. return daemon.driver.Diff(container.ID, initID)
  852. }
  853. func (daemon *Daemon) createRootfs(container *Container) error {
  854. // Step 1: create the container directory.
  855. // This doubles as a barrier to avoid race conditions.
  856. rootUID, rootGID, err := idtools.GetRootUIDGID(daemon.uidMaps, daemon.gidMaps)
  857. if err != nil {
  858. return err
  859. }
  860. if err := idtools.MkdirAs(container.root, 0700, rootUID, rootGID); err != nil {
  861. return err
  862. }
  863. initID := fmt.Sprintf("%s-init", container.ID)
  864. if err := daemon.driver.Create(initID, container.ImageID); err != nil {
  865. return err
  866. }
  867. initPath, err := daemon.driver.Get(initID, "")
  868. if err != nil {
  869. return err
  870. }
  871. if err := setupInitLayer(initPath, rootUID, rootGID); err != nil {
  872. if err := daemon.driver.Put(initID); err != nil {
  873. logrus.Errorf("Failed to Put init layer: %v", err)
  874. }
  875. return err
  876. }
  877. // We want to unmount init layer before we take snapshot of it
  878. // for the actual container.
  879. if err := daemon.driver.Put(initID); err != nil {
  880. return err
  881. }
  882. if err := daemon.driver.Create(container.ID, initID); err != nil {
  883. return err
  884. }
  885. return nil
  886. }
  887. // Graph returns *graph.Graph which can be using for layers graph operations.
  888. func (daemon *Daemon) Graph() *graph.Graph {
  889. return daemon.graph
  890. }
  891. // TagImage creates a tag in the repository reponame, pointing to the image named
  892. // imageName. If force is true, an existing tag with the same name may be
  893. // overwritten.
  894. func (daemon *Daemon) TagImage(repoName, tag, imageName string, force bool) error {
  895. if err := daemon.repositories.Tag(repoName, tag, imageName, force); err != nil {
  896. return err
  897. }
  898. daemon.EventsService.Log("tag", utils.ImageReference(repoName, tag), "")
  899. return nil
  900. }
  901. // PullImage initiates a pull operation. image is the repository name to pull, and
  902. // tag may be either empty, or indicate a specific tag to pull.
  903. func (daemon *Daemon) PullImage(image string, tag string, imagePullConfig *graph.ImagePullConfig) error {
  904. return daemon.repositories.Pull(image, tag, imagePullConfig)
  905. }
  906. // ImportImage imports an image, getting the archived layer data either from
  907. // inConfig (if src is "-"), or from a URI specified in src. Progress output is
  908. // written to outStream. Repository and tag names can optionally be given in
  909. // the repo and tag arguments, respectively.
  910. func (daemon *Daemon) ImportImage(src, repo, tag, msg string, inConfig io.ReadCloser, outStream io.Writer, containerConfig *runconfig.Config) error {
  911. return daemon.repositories.Import(src, repo, tag, msg, inConfig, outStream, containerConfig)
  912. }
  913. // ExportImage exports a list of images to the given output stream. The
  914. // exported images are archived into a tar when written to the output
  915. // stream. All images with the given tag and all versions containing
  916. // the same tag are exported. names is the set of tags to export, and
  917. // outStream is the writer which the images are written to.
  918. func (daemon *Daemon) ExportImage(names []string, outStream io.Writer) error {
  919. return daemon.repositories.ImageExport(names, outStream)
  920. }
  921. // PushImage initiates a push operation on the repository named localName.
  922. func (daemon *Daemon) PushImage(localName string, imagePushConfig *graph.ImagePushConfig) error {
  923. return daemon.repositories.Push(localName, imagePushConfig)
  924. }
  925. // LookupImage looks up an image by name and returns it as an ImageInspect
  926. // structure.
  927. func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) {
  928. return daemon.repositories.Lookup(name)
  929. }
  930. // LoadImage uploads a set of images into the repository. This is the
  931. // complement of ImageExport. The input stream is an uncompressed tar
  932. // ball containing images and metadata.
  933. func (daemon *Daemon) LoadImage(inTar io.ReadCloser, outStream io.Writer) error {
  934. return daemon.repositories.Load(inTar, outStream)
  935. }
  936. // ListImages returns a filtered list of images. filterArgs is a JSON-encoded set
  937. // of filter arguments which will be interpreted by pkg/parsers/filters.
  938. // filter is a shell glob string applied to repository names. The argument
  939. // named all controls whether all images in the graph are filtered, or just
  940. // the heads.
  941. func (daemon *Daemon) ListImages(filterArgs, filter string, all bool) ([]*types.Image, error) {
  942. return daemon.repositories.Images(filterArgs, filter, all)
  943. }
  944. // ImageHistory returns a slice of ImageHistory structures for the specified image
  945. // name by walking the image lineage.
  946. func (daemon *Daemon) ImageHistory(name string) ([]*types.ImageHistory, error) {
  947. return daemon.repositories.History(name)
  948. }
  949. // GetImage returns pointer to an Image struct corresponding to the given
  950. // name. The name can include an optional tag; otherwise the default tag will
  951. // be used.
  952. func (daemon *Daemon) GetImage(name string) (*image.Image, error) {
  953. return daemon.repositories.LookupImage(name)
  954. }
  955. func (daemon *Daemon) config() *Config {
  956. return daemon.configStore
  957. }
  958. func (daemon *Daemon) systemInitPath() string {
  959. return daemon.sysInitPath
  960. }
  961. // GraphDriver returns the currently used driver for processing
  962. // container layers.
  963. func (daemon *Daemon) GraphDriver() graphdriver.Driver {
  964. return daemon.driver
  965. }
  966. // ExecutionDriver returns the currently used driver for creating and
  967. // starting execs in a container.
  968. func (daemon *Daemon) ExecutionDriver() execdriver.Driver {
  969. return daemon.execDriver
  970. }
  971. func (daemon *Daemon) containerGraph() *graphdb.Database {
  972. return daemon.containerGraphDB
  973. }
  974. // GetUIDGIDMaps returns the current daemon's user namespace settings
  975. // for the full uid and gid maps which will be applied to containers
  976. // started in this instance.
  977. func (daemon *Daemon) GetUIDGIDMaps() ([]idtools.IDMap, []idtools.IDMap) {
  978. return daemon.uidMaps, daemon.gidMaps
  979. }
  980. // GetRemappedUIDGID returns the current daemon's uid and gid values
  981. // if user namespaces are in use for this daemon instance. If not
  982. // this function will return "real" root values of 0, 0.
  983. func (daemon *Daemon) GetRemappedUIDGID() (int, int) {
  984. uid, gid, _ := idtools.GetRootUIDGID(daemon.uidMaps, daemon.gidMaps)
  985. return uid, gid
  986. }
  987. // ImageGetCached returns the earliest created image that is a child
  988. // of the image with imgID, that had the same config when it was
  989. // created. nil is returned if a child cannot be found. An error is
  990. // returned if the parent image cannot be found.
  991. func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*image.Image, error) {
  992. // for now just exit if imgID has no children.
  993. // maybe parentRefs in graph could be used to store
  994. // the Image obj children for faster lookup below but this can
  995. // be quite memory hungry.
  996. if !daemon.Graph().HasChildren(imgID) {
  997. return nil, nil
  998. }
  999. // Retrieve all images
  1000. images := daemon.Graph().Map()
  1001. // Store the tree in a map of map (map[parentId][childId])
  1002. imageMap := make(map[string]map[string]struct{})
  1003. for _, img := range images {
  1004. if _, exists := imageMap[img.Parent]; !exists {
  1005. imageMap[img.Parent] = make(map[string]struct{})
  1006. }
  1007. imageMap[img.Parent][img.ID] = struct{}{}
  1008. }
  1009. // Loop on the children of the given image and check the config
  1010. var match *image.Image
  1011. for elem := range imageMap[imgID] {
  1012. img, ok := images[elem]
  1013. if !ok {
  1014. return nil, fmt.Errorf("unable to find image %q", elem)
  1015. }
  1016. if runconfig.Compare(&img.ContainerConfig, config) {
  1017. if match == nil || match.Created.Before(img.Created) {
  1018. match = img
  1019. }
  1020. }
  1021. }
  1022. return match, nil
  1023. }
  1024. // tempDir returns the default directory to use for temporary files.
  1025. func tempDir(rootDir string, rootUID, rootGID int) (string, error) {
  1026. var tmpDir string
  1027. if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" {
  1028. tmpDir = filepath.Join(rootDir, "tmp")
  1029. }
  1030. return tmpDir, idtools.MkdirAllAs(tmpDir, 0700, rootUID, rootGID)
  1031. }
  1032. func (daemon *Daemon) setHostConfig(container *Container, hostConfig *runconfig.HostConfig) error {
  1033. container.Lock()
  1034. if err := parseSecurityOpt(container, hostConfig); err != nil {
  1035. container.Unlock()
  1036. return err
  1037. }
  1038. container.Unlock()
  1039. // Do not lock while creating volumes since this could be calling out to external plugins
  1040. // Don't want to block other actions, like `docker ps` because we're waiting on an external plugin
  1041. if err := daemon.registerMountPoints(container, hostConfig); err != nil {
  1042. return err
  1043. }
  1044. container.Lock()
  1045. defer container.Unlock()
  1046. // Register any links from the host config before starting the container
  1047. if err := daemon.registerLinks(container, hostConfig); err != nil {
  1048. return err
  1049. }
  1050. container.hostConfig = hostConfig
  1051. container.toDisk()
  1052. return nil
  1053. }
  1054. func setDefaultMtu(config *Config) {
  1055. // do nothing if the config does not have the default 0 value.
  1056. if config.Mtu != 0 {
  1057. return
  1058. }
  1059. config.Mtu = defaultNetworkMtu
  1060. if routeMtu, err := getDefaultRouteMtu(); err == nil {
  1061. config.Mtu = routeMtu
  1062. }
  1063. }
  1064. var errNoDefaultRoute = errors.New("no default route was found")
  1065. // verifyContainerSettings performs validation of the hostconfig and config
  1066. // structures.
  1067. func (daemon *Daemon) verifyContainerSettings(hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) {
  1068. // First perform verification of settings common across all platforms.
  1069. if config != nil {
  1070. if config.WorkingDir != "" {
  1071. config.WorkingDir = filepath.FromSlash(config.WorkingDir) // Ensure in platform semantics
  1072. if !system.IsAbs(config.WorkingDir) {
  1073. return nil, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path.", config.WorkingDir)
  1074. }
  1075. }
  1076. if len(config.StopSignal) > 0 {
  1077. _, err := signal.ParseSignal(config.StopSignal)
  1078. if err != nil {
  1079. return nil, err
  1080. }
  1081. }
  1082. }
  1083. if hostConfig == nil {
  1084. return nil, nil
  1085. }
  1086. for port := range hostConfig.PortBindings {
  1087. _, portStr := nat.SplitProtoPort(string(port))
  1088. if _, err := nat.ParsePort(portStr); err != nil {
  1089. return nil, fmt.Errorf("Invalid port specification: %q", portStr)
  1090. }
  1091. for _, pb := range hostConfig.PortBindings[port] {
  1092. _, err := nat.NewPort(nat.SplitProtoPort(pb.HostPort))
  1093. if err != nil {
  1094. return nil, fmt.Errorf("Invalid port specification: %q", pb.HostPort)
  1095. }
  1096. }
  1097. }
  1098. // Now do platform-specific verification
  1099. return verifyPlatformContainerSettings(daemon, hostConfig, config)
  1100. }
  1101. func configureVolumes(config *Config, rootUID, rootGID int) (*store.VolumeStore, error) {
  1102. volumesDriver, err := local.New(config.Root, rootUID, rootGID)
  1103. if err != nil {
  1104. return nil, err
  1105. }
  1106. volumedrivers.Register(volumesDriver, volumesDriver.Name())
  1107. s := store.New()
  1108. s.AddAll(volumesDriver.List())
  1109. return s, nil
  1110. }
  1111. // AuthenticateToRegistry checks the validity of credentials in authConfig
  1112. func (daemon *Daemon) AuthenticateToRegistry(authConfig *cliconfig.AuthConfig) (string, error) {
  1113. return daemon.RegistryService.Auth(authConfig)
  1114. }
  1115. // SearchRegistryForImages queries the registry for images matching
  1116. // term. authConfig is used to login.
  1117. func (daemon *Daemon) SearchRegistryForImages(term string,
  1118. authConfig *cliconfig.AuthConfig,
  1119. headers map[string][]string) (*registry.SearchResults, error) {
  1120. return daemon.RegistryService.Search(term, authConfig, headers)
  1121. }