mirror of
https://github.com/moby/moby.git
synced 2026-01-11 10:41:43 +00:00
kernel-memory limits are not supported in cgroups v2, and were obsoleted in [kernel v5.4], producing a `ENOTSUP` in kernel v5.16. Support for this option was removed in runc and other runtimes, as various LTS kernels contained a broken implementation, resulting in unpredictable behavior. We deprecated this option in [moby@b8ca7de], producing a warning when used, and actively ignore the option since [moby@0798f5f]. Given that setting this option had no effect in most situations, we should just remove this option instead of continuing to handle it with the expectation that a runtime may still support it. Note that we still support RHEL 8 (kernel 4.18) and RHEL 9 (kernel 5.14). We no longer build packages for Ubuntu 20.04 (kernel 5.4) and Debian Bullseye 11 (kernel 5.10), which still have an LTS / ESM programme, but for those it would only impact situations where a runtime is used that still supports it, and an old API version was used. [kernel v5.4]: https://github.com/torvalds/linux/commit/0158115f702b0ba208ab0 [moby@b8ca7de]:b8ca7de823[moby@0798f5f]:0798f5f5cfSigned-off-by: Sebastiaan van Stijn <github@gone.nl>
209 lines
6.5 KiB
Go
209 lines
6.5 KiB
Go
package container
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
containertypes "github.com/moby/moby/api/types/container"
|
|
"github.com/moby/moby/api/types/events"
|
|
swarmtypes "github.com/moby/moby/api/types/swarm"
|
|
"github.com/moby/moby/v2/errdefs"
|
|
)
|
|
|
|
const (
|
|
containerConfigMountPath = `C:\`
|
|
containerSecretMountPath = `C:\ProgramData\Docker\secrets`
|
|
containerInternalSecretMountPath = `C:\ProgramData\Docker\internal\secrets`
|
|
containerInternalConfigsDirPath = `C:\ProgramData\Docker\internal\configs`
|
|
|
|
// defaultStopTimeout is the timeout (in seconds) for the shutdown call on a container
|
|
defaultStopTimeout = 30
|
|
)
|
|
|
|
// UnmountIpcMount unmounts Ipc related mounts.
|
|
// This is a NOOP on windows.
|
|
func (container *Container) UnmountIpcMount() error {
|
|
return nil
|
|
}
|
|
|
|
// IpcMounts returns the list of Ipc related mounts.
|
|
func (container *Container) IpcMounts() []Mount {
|
|
return nil
|
|
}
|
|
|
|
// CreateSecretSymlinks creates symlinks to files in the secret mount.
|
|
func (container *Container) CreateSecretSymlinks() error {
|
|
for _, r := range container.SecretReferences {
|
|
if r.File == nil {
|
|
continue
|
|
}
|
|
resolvedPath, _, err := container.ResolvePath(getSecretTargetPath(r))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := os.MkdirAll(filepath.Dir(resolvedPath), 0); err != nil {
|
|
return err
|
|
}
|
|
if err := os.Symlink(filepath.Join(containerInternalSecretMountPath, r.SecretID), resolvedPath); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SecretMounts returns the mount for the secret path.
|
|
// All secrets are stored in a single mount on Windows. Target symlinks are
|
|
// created for each secret, pointing to the files in this mount.
|
|
func (container *Container) SecretMounts() ([]Mount, error) {
|
|
var mounts []Mount
|
|
if len(container.SecretReferences) > 0 {
|
|
src, err := container.SecretMountPath()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
mounts = append(mounts, Mount{
|
|
Source: src,
|
|
Destination: containerInternalSecretMountPath,
|
|
Writable: false,
|
|
})
|
|
}
|
|
|
|
return mounts, nil
|
|
}
|
|
|
|
// UnmountSecrets unmounts the fs for secrets
|
|
func (container *Container) UnmountSecrets() error {
|
|
p, err := container.SecretMountPath()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return os.RemoveAll(p)
|
|
}
|
|
|
|
// CreateConfigSymlinks creates symlinks to files in the config mount.
|
|
func (container *Container) CreateConfigSymlinks() error {
|
|
for _, configRef := range container.ConfigReferences {
|
|
if configRef.File == nil {
|
|
continue
|
|
}
|
|
resolvedPath, _, err := container.ResolvePath(getConfigTargetPath(configRef))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := os.MkdirAll(filepath.Dir(resolvedPath), 0); err != nil {
|
|
return err
|
|
}
|
|
if err := os.Symlink(filepath.Join(containerInternalConfigsDirPath, configRef.ConfigID), resolvedPath); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ConfigMounts returns the mount for configs.
|
|
// TODO: Right now Windows doesn't really have a "secure" storage for secrets,
|
|
// however some configs may contain secrets. Once secure storage is worked out,
|
|
// configs and secret handling should be merged.
|
|
func (container *Container) ConfigMounts() []Mount {
|
|
var mounts []Mount
|
|
if len(container.ConfigReferences) > 0 {
|
|
mounts = append(mounts, Mount{
|
|
Source: container.ConfigsDirPath(),
|
|
Destination: containerInternalConfigsDirPath,
|
|
Writable: false,
|
|
})
|
|
}
|
|
|
|
return mounts
|
|
}
|
|
|
|
// DetachAndUnmount unmounts all volumes.
|
|
// On Windows it only delegates to `UnmountVolumes` since there is nothing to
|
|
// force unmount.
|
|
func (container *Container) DetachAndUnmount(volumeEventLog func(name string, action events.Action, attributes map[string]string)) error {
|
|
return container.UnmountVolumes(context.TODO(), volumeEventLog)
|
|
}
|
|
|
|
// TmpfsMounts returns the list of tmpfs mounts
|
|
func (container *Container) TmpfsMounts() ([]Mount, error) {
|
|
var mounts []Mount
|
|
return mounts, nil
|
|
}
|
|
|
|
// UpdateContainer updates configuration of a container. Callers must hold a Lock on the Container.
|
|
func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfig) error {
|
|
resources := hostConfig.Resources
|
|
if resources.CPUShares != 0 ||
|
|
resources.Memory != 0 ||
|
|
resources.NanoCPUs != 0 ||
|
|
resources.CgroupParent != "" ||
|
|
resources.BlkioWeight != 0 ||
|
|
len(resources.BlkioWeightDevice) != 0 ||
|
|
len(resources.BlkioDeviceReadBps) != 0 ||
|
|
len(resources.BlkioDeviceWriteBps) != 0 ||
|
|
len(resources.BlkioDeviceReadIOps) != 0 ||
|
|
len(resources.BlkioDeviceWriteIOps) != 0 ||
|
|
resources.CPUPeriod != 0 ||
|
|
resources.CPUQuota != 0 ||
|
|
resources.CPURealtimePeriod != 0 ||
|
|
resources.CPURealtimeRuntime != 0 ||
|
|
resources.CpusetCpus != "" ||
|
|
resources.CpusetMems != "" ||
|
|
len(resources.Devices) != 0 ||
|
|
len(resources.DeviceCgroupRules) != 0 ||
|
|
resources.MemoryReservation != 0 ||
|
|
resources.MemorySwap != 0 ||
|
|
resources.MemorySwappiness != nil ||
|
|
resources.OomKillDisable != nil ||
|
|
(resources.PidsLimit != nil && *resources.PidsLimit != 0) ||
|
|
len(resources.Ulimits) != 0 ||
|
|
resources.CPUCount != 0 ||
|
|
resources.CPUPercent != 0 ||
|
|
resources.IOMaximumIOps != 0 ||
|
|
resources.IOMaximumBandwidth != 0 {
|
|
return errdefs.InvalidParameter(errors.New("resource updating isn't supported on Windows"))
|
|
}
|
|
// update HostConfig of container
|
|
if hostConfig.RestartPolicy.Name != "" {
|
|
if container.HostConfig.AutoRemove && !hostConfig.RestartPolicy.IsNone() {
|
|
return conflictingUpdateOptions("Restart policy cannot be updated because AutoRemove is enabled for the container")
|
|
}
|
|
container.HostConfig.RestartPolicy = hostConfig.RestartPolicy
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// BuildHostnameFile writes the container's hostname file.
|
|
func (container *Container) BuildHostnameFile() error {
|
|
return nil
|
|
}
|
|
|
|
// GetMountPoints gives a platform specific transformation to types.MountPoint. Callers must hold a Container lock.
|
|
func (container *Container) GetMountPoints() []containertypes.MountPoint {
|
|
mountPoints := make([]containertypes.MountPoint, 0, len(container.MountPoints))
|
|
for _, m := range container.MountPoints {
|
|
mountPoints = append(mountPoints, containertypes.MountPoint{
|
|
Type: m.Type,
|
|
Name: m.Name,
|
|
Source: m.Path(),
|
|
Destination: m.Destination,
|
|
Driver: m.Driver,
|
|
RW: m.RW,
|
|
})
|
|
}
|
|
return mountPoints
|
|
}
|
|
|
|
func (container *Container) ConfigsDirPath() string {
|
|
return filepath.Join(container.Root, "configs")
|
|
}
|
|
|
|
// ConfigFilePath returns the path to the on-disk location of a config.
|
|
func (container *Container) ConfigFilePath(configRef swarmtypes.ConfigReference) (string, error) {
|
|
return filepath.Join(container.ConfigsDirPath(), configRef.ConfigID), nil
|
|
}
|