daemon.go 38 KB

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