2018-02-09 13:37:55 -05:00
|
|
|
package container
|
|
|
|
|
2018-02-13 10:45:40 -05:00
|
|
|
import (
|
2018-02-12 16:54:12 -05:00
|
|
|
"fmt"
|
2020-02-03 15:28:19 -05:00
|
|
|
"strings"
|
2018-02-12 16:54:12 -05:00
|
|
|
|
2018-02-13 10:45:40 -05:00
|
|
|
containertypes "github.com/docker/docker/api/types/container"
|
2018-10-10 06:20:13 -04:00
|
|
|
mounttypes "github.com/docker/docker/api/types/mount"
|
2018-03-28 04:47:11 -04:00
|
|
|
networktypes "github.com/docker/docker/api/types/network"
|
2018-02-13 10:45:40 -05:00
|
|
|
"github.com/docker/docker/api/types/strslice"
|
|
|
|
"github.com/docker/go-connections/nat"
|
2020-03-19 16:54:48 -04:00
|
|
|
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
2018-02-13 10:45:40 -05:00
|
|
|
)
|
2018-02-09 13:37:55 -05:00
|
|
|
|
|
|
|
// WithName sets the name of the container
|
|
|
|
func WithName(name string) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.Name = name
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithLinks sets the links of the container
|
|
|
|
func WithLinks(links ...string) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.HostConfig.Links = links
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-02 14:02:50 -05:00
|
|
|
// WithImage sets the image of the container
|
|
|
|
func WithImage(image string) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.Config.Image = image
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-09 13:37:55 -05:00
|
|
|
// WithCmd sets the comannds of the container
|
|
|
|
func WithCmd(cmds ...string) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.Config.Cmd = strslice.StrSlice(cmds)
|
|
|
|
}
|
|
|
|
}
|
2018-02-13 10:45:40 -05:00
|
|
|
|
|
|
|
// WithNetworkMode sets the network mode of the container
|
|
|
|
func WithNetworkMode(mode string) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.HostConfig.NetworkMode = containertypes.NetworkMode(mode)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithExposedPorts sets the exposed ports of the container
|
|
|
|
func WithExposedPorts(ports ...string) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.Config.ExposedPorts = map[nat.Port]struct{}{}
|
|
|
|
for _, port := range ports {
|
|
|
|
c.Config.ExposedPorts[nat.Port(port)] = struct{}{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithTty sets the TTY mode of the container
|
|
|
|
func WithTty(tty bool) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.Config.Tty = tty
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithWorkingDir sets the working dir of the container
|
|
|
|
func WithWorkingDir(dir string) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.Config.WorkingDir = dir
|
|
|
|
}
|
|
|
|
}
|
2018-02-12 16:54:12 -05:00
|
|
|
|
2018-10-10 06:20:13 -04:00
|
|
|
// WithMount adds an mount
|
|
|
|
func WithMount(m mounttypes.Mount) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.HostConfig.Mounts = append(c.HostConfig.Mounts, m)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-12 16:54:12 -05:00
|
|
|
// WithVolume sets the volume of the container
|
2020-02-03 15:28:19 -05:00
|
|
|
func WithVolume(target string) func(*TestContainerConfig) {
|
2018-02-12 16:54:12 -05:00
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
if c.Config.Volumes == nil {
|
|
|
|
c.Config.Volumes = map[string]struct{}{}
|
|
|
|
}
|
2020-02-03 15:28:19 -05:00
|
|
|
c.Config.Volumes[target] = struct{}{}
|
2018-02-12 16:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithBind sets the bind mount of the container
|
|
|
|
func WithBind(src, target string) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.HostConfig.Binds = append(c.HostConfig.Binds, fmt.Sprintf("%s:%s", src, target))
|
|
|
|
}
|
|
|
|
}
|
2018-03-28 04:47:11 -04:00
|
|
|
|
2020-02-03 15:28:19 -05:00
|
|
|
// WithTmpfs sets a target path in the container to a tmpfs
|
|
|
|
func WithTmpfs(target string) func(config *TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
if c.HostConfig.Tmpfs == nil {
|
|
|
|
c.HostConfig.Tmpfs = make(map[string]string)
|
|
|
|
}
|
|
|
|
|
|
|
|
spec := strings.SplitN(target, ":", 2)
|
|
|
|
var opts string
|
|
|
|
if len(spec) > 1 {
|
|
|
|
opts = spec[1]
|
|
|
|
}
|
|
|
|
c.HostConfig.Tmpfs[spec[0]] = opts
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-28 04:47:11 -04:00
|
|
|
// WithIPv4 sets the specified ip for the specified network of the container
|
|
|
|
func WithIPv4(network, ip string) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
2018-04-11 05:14:47 -04:00
|
|
|
if c.NetworkingConfig.EndpointsConfig == nil {
|
|
|
|
c.NetworkingConfig.EndpointsConfig = map[string]*networktypes.EndpointSettings{}
|
|
|
|
}
|
2018-03-28 04:47:11 -04:00
|
|
|
if v, ok := c.NetworkingConfig.EndpointsConfig[network]; !ok || v == nil {
|
|
|
|
c.NetworkingConfig.EndpointsConfig[network] = &networktypes.EndpointSettings{}
|
|
|
|
}
|
|
|
|
if c.NetworkingConfig.EndpointsConfig[network].IPAMConfig == nil {
|
|
|
|
c.NetworkingConfig.EndpointsConfig[network].IPAMConfig = &networktypes.EndpointIPAMConfig{}
|
|
|
|
}
|
|
|
|
c.NetworkingConfig.EndpointsConfig[network].IPAMConfig.IPv4Address = ip
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithIPv6 sets the specified ip6 for the specified network of the container
|
|
|
|
func WithIPv6(network, ip string) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
2018-04-11 05:14:47 -04:00
|
|
|
if c.NetworkingConfig.EndpointsConfig == nil {
|
|
|
|
c.NetworkingConfig.EndpointsConfig = map[string]*networktypes.EndpointSettings{}
|
|
|
|
}
|
2018-03-28 04:47:11 -04:00
|
|
|
if v, ok := c.NetworkingConfig.EndpointsConfig[network]; !ok || v == nil {
|
|
|
|
c.NetworkingConfig.EndpointsConfig[network] = &networktypes.EndpointSettings{}
|
|
|
|
}
|
|
|
|
if c.NetworkingConfig.EndpointsConfig[network].IPAMConfig == nil {
|
|
|
|
c.NetworkingConfig.EndpointsConfig[network].IPAMConfig = &networktypes.EndpointIPAMConfig{}
|
|
|
|
}
|
|
|
|
c.NetworkingConfig.EndpointsConfig[network].IPAMConfig.IPv6Address = ip
|
|
|
|
}
|
|
|
|
}
|
2018-05-09 17:20:11 -04:00
|
|
|
|
|
|
|
// WithLogDriver sets the log driver to use for the container
|
|
|
|
func WithLogDriver(driver string) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.HostConfig.LogConfig.Type = driver
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithAutoRemove sets the container to be removed on exit
|
|
|
|
func WithAutoRemove(c *TestContainerConfig) {
|
|
|
|
c.HostConfig.AutoRemove = true
|
|
|
|
}
|
2019-02-14 19:03:26 -05:00
|
|
|
|
2019-02-24 10:26:37 -05:00
|
|
|
// WithPidsLimit sets the container's "pids-limit
|
|
|
|
func WithPidsLimit(limit *int64) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
if c.HostConfig == nil {
|
|
|
|
c.HostConfig = &containertypes.HostConfig{}
|
|
|
|
}
|
|
|
|
c.HostConfig.PidsLimit = limit
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-14 19:03:26 -05:00
|
|
|
// WithRestartPolicy sets container's restart policy
|
|
|
|
func WithRestartPolicy(policy string) func(c *TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.HostConfig.RestartPolicy.Name = policy
|
|
|
|
}
|
|
|
|
}
|
2019-03-13 16:04:28 -04:00
|
|
|
|
|
|
|
// WithUser sets the user
|
|
|
|
func WithUser(user string) func(c *TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.Config.User = user
|
|
|
|
}
|
|
|
|
}
|
2019-03-14 23:44:18 -04:00
|
|
|
|
|
|
|
// WithPrivileged sets privileged mode for the container
|
|
|
|
func WithPrivileged(privileged bool) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
if c.HostConfig == nil {
|
|
|
|
c.HostConfig = &containertypes.HostConfig{}
|
|
|
|
}
|
|
|
|
c.HostConfig.Privileged = privileged
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithCgroupnsMode sets the cgroup namespace mode for the container
|
|
|
|
func WithCgroupnsMode(mode string) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
if c.HostConfig == nil {
|
|
|
|
c.HostConfig = &containertypes.HostConfig{}
|
|
|
|
}
|
|
|
|
c.HostConfig.CgroupnsMode = containertypes.CgroupnsMode(mode)
|
|
|
|
}
|
|
|
|
}
|
2019-11-01 20:09:40 -04:00
|
|
|
|
|
|
|
// WithExtraHost sets the user defined IP:Host mappings in the container's
|
|
|
|
// /etc/hosts file
|
|
|
|
func WithExtraHost(extraHost string) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.HostConfig.ExtraHosts = append(c.HostConfig.ExtraHosts, extraHost)
|
|
|
|
}
|
|
|
|
}
|
2020-03-19 16:54:48 -04:00
|
|
|
|
|
|
|
// WithPlatform specifies the desired platform the image should have.
|
|
|
|
func WithPlatform(p *specs.Platform) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.Platform = p
|
|
|
|
}
|
|
|
|
}
|
2022-03-12 05:05:55 -05:00
|
|
|
|
|
|
|
// WithWindowsDevice specifies a Windows Device, ala `--device` on the CLI
|
|
|
|
func WithWindowsDevice(device string) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.HostConfig.Devices = append(c.HostConfig.Devices, containertypes.DeviceMapping{PathOnHost: device})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithIsolation specifies the isolation technology to apply to the container
|
|
|
|
func WithIsolation(isolation containertypes.Isolation) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.HostConfig.Isolation = isolation
|
|
|
|
}
|
|
|
|
}
|
2022-05-12 08:54:44 -04:00
|
|
|
|
|
|
|
// WithConsoleSize sets the initial console size of the container
|
|
|
|
func WithConsoleSize(width, height uint) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.HostConfig.ConsoleSize = [2]uint{height, width}
|
|
|
|
}
|
|
|
|
}
|
daemon: support other containerd runtimes (MVP)
Contrary to popular belief, the OCI Runtime specification does not
specify the command-line API for runtimes. Looking at containerd's
architecture from the lens of the OCI Runtime spec, the _shim_ is the
OCI Runtime and runC is "just" an implementation detail of the
io.containerd.runc.v2 runtime. When one configures a non-default runtime
in Docker, what they're really doing is instructing Docker to create
containers using the io.containerd.runc.v2 runtime with a configuration
option telling the runtime that the runC binary is at some non-default
path. Consequently, only OCI runtimes which are compatible with the
io.containerd.runc.v2 shim, such as crun, can be used in this manner.
Other OCI runtimes, including kata-containers v2, come with their own
containerd shim and are not compatible with io.containerd.runc.v2.
As Docker has not historically provided a way to select a non-default
runtime which requires its own shim, runtimes such as kata-containers v2
could not be used with Docker.
Allow other containerd shims to be used with Docker; no daemon
configuration required. If the daemon is instructed to create a
container with a runtime name which does not match any of the configured
or stock runtimes, it passes the name along to containerd verbatim. A
user can start a container with the kata-containers runtime, for
example, simply by calling
docker run --runtime io.containerd.kata.v2
Runtime names which containerd would interpret as a path to an arbitrary
binary are disallowed. While handy for development and testing it is not
strictly necessary and would allow anyone with Engine API access to
trivially execute any binary on the host as root, so we have decided it
would be safest for our users if it was not allowed.
It is not yet possible to set an alternative containerd shim as the
default runtime; it can only be configured per-container.
Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-07-20 16:12:01 -04:00
|
|
|
|
|
|
|
// WithRuntime sets the runtime to use to start the container
|
|
|
|
func WithRuntime(name string) func(*TestContainerConfig) {
|
|
|
|
return func(c *TestContainerConfig) {
|
|
|
|
c.HostConfig.Runtime = name
|
|
|
|
}
|
|
|
|
}
|