inspect.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
  2. //go:build go1.19
  3. package daemon // import "github.com/docker/docker/daemon"
  4. import (
  5. "context"
  6. "errors"
  7. "fmt"
  8. "time"
  9. "github.com/docker/docker/api/types"
  10. "github.com/docker/docker/api/types/backend"
  11. networktypes "github.com/docker/docker/api/types/network"
  12. "github.com/docker/docker/api/types/versions"
  13. "github.com/docker/docker/api/types/versions/v1p20"
  14. "github.com/docker/docker/container"
  15. "github.com/docker/docker/daemon/network"
  16. "github.com/docker/docker/errdefs"
  17. "github.com/docker/go-connections/nat"
  18. )
  19. // ContainerInspect returns low-level information about a
  20. // container. Returns an error if the container cannot be found, or if
  21. // there is an error getting the data.
  22. func (daemon *Daemon) ContainerInspect(ctx context.Context, name string, size bool, version string) (interface{}, error) {
  23. switch {
  24. case versions.LessThan(version, "1.20"):
  25. return daemon.containerInspectPre120(ctx, name)
  26. case versions.Equal(version, "1.20"):
  27. return daemon.containerInspect120(name)
  28. }
  29. return daemon.ContainerInspectCurrent(ctx, name, size)
  30. }
  31. // ContainerInspectCurrent returns low-level information about a
  32. // container in a most recent api version.
  33. func (daemon *Daemon) ContainerInspectCurrent(ctx context.Context, name string, size bool) (*types.ContainerJSON, error) {
  34. ctr, err := daemon.GetContainer(name)
  35. if err != nil {
  36. return nil, err
  37. }
  38. ctr.Lock()
  39. base, err := daemon.getInspectData(ctr)
  40. if err != nil {
  41. ctr.Unlock()
  42. return nil, err
  43. }
  44. apiNetworks := make(map[string]*networktypes.EndpointSettings)
  45. for nwName, epConf := range ctr.NetworkSettings.Networks {
  46. if epConf.EndpointSettings != nil {
  47. // We must make a copy of this pointer object otherwise it can race with other operations
  48. apiNetworks[nwName] = epConf.EndpointSettings.Copy()
  49. }
  50. }
  51. mountPoints := ctr.GetMountPoints()
  52. networkSettings := &types.NetworkSettings{
  53. NetworkSettingsBase: types.NetworkSettingsBase{
  54. Bridge: ctr.NetworkSettings.Bridge,
  55. SandboxID: ctr.NetworkSettings.SandboxID,
  56. HairpinMode: ctr.NetworkSettings.HairpinMode,
  57. LinkLocalIPv6Address: ctr.NetworkSettings.LinkLocalIPv6Address,
  58. LinkLocalIPv6PrefixLen: ctr.NetworkSettings.LinkLocalIPv6PrefixLen,
  59. SandboxKey: ctr.NetworkSettings.SandboxKey,
  60. SecondaryIPAddresses: ctr.NetworkSettings.SecondaryIPAddresses,
  61. SecondaryIPv6Addresses: ctr.NetworkSettings.SecondaryIPv6Addresses,
  62. },
  63. DefaultNetworkSettings: daemon.getDefaultNetworkSettings(ctr.NetworkSettings.Networks),
  64. Networks: apiNetworks,
  65. }
  66. ports := make(nat.PortMap, len(ctr.NetworkSettings.Ports))
  67. for k, pm := range ctr.NetworkSettings.Ports {
  68. ports[k] = pm
  69. }
  70. networkSettings.NetworkSettingsBase.Ports = ports
  71. ctr.Unlock()
  72. if size {
  73. sizeRw, sizeRootFs, err := daemon.imageService.GetContainerLayerSize(ctx, base.ID)
  74. if err != nil {
  75. return nil, err
  76. }
  77. base.SizeRw = &sizeRw
  78. base.SizeRootFs = &sizeRootFs
  79. }
  80. return &types.ContainerJSON{
  81. ContainerJSONBase: base,
  82. Mounts: mountPoints,
  83. Config: ctr.Config,
  84. NetworkSettings: networkSettings,
  85. }, nil
  86. }
  87. // containerInspect120 serializes the master version of a container into a json type.
  88. func (daemon *Daemon) containerInspect120(name string) (*v1p20.ContainerJSON, error) {
  89. ctr, err := daemon.GetContainer(name)
  90. if err != nil {
  91. return nil, err
  92. }
  93. ctr.Lock()
  94. defer ctr.Unlock()
  95. base, err := daemon.getInspectData(ctr)
  96. if err != nil {
  97. return nil, err
  98. }
  99. return &v1p20.ContainerJSON{
  100. ContainerJSONBase: base,
  101. Mounts: ctr.GetMountPoints(),
  102. Config: &v1p20.ContainerConfig{
  103. Config: ctr.Config,
  104. MacAddress: ctr.Config.MacAddress,
  105. NetworkDisabled: ctr.Config.NetworkDisabled,
  106. ExposedPorts: ctr.Config.ExposedPorts,
  107. VolumeDriver: ctr.HostConfig.VolumeDriver,
  108. },
  109. NetworkSettings: daemon.getBackwardsCompatibleNetworkSettings(ctr.NetworkSettings),
  110. }, nil
  111. }
  112. func (daemon *Daemon) getInspectData(container *container.Container) (*types.ContainerJSONBase, error) {
  113. // make a copy to play with
  114. hostConfig := *container.HostConfig
  115. children := daemon.children(container)
  116. hostConfig.Links = nil // do not expose the internal structure
  117. for linkAlias, child := range children {
  118. hostConfig.Links = append(hostConfig.Links, fmt.Sprintf("%s:%s", child.Name, linkAlias))
  119. }
  120. // We merge the Ulimits from hostConfig with daemon default
  121. daemon.mergeUlimits(&hostConfig)
  122. var containerHealth *types.Health
  123. if container.State.Health != nil {
  124. containerHealth = &types.Health{
  125. Status: container.State.Health.Status(),
  126. FailingStreak: container.State.Health.FailingStreak,
  127. Log: append([]*types.HealthcheckResult{}, container.State.Health.Log...),
  128. }
  129. }
  130. containerState := &types.ContainerState{
  131. Status: container.State.StateString(),
  132. Running: container.State.Running,
  133. Paused: container.State.Paused,
  134. Restarting: container.State.Restarting,
  135. OOMKilled: container.State.OOMKilled,
  136. Dead: container.State.Dead,
  137. Pid: container.State.Pid,
  138. ExitCode: container.State.ExitCode(),
  139. Error: container.State.ErrorMsg,
  140. StartedAt: container.State.StartedAt.Format(time.RFC3339Nano),
  141. FinishedAt: container.State.FinishedAt.Format(time.RFC3339Nano),
  142. Health: containerHealth,
  143. }
  144. contJSONBase := &types.ContainerJSONBase{
  145. ID: container.ID,
  146. Created: container.Created.Format(time.RFC3339Nano),
  147. Path: container.Path,
  148. Args: container.Args,
  149. State: containerState,
  150. Image: container.ImageID.String(),
  151. LogPath: container.LogPath,
  152. Name: container.Name,
  153. RestartCount: container.RestartCount,
  154. Driver: container.Driver,
  155. Platform: container.OS,
  156. MountLabel: container.MountLabel,
  157. ProcessLabel: container.ProcessLabel,
  158. ExecIDs: container.GetExecIDs(),
  159. HostConfig: &hostConfig,
  160. }
  161. // Now set any platform-specific fields
  162. contJSONBase = setPlatformSpecificContainerFields(container, contJSONBase)
  163. contJSONBase.GraphDriver.Name = container.Driver
  164. if daemon.UsesSnapshotter() {
  165. // Additional information only applies to graphDrivers, so we're done.
  166. return contJSONBase, nil
  167. }
  168. if container.RWLayer == nil {
  169. if container.Dead {
  170. return contJSONBase, nil
  171. }
  172. return nil, errdefs.System(errors.New("RWLayer of container " + container.ID + " is unexpectedly nil"))
  173. }
  174. graphDriverData, err := container.RWLayer.Metadata()
  175. if err != nil {
  176. if container.Dead {
  177. // container is marked as Dead, and its graphDriver metadata may
  178. // have been removed; we can ignore errors.
  179. return contJSONBase, nil
  180. }
  181. return nil, errdefs.System(err)
  182. }
  183. contJSONBase.GraphDriver.Data = graphDriverData
  184. return contJSONBase, nil
  185. }
  186. // ContainerExecInspect returns low-level information about the exec
  187. // command. An error is returned if the exec cannot be found.
  188. func (daemon *Daemon) ContainerExecInspect(id string) (*backend.ExecInspect, error) {
  189. e := daemon.execCommands.Get(id)
  190. if e == nil {
  191. return nil, errExecNotFound(id)
  192. }
  193. if ctr := daemon.containers.Get(e.Container.ID); ctr == nil {
  194. return nil, errExecNotFound(id)
  195. }
  196. e.Lock()
  197. defer e.Unlock()
  198. pc := inspectExecProcessConfig(e)
  199. var pid int
  200. if e.Process != nil {
  201. pid = int(e.Process.Pid())
  202. }
  203. return &backend.ExecInspect{
  204. ID: e.ID,
  205. Running: e.Running,
  206. ExitCode: e.ExitCode,
  207. ProcessConfig: pc,
  208. OpenStdin: e.OpenStdin,
  209. OpenStdout: e.OpenStdout,
  210. OpenStderr: e.OpenStderr,
  211. CanRemove: e.CanRemove,
  212. ContainerID: e.Container.ID,
  213. DetachKeys: e.DetachKeys,
  214. Pid: pid,
  215. }, nil
  216. }
  217. func (daemon *Daemon) getBackwardsCompatibleNetworkSettings(settings *network.Settings) *v1p20.NetworkSettings {
  218. result := &v1p20.NetworkSettings{
  219. NetworkSettingsBase: types.NetworkSettingsBase{
  220. Bridge: settings.Bridge,
  221. SandboxID: settings.SandboxID,
  222. HairpinMode: settings.HairpinMode,
  223. LinkLocalIPv6Address: settings.LinkLocalIPv6Address,
  224. LinkLocalIPv6PrefixLen: settings.LinkLocalIPv6PrefixLen,
  225. Ports: settings.Ports,
  226. SandboxKey: settings.SandboxKey,
  227. SecondaryIPAddresses: settings.SecondaryIPAddresses,
  228. SecondaryIPv6Addresses: settings.SecondaryIPv6Addresses,
  229. },
  230. DefaultNetworkSettings: daemon.getDefaultNetworkSettings(settings.Networks),
  231. }
  232. return result
  233. }
  234. // getDefaultNetworkSettings creates the deprecated structure that holds the information
  235. // about the bridge network for a container.
  236. func (daemon *Daemon) getDefaultNetworkSettings(networks map[string]*network.EndpointSettings) types.DefaultNetworkSettings {
  237. var settings types.DefaultNetworkSettings
  238. if defaultNetwork, ok := networks["bridge"]; ok && defaultNetwork.EndpointSettings != nil {
  239. settings.EndpointID = defaultNetwork.EndpointID
  240. settings.Gateway = defaultNetwork.Gateway
  241. settings.GlobalIPv6Address = defaultNetwork.GlobalIPv6Address
  242. settings.GlobalIPv6PrefixLen = defaultNetwork.GlobalIPv6PrefixLen
  243. settings.IPAddress = defaultNetwork.IPAddress
  244. settings.IPPrefixLen = defaultNetwork.IPPrefixLen
  245. settings.IPv6Gateway = defaultNetwork.IPv6Gateway
  246. settings.MacAddress = defaultNetwork.MacAddress
  247. }
  248. return settings
  249. }