Change the persistent container metadata to store the whole platform
(as defined by OCI) instead of only the operating system.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
| ... | ... |
@@ -15,6 +15,7 @@ import ( |
| 15 | 15 |
|
| 16 | 16 |
"github.com/containerd/containerd/cio" |
| 17 | 17 |
"github.com/containerd/log" |
| 18 |
+ "github.com/containerd/platforms" |
|
| 18 | 19 |
containertypes "github.com/docker/docker/api/types/container" |
| 19 | 20 |
"github.com/docker/docker/api/types/events" |
| 20 | 21 |
mounttypes "github.com/docker/docker/api/types/mount" |
| ... | ... |
@@ -84,7 +85,12 @@ type Container struct {
|
| 84 | 84 |
LogPath string |
| 85 | 85 |
Name string |
| 86 | 86 |
Driver string |
| 87 |
- OS string |
|
| 87 |
+ |
|
| 88 |
+ // Deprecated: use [ImagePlatform.OS] instead. |
|
| 89 |
+ // TODO: Remove, see https://github.com/moby/moby/issues/48892 |
|
| 90 |
+ OS string |
|
| 91 |
+ |
|
| 92 |
+ ImagePlatform ocispec.Platform |
|
| 88 | 93 |
|
| 89 | 94 |
RestartCount int |
| 90 | 95 |
HasBeenStartedBefore bool |
| ... | ... |
@@ -162,11 +168,17 @@ func (container *Container) FromDisk() error {
|
| 162 | 162 |
return err |
| 163 | 163 |
} |
| 164 | 164 |
|
| 165 |
- // Ensure the operating system is set if blank. Assume it is the OS of the |
|
| 166 |
- // host OS if not, to ensure containers created before multiple-OS |
|
| 167 |
- // support are migrated |
|
| 168 |
- if container.OS == "" {
|
|
| 169 |
- container.OS = runtime.GOOS |
|
| 165 |
+ if container.OS != "" {
|
|
| 166 |
+ // OS was deprecated in favor of ImagePlatform |
|
| 167 |
+ // Make sure we migrate the OS to ImagePlatform.OS. |
|
| 168 |
+ if container.ImagePlatform.OS == "" {
|
|
| 169 |
+ container.ImagePlatform.OS = container.OS //nolint:staticcheck // ignore SA1019: field is deprecated |
|
| 170 |
+ } |
|
| 171 |
+ } else {
|
|
| 172 |
+ // Pre multiple-OS support containers have no OS set. |
|
| 173 |
+ // Assume it is the host platform. |
|
| 174 |
+ container.ImagePlatform = platforms.DefaultSpec() |
|
| 175 |
+ container.OS = container.ImagePlatform.OS //nolint:staticcheck // ignore SA1019: field is deprecated |
|
| 170 | 176 |
} |
| 171 | 177 |
|
| 172 | 178 |
return container.readHostConfig() |
| ... | ... |
@@ -752,7 +764,7 @@ func getConfigTargetPath(r *swarmtypes.ConfigReference) string {
|
| 752 | 752 |
// CreateDaemonEnvironment creates a new environment variable slice for this container. |
| 753 | 753 |
func (container *Container) CreateDaemonEnvironment(tty bool, linkedEnv []string) []string {
|
| 754 | 754 |
// Setup environment |
| 755 |
- ctrOS := container.OS |
|
| 755 |
+ ctrOS := container.ImagePlatform.OS |
|
| 756 | 756 |
if ctrOS == "" {
|
| 757 | 757 |
ctrOS = runtime.GOOS |
| 758 | 758 |
} |
| ... | ... |
@@ -151,7 +151,7 @@ func (daemon *Daemon) CreateImageFromContainer(ctx context.Context, name string, |
| 151 | 151 |
if c.Config == nil {
|
| 152 | 152 |
c.Config = container.Config |
| 153 | 153 |
} |
| 154 |
- newConfig, err := dockerfile.BuildFromConfig(ctx, c.Config, c.Changes, container.OS) |
|
| 154 |
+ newConfig, err := dockerfile.BuildFromConfig(ctx, c.Config, c.Changes, container.ImagePlatform.OS) |
|
| 155 | 155 |
if err != nil {
|
| 156 | 156 |
return "", err |
| 157 | 157 |
} |
| ... | ... |
@@ -166,7 +166,7 @@ func (daemon *Daemon) CreateImageFromContainer(ctx context.Context, name string, |
| 166 | 166 |
ContainerConfig: container.Config, |
| 167 | 167 |
ContainerID: container.ID, |
| 168 | 168 |
ContainerMountLabel: container.MountLabel, |
| 169 |
- ContainerOS: container.OS, |
|
| 169 |
+ ContainerOS: container.ImagePlatform.OS, |
|
| 170 | 170 |
ParentImageID: string(container.ImageID), |
| 171 | 171 |
}) |
| 172 | 172 |
if err != nil {
|
| ... | ... |
@@ -23,6 +23,7 @@ import ( |
| 23 | 23 |
volumemounts "github.com/docker/docker/volume/mounts" |
| 24 | 24 |
"github.com/docker/go-connections/nat" |
| 25 | 25 |
"github.com/moby/sys/signal" |
| 26 |
+ ocispec "github.com/opencontainers/image-spec/specs-go/v1" |
|
| 26 | 27 |
"github.com/opencontainers/selinux/go-selinux" |
| 27 | 28 |
"github.com/pkg/errors" |
| 28 | 29 |
) |
| ... | ... |
@@ -119,7 +120,7 @@ func (daemon *Daemon) register(ctx context.Context, c *container.Container) erro |
| 119 | 119 |
return c.CheckpointTo(ctx, daemon.containersReplica) |
| 120 | 120 |
} |
| 121 | 121 |
|
| 122 |
-func (daemon *Daemon) newContainer(name string, operatingSystem string, config *containertypes.Config, hostConfig *containertypes.HostConfig, imgID image.ID, managed bool) (*container.Container, error) {
|
|
| 122 |
+func (daemon *Daemon) newContainer(name string, platform ocispec.Platform, config *containertypes.Config, hostConfig *containertypes.HostConfig, imgID image.ID, managed bool) (*container.Container, error) {
|
|
| 123 | 123 |
var ( |
| 124 | 124 |
id string |
| 125 | 125 |
err error |
| ... | ... |
@@ -153,8 +154,9 @@ func (daemon *Daemon) newContainer(name string, operatingSystem string, config * |
| 153 | 153 |
base.NetworkSettings = &network.Settings{}
|
| 154 | 154 |
base.Name = name |
| 155 | 155 |
base.Driver = daemon.imageService.StorageDriver() |
| 156 |
- base.OS = operatingSystem |
|
| 157 |
- return base, nil |
|
| 156 |
+ base.ImagePlatform = platform |
|
| 157 |
+ base.OS = platform.OS //nolint:staticcheck // ignore SA1019: field is deprecated, but still set for compatibility |
|
| 158 |
+ return base, err |
|
| 158 | 159 |
} |
| 159 | 160 |
|
| 160 | 161 |
// GetByName returns a container given a name. |
| ... | ... |
@@ -325,7 +325,7 @@ func (i *ImageService) CommitBuildStep(ctx context.Context, c backend.CommitConf |
| 325 | 325 |
return "", fmt.Errorf("container not found: %s", c.ContainerID)
|
| 326 | 326 |
} |
| 327 | 327 |
c.ContainerMountLabel = ctr.MountLabel |
| 328 |
- c.ContainerOS = ctr.OS |
|
| 328 |
+ c.ContainerOS = ctr.ImagePlatform.OS |
|
| 329 | 329 |
c.ParentImageID = string(ctr.ImageID) |
| 330 | 330 |
return i.CommitImage(ctx, c) |
| 331 | 331 |
} |
| ... | ... |
@@ -3,7 +3,6 @@ package daemon // import "github.com/docker/docker/daemon" |
| 3 | 3 |
import ( |
| 4 | 4 |
"context" |
| 5 | 5 |
"fmt" |
| 6 |
- "runtime" |
|
| 7 | 6 |
"strings" |
| 8 | 7 |
"time" |
| 9 | 8 |
|
| ... | ... |
@@ -23,7 +22,7 @@ import ( |
| 23 | 23 |
"github.com/docker/docker/runconfig" |
| 24 | 24 |
ocispec "github.com/opencontainers/image-spec/specs-go/v1" |
| 25 | 25 |
"github.com/opencontainers/selinux/go-selinux" |
| 26 |
- archvariant "github.com/tonistiigi/go-archvariant" |
|
| 26 |
+ "github.com/tonistiigi/go-archvariant" |
|
| 27 | 27 |
) |
| 28 | 28 |
|
| 29 | 29 |
type createOpts struct {
|
| ... | ... |
@@ -130,7 +129,7 @@ func (daemon *Daemon) create(ctx context.Context, daemonCfg *config.Config, opts |
| 130 | 130 |
imgManifest *ocispec.Descriptor |
| 131 | 131 |
imgID image.ID |
| 132 | 132 |
err error |
| 133 |
- os = runtime.GOOS |
|
| 133 |
+ platform = platforms.DefaultSpec() |
|
| 134 | 134 |
) |
| 135 | 135 |
|
| 136 | 136 |
if opts.params.Config.Image != "" {
|
| ... | ... |
@@ -148,17 +147,17 @@ func (daemon *Daemon) create(ctx context.Context, daemonCfg *config.Config, opts |
| 148 | 148 |
return nil, err |
| 149 | 149 |
} |
| 150 | 150 |
} |
| 151 |
- os = img.OperatingSystem() |
|
| 151 |
+ platform = img.Platform() |
|
| 152 | 152 |
imgID = img.ID() |
| 153 | 153 |
} else if isWindows {
|
| 154 |
- os = "linux" // 'scratch' case. |
|
| 154 |
+ platform.OS = "linux" // 'scratch' case. |
|
| 155 | 155 |
} |
| 156 | 156 |
|
| 157 | 157 |
// On WCOW, if are not being invoked by the builder to create this container (where |
| 158 | 158 |
// ignoreImagesArgEscaped will be true) - if the image already has its arguments escaped, |
| 159 | 159 |
// ensure that this is replicated across to the created container to avoid double-escaping |
| 160 | 160 |
// of the arguments/command line when the runtime attempts to run the container. |
| 161 |
- if os == "windows" && !opts.ignoreImagesArgsEscaped && img != nil && img.RunConfig().ArgsEscaped {
|
|
| 161 |
+ if platform.OS == "windows" && !opts.ignoreImagesArgsEscaped && img != nil && img.RunConfig().ArgsEscaped {
|
|
| 162 | 162 |
opts.params.Config.ArgsEscaped = true |
| 163 | 163 |
} |
| 164 | 164 |
|
| ... | ... |
@@ -170,7 +169,7 @@ func (daemon *Daemon) create(ctx context.Context, daemonCfg *config.Config, opts |
| 170 | 170 |
return nil, errdefs.InvalidParameter(err) |
| 171 | 171 |
} |
| 172 | 172 |
|
| 173 |
- if ctr, err = daemon.newContainer(opts.params.Name, os, opts.params.Config, opts.params.HostConfig, imgID, opts.managed); err != nil {
|
|
| 173 |
+ if ctr, err = daemon.newContainer(opts.params.Name, platform, opts.params.Config, opts.params.HostConfig, imgID, opts.managed); err != nil {
|
|
| 174 | 174 |
return nil, err |
| 175 | 175 |
} |
| 176 | 176 |
defer func() {
|
| ... | ... |
@@ -9,7 +9,7 @@ import ( |
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 | 11 |
func (daemon *Daemon) execSetPlatformOpt(ctx context.Context, daemonCfg *config.Config, ec *container.ExecConfig, p *specs.Process) error {
|
| 12 |
- if ec.Container.OS == "windows" {
|
|
| 12 |
+ if ec.Container.ImagePlatform.OS == "windows" {
|
|
| 13 | 13 |
p.User.Username = ec.User |
| 14 | 14 |
} |
| 15 | 15 |
return nil |
| ... | ... |
@@ -20,7 +20,7 @@ func (daemon *Daemon) ContainerExport(ctx context.Context, name string, out io.W |
| 20 | 20 |
return err |
| 21 | 21 |
} |
| 22 | 22 |
|
| 23 |
- if isWindows && ctr.OS == "windows" {
|
|
| 23 |
+ if isWindows && ctr.ImagePlatform.OS == "windows" {
|
|
| 24 | 24 |
return fmt.Errorf("the daemon on this operating system does not support exporting Windows containers")
|
| 25 | 25 |
} |
| 26 | 26 |
|
| ... | ... |
@@ -457,7 +457,7 @@ func getShell(cntr *container.Container) []string {
|
| 457 | 457 |
if runtime.GOOS != "windows" {
|
| 458 | 458 |
return []string{"/bin/sh", "-c"}
|
| 459 | 459 |
} |
| 460 |
- if cntr.OS != runtime.GOOS {
|
|
| 460 |
+ if cntr.ImagePlatform.OS != runtime.GOOS {
|
|
| 461 | 461 |
return []string{"/bin/sh", "-c"}
|
| 462 | 462 |
} |
| 463 | 463 |
return []string{"cmd", "/S", "/C"}
|
| ... | ... |
@@ -128,7 +128,7 @@ func (i *ImageService) CommitBuildStep(ctx context.Context, c backend.CommitConf |
| 128 | 128 |
return "", errors.Errorf("container not found: %s", c.ContainerID)
|
| 129 | 129 |
} |
| 130 | 130 |
c.ContainerMountLabel = ctr.MountLabel |
| 131 |
- c.ContainerOS = ctr.OS |
|
| 131 |
+ c.ContainerOS = ctr.ImagePlatform.OS |
|
| 132 | 132 |
c.ParentImageID = string(ctr.ImageID) |
| 133 | 133 |
return i.CommitImage(ctx, c) |
| 134 | 134 |
} |
| ... | ... |
@@ -145,7 +145,7 @@ func (daemon *Daemon) getInspectData(daemonCfg *config.Config, container *contai |
| 145 | 145 |
Name: container.Name, |
| 146 | 146 |
RestartCount: container.RestartCount, |
| 147 | 147 |
Driver: container.Driver, |
| 148 |
- Platform: container.OS, |
|
| 148 |
+ Platform: container.ImagePlatform.OS, |
|
| 149 | 149 |
MountLabel: container.MountLabel, |
| 150 | 150 |
ProcessLabel: container.ProcessLabel, |
| 151 | 151 |
ExecIDs: container.GetExecIDs(), |