moby: add a Devices array to the image yml

According to https://github.com/linuxkit/linuxkit/pull/3684#issuecomment-860128095

runc removed the console as a default device, so now it must be specified
explicitly in the OCI config.

See 60e21ec26e

The similar code in moby/moby is here: https://github.com/moby/moby/blob/master/oci/devices_linux.go

This patch allows packages to declare a `devices` array, which can contain `/dev/console` etc.

Signed-off-by: David Scott <dave@recoil.org>
This commit is contained in:
David Scott 2021-08-07 19:54:00 +01:00
parent d0145160a8
commit 24db42dd68
4 changed files with 104 additions and 1 deletions

View File

@ -232,6 +232,21 @@ services:
- CAP_DAC_OVERRIDE
```
## `devices`
To access the console, it's necessary to explicitly add a "device" definition, for example:
```
devices:
- path: "/dev/console"
type: c
major: 5
minor: 1
mode: 0666
```
See the [the getty package](../pkg/getty/build.yml) for a more complete example
and see [runc](https://github.com/opencontainers/runc/commit/60e21ec26e15945259d4b1e790e8fd119ee86467) for context).
### Mount Options
When mounting filesystem paths into a container - whether as part of `onboot` or `services` - there are several options of which you need to be aware. Using them properly is necessary for your containers to function properly.

View File

@ -14,5 +14,26 @@ config:
- /var/lib/containerd:/var/lib/containerd
- /dev:/dev
- /sys:/sys
devices:
- path: "/dev/console"
type: c
major: 5
minor: 1
mode: 0666
- path: "/dev/tty0"
type: c
major: 4
minor: 0
mode: 0666
- path: "/dev/ttyS0"
type: c
major: 4
minor: 64
mode: 0666
- path: "/dev/ttyAMA0"
type: c
major: 204
minor: 64
mode: 0666
capabilities:
- all

View File

@ -2,6 +2,7 @@ package moby
import (
"fmt"
"os"
"sort"
"strconv"
"strings"
@ -70,6 +71,7 @@ type ImageConfig struct {
Mounts *[]specs.Mount `yaml:"mounts,omitempty" json:"mounts,omitempty"`
Binds *[]string `yaml:"binds,omitempty" json:"binds,omitempty"`
BindsAdd *[]string `yaml:"binds.add,omitempty" json:"binds.add,omitempty"`
Devices *[]Device `yaml:"devices,omitempty" json:"devices,omitempty"`
Tmpfs *[]string `yaml:"tmpfs,omitempty" json:"tmpfs,omitempty"`
Command *[]string `yaml:"command,omitempty" json:"command,omitempty"`
Env *[]string `yaml:"env,omitempty" json:"env,omitempty"`
@ -102,6 +104,15 @@ type ImageConfig struct {
ref *reference.Spec
}
// Device specifies a device to be exposed to the container.
type Device struct {
Path string `yaml:"path" json:"path"`
Type string `yaml:"type" json:"type"`
Major int64 `yaml:"major" json:"major"`
Minor int64 `yaml:"minor" json:"minor"`
Mode string `yaml:"mode,omitempty" json:"mode,omitempty"`
}
// Runtime is the type of config processed at runtime, not used to build the OCI spec
type Runtime struct {
Cgroups *[]string `yaml:"cgroups,omitempty" json:"cgroups,omitempty"`
@ -561,6 +572,17 @@ func assignResources(v1, v2 *specs.LinuxResources) specs.LinuxResources {
return specs.LinuxResources{}
}
// assignDevices does ordered overrides from Devices
func assignDevices(v1, v2 *[]Device) []Device {
if v2 != nil {
return *v2
}
if v1 != nil {
return *v1
}
return []Device{}
}
// assignRuntime does ordered overrides from Runtime
func assignRuntime(v1, v2 *Runtime) Runtime {
if v1 == nil {
@ -1021,6 +1043,25 @@ func ConfigToOCI(yaml *Image, config imagespec.ImageConfig, idMap map[string]uin
resources := assignResources(label.Resources, yaml.Resources)
devices := assignDevices(label.Devices, yaml.Devices)
var linuxDevices []specs.LinuxDevice
for _, device := range devices {
mode, err := strconv.ParseInt(device.Mode, 8, 32)
if err != nil {
return oci, runtime, fmt.Errorf("Cannot parse device mode as octal value: %v", err)
}
fileMode := os.FileMode(mode)
linuxDevice := specs.LinuxDevice{
Path: device.Path,
Type: device.Type,
Major: device.Major,
Minor: device.Minor,
FileMode: &fileMode,
}
linuxDevices = append(linuxDevices, linuxDevice)
resources.Devices = append(resources.Devices, deviceCgroup(linuxDevice))
}
oci.Linux = &specs.Linux{
UIDMappings: assignMappings(label.UIDMappings, yaml.UIDMappings),
GIDMappings: assignMappings(label.GIDMappings, yaml.GIDMappings),
@ -1028,7 +1069,7 @@ func ConfigToOCI(yaml *Image, config imagespec.ImageConfig, idMap map[string]uin
Resources: &resources,
CgroupsPath: assignString(label.CgroupsPath, yaml.CgroupsPath),
Namespaces: namespaces,
// Devices
Devices: linuxDevices,
// Seccomp
RootfsPropagation: assignString(label.RootfsPropagation, yaml.RootfsPropagation),
MaskedPaths: assignStrings(label.MaskedPaths, yaml.MaskedPaths),
@ -1041,3 +1082,13 @@ func ConfigToOCI(yaml *Image, config imagespec.ImageConfig, idMap map[string]uin
return oci, runtime, nil
}
func deviceCgroup(device specs.LinuxDevice) specs.LinuxDeviceCgroup {
return specs.LinuxDeviceCgroup{
Allow: true,
Type: device.Type,
Major: &device.Major,
Minor: &device.Minor,
Access: "rwm",
}
}

View File

@ -67,6 +67,21 @@ var schema = string(`
"type": "array",
"items": { "$ref": "#/definitions/mount" }
},
"device": {
"type": "object",
"additionalProperties": false,
"properties": {
"path": { "type": "string" },
"type": { "type": "string" },
"major": { "type": "integer" },
"minor": { "type": "integer" },
"mode": { "type": "string" }
}
},
"devices": {
"type": "array",
"items": { "$ref": "#/definitions/device" }
},
"idmapping": {
"type": "object",
"additionalProperties": false,
@ -265,6 +280,7 @@ var schema = string(`
"mounts": { "$ref": "#/definitions/mounts" },
"binds": { "$ref": "#/definitions/strings" },
"binds.add": { "$ref": "#/definitions/strings" },
"devices": { "$ref": "#/definitions/devices" },
"tmpfs": { "$ref": "#/definitions/strings" },
"command": { "$ref": "#/definitions/strings" },
"env": { "$ref": "#/definitions/strings" },