container_operations_unix.go 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251
  1. // +build linux freebsd
  2. package daemon
  3. import (
  4. "fmt"
  5. "net"
  6. "os"
  7. "path"
  8. "path/filepath"
  9. "strconv"
  10. "strings"
  11. "syscall"
  12. "time"
  13. "github.com/Sirupsen/logrus"
  14. "github.com/docker/docker/container"
  15. "github.com/docker/docker/daemon/execdriver"
  16. "github.com/docker/docker/daemon/links"
  17. "github.com/docker/docker/daemon/network"
  18. "github.com/docker/docker/errors"
  19. "github.com/docker/docker/pkg/fileutils"
  20. "github.com/docker/docker/pkg/idtools"
  21. "github.com/docker/docker/pkg/mount"
  22. "github.com/docker/docker/pkg/stringid"
  23. "github.com/docker/docker/runconfig"
  24. containertypes "github.com/docker/engine-api/types/container"
  25. networktypes "github.com/docker/engine-api/types/network"
  26. "github.com/docker/go-connections/nat"
  27. "github.com/docker/go-units"
  28. "github.com/docker/libnetwork"
  29. "github.com/docker/libnetwork/netlabel"
  30. "github.com/docker/libnetwork/options"
  31. "github.com/docker/libnetwork/types"
  32. "github.com/opencontainers/runc/libcontainer/configs"
  33. "github.com/opencontainers/runc/libcontainer/devices"
  34. "github.com/opencontainers/runc/libcontainer/label"
  35. )
  36. func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]string, error) {
  37. var env []string
  38. children := daemon.children(container)
  39. bridgeSettings := container.NetworkSettings.Networks["bridge"]
  40. if bridgeSettings == nil {
  41. return nil, nil
  42. }
  43. for linkAlias, child := range children {
  44. if !child.IsRunning() {
  45. return nil, fmt.Errorf("Cannot link to a non running container: %s AS %s", child.Name, linkAlias)
  46. }
  47. childBridgeSettings := child.NetworkSettings.Networks["bridge"]
  48. if childBridgeSettings == nil {
  49. return nil, fmt.Errorf("container %s not attached to default bridge network", child.ID)
  50. }
  51. link := links.NewLink(
  52. bridgeSettings.IPAddress,
  53. childBridgeSettings.IPAddress,
  54. linkAlias,
  55. child.Config.Env,
  56. child.Config.ExposedPorts,
  57. )
  58. for _, envVar := range link.ToEnv() {
  59. env = append(env, envVar)
  60. }
  61. }
  62. return env, nil
  63. }
  64. func (daemon *Daemon) populateCommand(c *container.Container, env []string) error {
  65. var en *execdriver.Network
  66. if !c.Config.NetworkDisabled {
  67. en = &execdriver.Network{}
  68. if !daemon.execDriver.SupportsHooks() || c.HostConfig.NetworkMode.IsHost() {
  69. en.NamespacePath = c.NetworkSettings.SandboxKey
  70. }
  71. if c.HostConfig.NetworkMode.IsContainer() {
  72. nc, err := daemon.getNetworkedContainer(c.ID, c.HostConfig.NetworkMode.ConnectedContainer())
  73. if err != nil {
  74. return err
  75. }
  76. en.ContainerID = nc.ID
  77. }
  78. }
  79. ipc := &execdriver.Ipc{}
  80. var err error
  81. c.ShmPath, err = c.ShmResourcePath()
  82. if err != nil {
  83. return err
  84. }
  85. if c.HostConfig.IpcMode.IsContainer() {
  86. ic, err := daemon.getIpcContainer(c)
  87. if err != nil {
  88. return err
  89. }
  90. ipc.ContainerID = ic.ID
  91. c.ShmPath = ic.ShmPath
  92. } else {
  93. ipc.HostIpc = c.HostConfig.IpcMode.IsHost()
  94. if ipc.HostIpc {
  95. if _, err := os.Stat("/dev/shm"); err != nil {
  96. return fmt.Errorf("/dev/shm is not mounted, but must be for --ipc=host")
  97. }
  98. c.ShmPath = "/dev/shm"
  99. }
  100. }
  101. pid := &execdriver.Pid{}
  102. pid.HostPid = c.HostConfig.PidMode.IsHost()
  103. uts := &execdriver.UTS{
  104. HostUTS: c.HostConfig.UTSMode.IsHost(),
  105. }
  106. // Build lists of devices allowed and created within the container.
  107. var userSpecifiedDevices []*configs.Device
  108. for _, deviceMapping := range c.HostConfig.Devices {
  109. devs, err := getDevicesFromPath(deviceMapping)
  110. if err != nil {
  111. return err
  112. }
  113. userSpecifiedDevices = append(userSpecifiedDevices, devs...)
  114. }
  115. allowedDevices := mergeDevices(configs.DefaultAllowedDevices, userSpecifiedDevices)
  116. autoCreatedDevices := mergeDevices(configs.DefaultAutoCreatedDevices, userSpecifiedDevices)
  117. var rlimits []*units.Rlimit
  118. ulimits := c.HostConfig.Ulimits
  119. // Merge ulimits with daemon defaults
  120. ulIdx := make(map[string]*units.Ulimit)
  121. for _, ul := range ulimits {
  122. ulIdx[ul.Name] = ul
  123. }
  124. for name, ul := range daemon.configStore.Ulimits {
  125. if _, exists := ulIdx[name]; !exists {
  126. ulimits = append(ulimits, ul)
  127. }
  128. }
  129. weightDevices, err := getBlkioWeightDevices(c.HostConfig)
  130. if err != nil {
  131. return err
  132. }
  133. readBpsDevice, err := getBlkioReadBpsDevices(c.HostConfig)
  134. if err != nil {
  135. return err
  136. }
  137. writeBpsDevice, err := getBlkioWriteBpsDevices(c.HostConfig)
  138. if err != nil {
  139. return err
  140. }
  141. readIOpsDevice, err := getBlkioReadIOpsDevices(c.HostConfig)
  142. if err != nil {
  143. return err
  144. }
  145. writeIOpsDevice, err := getBlkioWriteIOpsDevices(c.HostConfig)
  146. if err != nil {
  147. return err
  148. }
  149. for _, limit := range ulimits {
  150. rl, err := limit.GetRlimit()
  151. if err != nil {
  152. return err
  153. }
  154. rlimits = append(rlimits, rl)
  155. }
  156. resources := &execdriver.Resources{
  157. CommonResources: execdriver.CommonResources{
  158. Memory: c.HostConfig.Memory,
  159. MemoryReservation: c.HostConfig.MemoryReservation,
  160. CPUShares: c.HostConfig.CPUShares,
  161. BlkioWeight: c.HostConfig.BlkioWeight,
  162. },
  163. MemorySwap: c.HostConfig.MemorySwap,
  164. KernelMemory: c.HostConfig.KernelMemory,
  165. CpusetCpus: c.HostConfig.CpusetCpus,
  166. CpusetMems: c.HostConfig.CpusetMems,
  167. CPUPeriod: c.HostConfig.CPUPeriod,
  168. CPUQuota: c.HostConfig.CPUQuota,
  169. Rlimits: rlimits,
  170. BlkioWeightDevice: weightDevices,
  171. BlkioThrottleReadBpsDevice: readBpsDevice,
  172. BlkioThrottleWriteBpsDevice: writeBpsDevice,
  173. BlkioThrottleReadIOpsDevice: readIOpsDevice,
  174. BlkioThrottleWriteIOpsDevice: writeIOpsDevice,
  175. PidsLimit: c.HostConfig.PidsLimit,
  176. MemorySwappiness: -1,
  177. }
  178. if c.HostConfig.OomKillDisable != nil {
  179. resources.OomKillDisable = *c.HostConfig.OomKillDisable
  180. }
  181. if c.HostConfig.MemorySwappiness != nil {
  182. resources.MemorySwappiness = *c.HostConfig.MemorySwappiness
  183. }
  184. processConfig := execdriver.ProcessConfig{
  185. CommonProcessConfig: execdriver.CommonProcessConfig{
  186. Entrypoint: c.Path,
  187. Arguments: c.Args,
  188. Tty: c.Config.Tty,
  189. },
  190. Privileged: c.HostConfig.Privileged,
  191. User: c.Config.User,
  192. }
  193. processConfig.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
  194. processConfig.Env = env
  195. remappedRoot := &execdriver.User{}
  196. rootUID, rootGID := daemon.GetRemappedUIDGID()
  197. if rootUID != 0 {
  198. remappedRoot.UID = rootUID
  199. remappedRoot.GID = rootGID
  200. }
  201. uidMap, gidMap := daemon.GetUIDGIDMaps()
  202. if !daemon.seccompEnabled {
  203. if c.SeccompProfile != "" && c.SeccompProfile != "unconfined" {
  204. return fmt.Errorf("Seccomp is not enabled in your kernel, cannot run a custom seccomp profile.")
  205. }
  206. logrus.Warn("Seccomp is not enabled in your kernel, running container without default profile.")
  207. c.SeccompProfile = "unconfined"
  208. }
  209. defaultCgroupParent := "/docker"
  210. if daemon.configStore.CgroupParent != "" {
  211. defaultCgroupParent = daemon.configStore.CgroupParent
  212. } else if daemon.usingSystemd() {
  213. defaultCgroupParent = "system.slice"
  214. }
  215. c.Command = &execdriver.Command{
  216. CommonCommand: execdriver.CommonCommand{
  217. ID: c.ID,
  218. MountLabel: c.GetMountLabel(),
  219. Network: en,
  220. ProcessConfig: processConfig,
  221. ProcessLabel: c.GetProcessLabel(),
  222. Rootfs: c.BaseFS,
  223. Resources: resources,
  224. WorkingDir: c.Config.WorkingDir,
  225. },
  226. AllowedDevices: allowedDevices,
  227. AppArmorProfile: c.AppArmorProfile,
  228. AutoCreatedDevices: autoCreatedDevices,
  229. CapAdd: c.HostConfig.CapAdd,
  230. CapDrop: c.HostConfig.CapDrop,
  231. CgroupParent: defaultCgroupParent,
  232. GIDMapping: gidMap,
  233. GroupAdd: c.HostConfig.GroupAdd,
  234. Ipc: ipc,
  235. OomScoreAdj: c.HostConfig.OomScoreAdj,
  236. Pid: pid,
  237. ReadonlyRootfs: c.HostConfig.ReadonlyRootfs,
  238. RemappedRoot: remappedRoot,
  239. SeccompProfile: c.SeccompProfile,
  240. UIDMapping: uidMap,
  241. UTS: uts,
  242. NoNewPrivileges: c.NoNewPrivileges,
  243. }
  244. if c.HostConfig.CgroupParent != "" {
  245. c.Command.CgroupParent = c.HostConfig.CgroupParent
  246. }
  247. return nil
  248. }
  249. // getSize returns the real size & virtual size of the container.
  250. func (daemon *Daemon) getSize(container *container.Container) (int64, int64) {
  251. var (
  252. sizeRw, sizeRootfs int64
  253. err error
  254. )
  255. if err := daemon.Mount(container); err != nil {
  256. logrus.Errorf("Failed to compute size of container rootfs %s: %s", container.ID, err)
  257. return sizeRw, sizeRootfs
  258. }
  259. defer daemon.Unmount(container)
  260. sizeRw, err = container.RWLayer.Size()
  261. if err != nil {
  262. logrus.Errorf("Driver %s couldn't return diff size of container %s: %s",
  263. daemon.GraphDriverName(), container.ID, err)
  264. // FIXME: GetSize should return an error. Not changing it now in case
  265. // there is a side-effect.
  266. sizeRw = -1
  267. }
  268. if parent := container.RWLayer.Parent(); parent != nil {
  269. sizeRootfs, err = parent.Size()
  270. if err != nil {
  271. sizeRootfs = -1
  272. } else if sizeRw != -1 {
  273. sizeRootfs += sizeRw
  274. }
  275. }
  276. return sizeRw, sizeRootfs
  277. }
  278. func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libnetwork.Network) ([]libnetwork.SandboxOption, error) {
  279. var (
  280. sboxOptions []libnetwork.SandboxOption
  281. err error
  282. dns []string
  283. dnsSearch []string
  284. dnsOptions []string
  285. bindings = make(nat.PortMap)
  286. pbList []types.PortBinding
  287. exposeList []types.TransportPort
  288. )
  289. sboxOptions = append(sboxOptions, libnetwork.OptionHostname(container.Config.Hostname),
  290. libnetwork.OptionDomainname(container.Config.Domainname))
  291. if container.HostConfig.NetworkMode.IsHost() {
  292. sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox())
  293. sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts"))
  294. sboxOptions = append(sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf"))
  295. } else if daemon.execDriver.SupportsHooks() {
  296. // OptionUseExternalKey is mandatory for userns support.
  297. // But optional for non-userns support
  298. sboxOptions = append(sboxOptions, libnetwork.OptionUseExternalKey())
  299. }
  300. container.HostsPath, err = container.GetRootResourcePath("hosts")
  301. if err != nil {
  302. return nil, err
  303. }
  304. sboxOptions = append(sboxOptions, libnetwork.OptionHostsPath(container.HostsPath))
  305. container.ResolvConfPath, err = container.GetRootResourcePath("resolv.conf")
  306. if err != nil {
  307. return nil, err
  308. }
  309. sboxOptions = append(sboxOptions, libnetwork.OptionResolvConfPath(container.ResolvConfPath))
  310. if len(container.HostConfig.DNS) > 0 {
  311. dns = container.HostConfig.DNS
  312. } else if len(daemon.configStore.DNS) > 0 {
  313. dns = daemon.configStore.DNS
  314. }
  315. for _, d := range dns {
  316. sboxOptions = append(sboxOptions, libnetwork.OptionDNS(d))
  317. }
  318. if len(container.HostConfig.DNSSearch) > 0 {
  319. dnsSearch = container.HostConfig.DNSSearch
  320. } else if len(daemon.configStore.DNSSearch) > 0 {
  321. dnsSearch = daemon.configStore.DNSSearch
  322. }
  323. for _, ds := range dnsSearch {
  324. sboxOptions = append(sboxOptions, libnetwork.OptionDNSSearch(ds))
  325. }
  326. if len(container.HostConfig.DNSOptions) > 0 {
  327. dnsOptions = container.HostConfig.DNSOptions
  328. } else if len(daemon.configStore.DNSOptions) > 0 {
  329. dnsOptions = daemon.configStore.DNSOptions
  330. }
  331. for _, ds := range dnsOptions {
  332. sboxOptions = append(sboxOptions, libnetwork.OptionDNSOptions(ds))
  333. }
  334. if container.NetworkSettings.SecondaryIPAddresses != nil {
  335. name := container.Config.Hostname
  336. if container.Config.Domainname != "" {
  337. name = name + "." + container.Config.Domainname
  338. }
  339. for _, a := range container.NetworkSettings.SecondaryIPAddresses {
  340. sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(name, a.Addr))
  341. }
  342. }
  343. for _, extraHost := range container.HostConfig.ExtraHosts {
  344. // allow IPv6 addresses in extra hosts; only split on first ":"
  345. parts := strings.SplitN(extraHost, ":", 2)
  346. sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(parts[0], parts[1]))
  347. }
  348. if container.HostConfig.PortBindings != nil {
  349. for p, b := range container.HostConfig.PortBindings {
  350. bindings[p] = []nat.PortBinding{}
  351. for _, bb := range b {
  352. bindings[p] = append(bindings[p], nat.PortBinding{
  353. HostIP: bb.HostIP,
  354. HostPort: bb.HostPort,
  355. })
  356. }
  357. }
  358. }
  359. portSpecs := container.Config.ExposedPorts
  360. ports := make([]nat.Port, len(portSpecs))
  361. var i int
  362. for p := range portSpecs {
  363. ports[i] = p
  364. i++
  365. }
  366. nat.SortPortMap(ports, bindings)
  367. for _, port := range ports {
  368. expose := types.TransportPort{}
  369. expose.Proto = types.ParseProtocol(port.Proto())
  370. expose.Port = uint16(port.Int())
  371. exposeList = append(exposeList, expose)
  372. pb := types.PortBinding{Port: expose.Port, Proto: expose.Proto}
  373. binding := bindings[port]
  374. for i := 0; i < len(binding); i++ {
  375. pbCopy := pb.GetCopy()
  376. newP, err := nat.NewPort(nat.SplitProtoPort(binding[i].HostPort))
  377. var portStart, portEnd int
  378. if err == nil {
  379. portStart, portEnd, err = newP.Range()
  380. }
  381. if err != nil {
  382. return nil, fmt.Errorf("Error parsing HostPort value(%s):%v", binding[i].HostPort, err)
  383. }
  384. pbCopy.HostPort = uint16(portStart)
  385. pbCopy.HostPortEnd = uint16(portEnd)
  386. pbCopy.HostIP = net.ParseIP(binding[i].HostIP)
  387. pbList = append(pbList, pbCopy)
  388. }
  389. if container.HostConfig.PublishAllPorts && len(binding) == 0 {
  390. pbList = append(pbList, pb)
  391. }
  392. }
  393. sboxOptions = append(sboxOptions,
  394. libnetwork.OptionPortMapping(pbList),
  395. libnetwork.OptionExposedPorts(exposeList))
  396. // Link feature is supported only for the default bridge network.
  397. // return if this call to build join options is not for default bridge network
  398. if n.Name() != "bridge" {
  399. return sboxOptions, nil
  400. }
  401. ep, _ := container.GetEndpointInNetwork(n)
  402. if ep == nil {
  403. return sboxOptions, nil
  404. }
  405. var childEndpoints, parentEndpoints []string
  406. children := daemon.children(container)
  407. for linkAlias, child := range children {
  408. if !isLinkable(child) {
  409. return nil, fmt.Errorf("Cannot link to %s, as it does not belong to the default network", child.Name)
  410. }
  411. _, alias := path.Split(linkAlias)
  412. // allow access to the linked container via the alias, real name, and container hostname
  413. aliasList := alias + " " + child.Config.Hostname
  414. // only add the name if alias isn't equal to the name
  415. if alias != child.Name[1:] {
  416. aliasList = aliasList + " " + child.Name[1:]
  417. }
  418. sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.Networks["bridge"].IPAddress))
  419. cEndpoint, _ := child.GetEndpointInNetwork(n)
  420. if cEndpoint != nil && cEndpoint.ID() != "" {
  421. childEndpoints = append(childEndpoints, cEndpoint.ID())
  422. }
  423. }
  424. bridgeSettings := container.NetworkSettings.Networks["bridge"]
  425. for alias, parent := range daemon.parents(container) {
  426. if daemon.configStore.DisableBridge || !container.HostConfig.NetworkMode.IsPrivate() {
  427. continue
  428. }
  429. _, alias = path.Split(alias)
  430. logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", parent.ID, alias, bridgeSettings.IPAddress)
  431. sboxOptions = append(sboxOptions, libnetwork.OptionParentUpdate(
  432. parent.ID,
  433. alias,
  434. bridgeSettings.IPAddress,
  435. ))
  436. if ep.ID() != "" {
  437. parentEndpoints = append(parentEndpoints, ep.ID())
  438. }
  439. }
  440. linkOptions := options.Generic{
  441. netlabel.GenericData: options.Generic{
  442. "ParentEndpoints": parentEndpoints,
  443. "ChildEndpoints": childEndpoints,
  444. },
  445. }
  446. sboxOptions = append(sboxOptions, libnetwork.OptionGeneric(linkOptions))
  447. return sboxOptions, nil
  448. }
  449. func (daemon *Daemon) updateNetworkSettings(container *container.Container, n libnetwork.Network) error {
  450. if container.NetworkSettings == nil {
  451. container.NetworkSettings = &network.Settings{Networks: make(map[string]*networktypes.EndpointSettings)}
  452. }
  453. if !container.HostConfig.NetworkMode.IsHost() && containertypes.NetworkMode(n.Type()).IsHost() {
  454. return runconfig.ErrConflictHostNetwork
  455. }
  456. for s := range container.NetworkSettings.Networks {
  457. sn, err := daemon.FindNetwork(s)
  458. if err != nil {
  459. continue
  460. }
  461. if sn.Name() == n.Name() {
  462. // Avoid duplicate config
  463. return nil
  464. }
  465. if !containertypes.NetworkMode(sn.Type()).IsPrivate() ||
  466. !containertypes.NetworkMode(n.Type()).IsPrivate() {
  467. return runconfig.ErrConflictSharedNetwork
  468. }
  469. if containertypes.NetworkMode(sn.Name()).IsNone() ||
  470. containertypes.NetworkMode(n.Name()).IsNone() {
  471. return runconfig.ErrConflictNoNetwork
  472. }
  473. }
  474. if _, ok := container.NetworkSettings.Networks[n.Name()]; !ok {
  475. container.NetworkSettings.Networks[n.Name()] = new(networktypes.EndpointSettings)
  476. }
  477. return nil
  478. }
  479. func (daemon *Daemon) updateEndpointNetworkSettings(container *container.Container, n libnetwork.Network, ep libnetwork.Endpoint) error {
  480. if err := container.BuildEndpointInfo(n, ep); err != nil {
  481. return err
  482. }
  483. if container.HostConfig.NetworkMode == containertypes.NetworkMode("bridge") {
  484. container.NetworkSettings.Bridge = daemon.configStore.bridgeConfig.Iface
  485. }
  486. return nil
  487. }
  488. // UpdateNetwork is used to update the container's network (e.g. when linked containers
  489. // get removed/unlinked).
  490. func (daemon *Daemon) updateNetwork(container *container.Container) error {
  491. ctrl := daemon.netController
  492. sid := container.NetworkSettings.SandboxID
  493. sb, err := ctrl.SandboxByID(sid)
  494. if err != nil {
  495. return fmt.Errorf("error locating sandbox id %s: %v", sid, err)
  496. }
  497. // Find if container is connected to the default bridge network
  498. var n libnetwork.Network
  499. for name := range container.NetworkSettings.Networks {
  500. sn, err := daemon.FindNetwork(name)
  501. if err != nil {
  502. continue
  503. }
  504. if sn.Name() == "bridge" {
  505. n = sn
  506. break
  507. }
  508. }
  509. if n == nil {
  510. // Not connected to the default bridge network; Nothing to do
  511. return nil
  512. }
  513. options, err := daemon.buildSandboxOptions(container, n)
  514. if err != nil {
  515. return fmt.Errorf("Update network failed: %v", err)
  516. }
  517. if err := sb.Refresh(options...); err != nil {
  518. return fmt.Errorf("Update network failed: Failure in refresh sandbox %s: %v", sid, err)
  519. }
  520. return nil
  521. }
  522. // updateContainerNetworkSettings update the network settings
  523. func (daemon *Daemon) updateContainerNetworkSettings(container *container.Container, endpointsConfig map[string]*networktypes.EndpointSettings) error {
  524. var (
  525. n libnetwork.Network
  526. err error
  527. )
  528. mode := container.HostConfig.NetworkMode
  529. if container.Config.NetworkDisabled || mode.IsContainer() {
  530. return nil
  531. }
  532. networkName := mode.NetworkName()
  533. if mode.IsDefault() {
  534. networkName = daemon.netController.Config().Daemon.DefaultNetwork
  535. }
  536. if mode.IsUserDefined() {
  537. n, err = daemon.FindNetwork(networkName)
  538. if err != nil {
  539. return err
  540. }
  541. networkName = n.Name()
  542. }
  543. if container.NetworkSettings == nil {
  544. container.NetworkSettings = &network.Settings{}
  545. }
  546. if len(endpointsConfig) > 0 {
  547. container.NetworkSettings.Networks = endpointsConfig
  548. }
  549. if container.NetworkSettings.Networks == nil {
  550. container.NetworkSettings.Networks = make(map[string]*networktypes.EndpointSettings)
  551. container.NetworkSettings.Networks[networkName] = new(networktypes.EndpointSettings)
  552. }
  553. if !mode.IsUserDefined() {
  554. return nil
  555. }
  556. // Make sure to internally store the per network endpoint config by network name
  557. if _, ok := container.NetworkSettings.Networks[networkName]; ok {
  558. return nil
  559. }
  560. if nwConfig, ok := container.NetworkSettings.Networks[n.ID()]; ok {
  561. container.NetworkSettings.Networks[networkName] = nwConfig
  562. delete(container.NetworkSettings.Networks, n.ID())
  563. return nil
  564. }
  565. return nil
  566. }
  567. func (daemon *Daemon) allocateNetwork(container *container.Container) error {
  568. controller := daemon.netController
  569. // Cleanup any stale sandbox left over due to ungraceful daemon shutdown
  570. if err := controller.SandboxDestroy(container.ID); err != nil {
  571. logrus.Errorf("failed to cleanup up stale network sandbox for container %s", container.ID)
  572. }
  573. updateSettings := false
  574. if len(container.NetworkSettings.Networks) == 0 {
  575. if container.Config.NetworkDisabled || container.HostConfig.NetworkMode.IsContainer() {
  576. return nil
  577. }
  578. err := daemon.updateContainerNetworkSettings(container, nil)
  579. if err != nil {
  580. return err
  581. }
  582. updateSettings = true
  583. }
  584. for n, nConf := range container.NetworkSettings.Networks {
  585. if err := daemon.connectToNetwork(container, n, nConf, updateSettings); err != nil {
  586. return err
  587. }
  588. }
  589. return container.WriteHostConfig()
  590. }
  591. func (daemon *Daemon) getNetworkSandbox(container *container.Container) libnetwork.Sandbox {
  592. var sb libnetwork.Sandbox
  593. daemon.netController.WalkSandboxes(func(s libnetwork.Sandbox) bool {
  594. if s.ContainerID() == container.ID {
  595. sb = s
  596. return true
  597. }
  598. return false
  599. })
  600. return sb
  601. }
  602. // hasUserDefinedIPAddress returns whether the passed endpoint configuration contains IP address configuration
  603. func hasUserDefinedIPAddress(epConfig *networktypes.EndpointSettings) bool {
  604. return epConfig != nil && epConfig.IPAMConfig != nil && (len(epConfig.IPAMConfig.IPv4Address) > 0 || len(epConfig.IPAMConfig.IPv6Address) > 0)
  605. }
  606. // User specified ip address is acceptable only for networks with user specified subnets.
  607. func validateNetworkingConfig(n libnetwork.Network, epConfig *networktypes.EndpointSettings) error {
  608. if n == nil || epConfig == nil {
  609. return nil
  610. }
  611. if !hasUserDefinedIPAddress(epConfig) {
  612. return nil
  613. }
  614. _, _, nwIPv4Configs, nwIPv6Configs := n.Info().IpamConfig()
  615. for _, s := range []struct {
  616. ipConfigured bool
  617. subnetConfigs []*libnetwork.IpamConf
  618. }{
  619. {
  620. ipConfigured: len(epConfig.IPAMConfig.IPv4Address) > 0,
  621. subnetConfigs: nwIPv4Configs,
  622. },
  623. {
  624. ipConfigured: len(epConfig.IPAMConfig.IPv6Address) > 0,
  625. subnetConfigs: nwIPv6Configs,
  626. },
  627. } {
  628. if s.ipConfigured {
  629. foundSubnet := false
  630. for _, cfg := range s.subnetConfigs {
  631. if len(cfg.PreferredPool) > 0 {
  632. foundSubnet = true
  633. break
  634. }
  635. }
  636. if !foundSubnet {
  637. return runconfig.ErrUnsupportedNetworkNoSubnetAndIP
  638. }
  639. }
  640. }
  641. return nil
  642. }
  643. // cleanOperationalData resets the operational data from the passed endpoint settings
  644. func cleanOperationalData(es *networktypes.EndpointSettings) {
  645. es.EndpointID = ""
  646. es.Gateway = ""
  647. es.IPAddress = ""
  648. es.IPPrefixLen = 0
  649. es.IPv6Gateway = ""
  650. es.GlobalIPv6Address = ""
  651. es.GlobalIPv6PrefixLen = 0
  652. es.MacAddress = ""
  653. }
  654. func (daemon *Daemon) updateNetworkConfig(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (libnetwork.Network, error) {
  655. if container.HostConfig.NetworkMode.IsContainer() {
  656. return nil, runconfig.ErrConflictSharedNetwork
  657. }
  658. if containertypes.NetworkMode(idOrName).IsBridge() &&
  659. daemon.configStore.DisableBridge {
  660. container.Config.NetworkDisabled = true
  661. return nil, nil
  662. }
  663. if !containertypes.NetworkMode(idOrName).IsUserDefined() {
  664. if hasUserDefinedIPAddress(endpointConfig) {
  665. return nil, runconfig.ErrUnsupportedNetworkAndIP
  666. }
  667. if endpointConfig != nil && len(endpointConfig.Aliases) > 0 {
  668. return nil, runconfig.ErrUnsupportedNetworkAndAlias
  669. }
  670. }
  671. n, err := daemon.FindNetwork(idOrName)
  672. if err != nil {
  673. return nil, err
  674. }
  675. if err := validateNetworkingConfig(n, endpointConfig); err != nil {
  676. return nil, err
  677. }
  678. if updateSettings {
  679. if err := daemon.updateNetworkSettings(container, n); err != nil {
  680. return nil, err
  681. }
  682. }
  683. return n, nil
  684. }
  685. // ConnectToNetwork connects a container to a network
  686. func (daemon *Daemon) ConnectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings) error {
  687. if !container.Running {
  688. if container.RemovalInProgress || container.Dead {
  689. return errRemovalContainer(container.ID)
  690. }
  691. if _, err := daemon.updateNetworkConfig(container, idOrName, endpointConfig, true); err != nil {
  692. return err
  693. }
  694. if endpointConfig != nil {
  695. container.NetworkSettings.Networks[idOrName] = endpointConfig
  696. }
  697. } else {
  698. if err := daemon.connectToNetwork(container, idOrName, endpointConfig, true); err != nil {
  699. return err
  700. }
  701. }
  702. if err := container.ToDiskLocking(); err != nil {
  703. return fmt.Errorf("Error saving container to disk: %v", err)
  704. }
  705. return nil
  706. }
  707. func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (err error) {
  708. n, err := daemon.updateNetworkConfig(container, idOrName, endpointConfig, updateSettings)
  709. if err != nil {
  710. return err
  711. }
  712. if n == nil {
  713. return nil
  714. }
  715. controller := daemon.netController
  716. sb := daemon.getNetworkSandbox(container)
  717. createOptions, err := container.BuildCreateEndpointOptions(n, endpointConfig, sb)
  718. if err != nil {
  719. return err
  720. }
  721. endpointName := strings.TrimPrefix(container.Name, "/")
  722. ep, err := n.CreateEndpoint(endpointName, createOptions...)
  723. if err != nil {
  724. return err
  725. }
  726. defer func() {
  727. if err != nil {
  728. if e := ep.Delete(false); e != nil {
  729. logrus.Warnf("Could not rollback container connection to network %s", idOrName)
  730. }
  731. }
  732. }()
  733. if endpointConfig != nil {
  734. container.NetworkSettings.Networks[n.Name()] = endpointConfig
  735. }
  736. if err := daemon.updateEndpointNetworkSettings(container, n, ep); err != nil {
  737. return err
  738. }
  739. if sb == nil {
  740. options, err := daemon.buildSandboxOptions(container, n)
  741. if err != nil {
  742. return err
  743. }
  744. sb, err = controller.NewSandbox(container.ID, options...)
  745. if err != nil {
  746. return err
  747. }
  748. container.UpdateSandboxNetworkSettings(sb)
  749. }
  750. joinOptions, err := container.BuildJoinOptions(n)
  751. if err != nil {
  752. return err
  753. }
  754. if err := ep.Join(sb, joinOptions...); err != nil {
  755. return err
  756. }
  757. if err := container.UpdateJoinInfo(n, ep); err != nil {
  758. return fmt.Errorf("Updating join info failed: %v", err)
  759. }
  760. daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID})
  761. return nil
  762. }
  763. // ForceEndpointDelete deletes an endpoing from a network forcefully
  764. func (daemon *Daemon) ForceEndpointDelete(name string, n libnetwork.Network) error {
  765. ep, err := n.EndpointByName(name)
  766. if err != nil {
  767. return err
  768. }
  769. return ep.Delete(true)
  770. }
  771. // DisconnectFromNetwork disconnects container from network n.
  772. func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error {
  773. if container.HostConfig.NetworkMode.IsHost() && containertypes.NetworkMode(n.Type()).IsHost() {
  774. return runconfig.ErrConflictHostNetwork
  775. }
  776. if !container.Running {
  777. if container.RemovalInProgress || container.Dead {
  778. return errRemovalContainer(container.ID)
  779. }
  780. if _, ok := container.NetworkSettings.Networks[n.Name()]; ok {
  781. delete(container.NetworkSettings.Networks, n.Name())
  782. } else {
  783. return fmt.Errorf("container %s is not connected to the network %s", container.ID, n.Name())
  784. }
  785. } else {
  786. if err := disconnectFromNetwork(container, n, false); err != nil {
  787. return err
  788. }
  789. }
  790. if err := container.ToDiskLocking(); err != nil {
  791. return fmt.Errorf("Error saving container to disk: %v", err)
  792. }
  793. attributes := map[string]string{
  794. "container": container.ID,
  795. }
  796. daemon.LogNetworkEventWithAttributes(n, "disconnect", attributes)
  797. return nil
  798. }
  799. func disconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error {
  800. var (
  801. ep libnetwork.Endpoint
  802. sbox libnetwork.Sandbox
  803. )
  804. s := func(current libnetwork.Endpoint) bool {
  805. epInfo := current.Info()
  806. if epInfo == nil {
  807. return false
  808. }
  809. if sb := epInfo.Sandbox(); sb != nil {
  810. if sb.ContainerID() == container.ID {
  811. ep = current
  812. sbox = sb
  813. return true
  814. }
  815. }
  816. return false
  817. }
  818. n.WalkEndpoints(s)
  819. if ep == nil && force {
  820. epName := strings.TrimPrefix(container.Name, "/")
  821. ep, err := n.EndpointByName(epName)
  822. if err != nil {
  823. return err
  824. }
  825. return ep.Delete(force)
  826. }
  827. if ep == nil {
  828. return fmt.Errorf("container %s is not connected to the network", container.ID)
  829. }
  830. if err := ep.Leave(sbox); err != nil {
  831. return fmt.Errorf("container %s failed to leave network %s: %v", container.ID, n.Name(), err)
  832. }
  833. if err := ep.Delete(false); err != nil {
  834. return fmt.Errorf("endpoint delete failed for container %s on network %s: %v", container.ID, n.Name(), err)
  835. }
  836. delete(container.NetworkSettings.Networks, n.Name())
  837. return nil
  838. }
  839. func (daemon *Daemon) initializeNetworking(container *container.Container) error {
  840. var err error
  841. if container.HostConfig.NetworkMode.IsContainer() {
  842. // we need to get the hosts files from the container to join
  843. nc, err := daemon.getNetworkedContainer(container.ID, container.HostConfig.NetworkMode.ConnectedContainer())
  844. if err != nil {
  845. return err
  846. }
  847. container.HostnamePath = nc.HostnamePath
  848. container.HostsPath = nc.HostsPath
  849. container.ResolvConfPath = nc.ResolvConfPath
  850. container.Config.Hostname = nc.Config.Hostname
  851. container.Config.Domainname = nc.Config.Domainname
  852. return nil
  853. }
  854. if container.HostConfig.NetworkMode.IsHost() {
  855. container.Config.Hostname, err = os.Hostname()
  856. if err != nil {
  857. return err
  858. }
  859. parts := strings.SplitN(container.Config.Hostname, ".", 2)
  860. if len(parts) > 1 {
  861. container.Config.Hostname = parts[0]
  862. container.Config.Domainname = parts[1]
  863. }
  864. }
  865. if err := daemon.allocateNetwork(container); err != nil {
  866. return err
  867. }
  868. return container.BuildHostnameFile()
  869. }
  870. // called from the libcontainer pre-start hook to set the network
  871. // namespace configuration linkage to the libnetwork "sandbox" entity
  872. func (daemon *Daemon) setNetworkNamespaceKey(containerID string, pid int) error {
  873. path := fmt.Sprintf("/proc/%d/ns/net", pid)
  874. var sandbox libnetwork.Sandbox
  875. search := libnetwork.SandboxContainerWalker(&sandbox, containerID)
  876. daemon.netController.WalkSandboxes(search)
  877. if sandbox == nil {
  878. return fmt.Errorf("error locating sandbox id %s: no sandbox found", containerID)
  879. }
  880. return sandbox.SetKey(path)
  881. }
  882. func (daemon *Daemon) getIpcContainer(container *container.Container) (*container.Container, error) {
  883. containerID := container.HostConfig.IpcMode.Container()
  884. c, err := daemon.GetContainer(containerID)
  885. if err != nil {
  886. return nil, err
  887. }
  888. if !c.IsRunning() {
  889. return nil, fmt.Errorf("cannot join IPC of a non running container: %s", containerID)
  890. }
  891. if c.IsRestarting() {
  892. return nil, errContainerIsRestarting(container.ID)
  893. }
  894. return c, nil
  895. }
  896. func (daemon *Daemon) getNetworkedContainer(containerID, connectedContainerID string) (*container.Container, error) {
  897. nc, err := daemon.GetContainer(connectedContainerID)
  898. if err != nil {
  899. return nil, err
  900. }
  901. if containerID == nc.ID {
  902. return nil, fmt.Errorf("cannot join own network")
  903. }
  904. if !nc.IsRunning() {
  905. err := fmt.Errorf("cannot join network of a non running container: %s", connectedContainerID)
  906. return nil, errors.NewRequestConflictError(err)
  907. }
  908. if nc.IsRestarting() {
  909. return nil, errContainerIsRestarting(connectedContainerID)
  910. }
  911. return nc, nil
  912. }
  913. func (daemon *Daemon) releaseNetwork(container *container.Container) {
  914. if container.HostConfig.NetworkMode.IsContainer() || container.Config.NetworkDisabled {
  915. return
  916. }
  917. sid := container.NetworkSettings.SandboxID
  918. settings := container.NetworkSettings.Networks
  919. container.NetworkSettings.Ports = nil
  920. if sid == "" || len(settings) == 0 {
  921. return
  922. }
  923. var networks []libnetwork.Network
  924. for n, epSettings := range settings {
  925. if nw, err := daemon.FindNetwork(n); err == nil {
  926. networks = append(networks, nw)
  927. }
  928. cleanOperationalData(epSettings)
  929. }
  930. sb, err := daemon.netController.SandboxByID(sid)
  931. if err != nil {
  932. logrus.Errorf("error locating sandbox id %s: %v", sid, err)
  933. return
  934. }
  935. if err := sb.Delete(); err != nil {
  936. logrus.Errorf("Error deleting sandbox id %s for container %s: %v", sid, container.ID, err)
  937. }
  938. attributes := map[string]string{
  939. "container": container.ID,
  940. }
  941. for _, nw := range networks {
  942. daemon.LogNetworkEventWithAttributes(nw, "disconnect", attributes)
  943. }
  944. }
  945. func (daemon *Daemon) setupIpcDirs(c *container.Container) error {
  946. rootUID, rootGID := daemon.GetRemappedUIDGID()
  947. if !c.HasMountFor("/dev/shm") {
  948. shmPath, err := c.ShmResourcePath()
  949. if err != nil {
  950. return err
  951. }
  952. if err := idtools.MkdirAllAs(shmPath, 0700, rootUID, rootGID); err != nil {
  953. return err
  954. }
  955. shmSize := container.DefaultSHMSize
  956. if c.HostConfig.ShmSize != 0 {
  957. shmSize = c.HostConfig.ShmSize
  958. }
  959. shmproperty := "mode=1777,size=" + strconv.FormatInt(shmSize, 10)
  960. if err := syscall.Mount("shm", shmPath, "tmpfs", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), label.FormatMountLabel(shmproperty, c.GetMountLabel())); err != nil {
  961. return fmt.Errorf("mounting shm tmpfs: %s", err)
  962. }
  963. if err := os.Chown(shmPath, rootUID, rootGID); err != nil {
  964. return err
  965. }
  966. }
  967. return nil
  968. }
  969. func (daemon *Daemon) mountVolumes(container *container.Container) error {
  970. mounts, err := daemon.setupMounts(container)
  971. if err != nil {
  972. return err
  973. }
  974. for _, m := range mounts {
  975. dest, err := container.GetResourcePath(m.Destination)
  976. if err != nil {
  977. return err
  978. }
  979. var stat os.FileInfo
  980. stat, err = os.Stat(m.Source)
  981. if err != nil {
  982. return err
  983. }
  984. if err = fileutils.CreateIfNotExists(dest, stat.IsDir()); err != nil {
  985. return err
  986. }
  987. opts := "rbind,ro"
  988. if m.Writable {
  989. opts = "rbind,rw"
  990. }
  991. if err := mount.Mount(m.Source, dest, "bind", opts); err != nil {
  992. return err
  993. }
  994. }
  995. return nil
  996. }
  997. func killProcessDirectly(container *container.Container) error {
  998. if _, err := container.WaitStop(10 * time.Second); err != nil {
  999. // Ensure that we don't kill ourselves
  1000. if pid := container.GetPID(); pid != 0 {
  1001. logrus.Infof("Container %s failed to exit within 10 seconds of kill - trying direct SIGKILL", stringid.TruncateID(container.ID))
  1002. if err := syscall.Kill(pid, 9); err != nil {
  1003. if err != syscall.ESRCH {
  1004. return err
  1005. }
  1006. e := errNoSuchProcess{pid, 9}
  1007. logrus.Debug(e)
  1008. return e
  1009. }
  1010. }
  1011. }
  1012. return nil
  1013. }
  1014. func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []*configs.Device, err error) {
  1015. resolvedPathOnHost := deviceMapping.PathOnHost
  1016. // check if it is a symbolic link
  1017. if src, e := os.Lstat(deviceMapping.PathOnHost); e == nil && src.Mode()&os.ModeSymlink == os.ModeSymlink {
  1018. if linkedPathOnHost, e := os.Readlink(deviceMapping.PathOnHost); e == nil {
  1019. resolvedPathOnHost = linkedPathOnHost
  1020. }
  1021. }
  1022. device, err := devices.DeviceFromPath(resolvedPathOnHost, deviceMapping.CgroupPermissions)
  1023. // if there was no error, return the device
  1024. if err == nil {
  1025. device.Path = deviceMapping.PathInContainer
  1026. return append(devs, device), nil
  1027. }
  1028. // if the device is not a device node
  1029. // try to see if it's a directory holding many devices
  1030. if err == devices.ErrNotADevice {
  1031. // check if it is a directory
  1032. if src, e := os.Stat(resolvedPathOnHost); e == nil && src.IsDir() {
  1033. // mount the internal devices recursively
  1034. filepath.Walk(resolvedPathOnHost, func(dpath string, f os.FileInfo, e error) error {
  1035. childDevice, e := devices.DeviceFromPath(dpath, deviceMapping.CgroupPermissions)
  1036. if e != nil {
  1037. // ignore the device
  1038. return nil
  1039. }
  1040. // add the device to userSpecified devices
  1041. childDevice.Path = strings.Replace(dpath, resolvedPathOnHost, deviceMapping.PathInContainer, 1)
  1042. devs = append(devs, childDevice)
  1043. return nil
  1044. })
  1045. }
  1046. }
  1047. if len(devs) > 0 {
  1048. return devs, nil
  1049. }
  1050. return devs, fmt.Errorf("error gathering device information while adding custom device %q: %s", deviceMapping.PathOnHost, err)
  1051. }
  1052. func mergeDevices(defaultDevices, userDevices []*configs.Device) []*configs.Device {
  1053. if len(userDevices) == 0 {
  1054. return defaultDevices
  1055. }
  1056. paths := map[string]*configs.Device{}
  1057. for _, d := range userDevices {
  1058. paths[d.Path] = d
  1059. }
  1060. var devs []*configs.Device
  1061. for _, d := range defaultDevices {
  1062. if _, defined := paths[d.Path]; !defined {
  1063. devs = append(devs, d)
  1064. }
  1065. }
  1066. return append(devs, userDevices...)
  1067. }
  1068. func detachMounted(path string) error {
  1069. return syscall.Unmount(path, syscall.MNT_DETACH)
  1070. }
  1071. func isLinkable(child *container.Container) bool {
  1072. // A container is linkable only if it belongs to the default network
  1073. _, ok := child.NetworkSettings.Networks["bridge"]
  1074. return ok
  1075. }
  1076. func errRemovalContainer(containerID string) error {
  1077. return fmt.Errorf("Container %s is marked for removal and cannot be connected or disconnected to the network", containerID)
  1078. }