|
@@ -8,160 +8,245 @@ import (
|
|
"path"
|
|
"path"
|
|
"strconv"
|
|
"strconv"
|
|
"strings"
|
|
"strings"
|
|
|
|
+ "time"
|
|
|
|
|
|
"github.com/docker/docker/opts"
|
|
"github.com/docker/docker/opts"
|
|
- flag "github.com/docker/docker/pkg/mflag"
|
|
|
|
"github.com/docker/docker/pkg/mount"
|
|
"github.com/docker/docker/pkg/mount"
|
|
"github.com/docker/docker/pkg/signal"
|
|
"github.com/docker/docker/pkg/signal"
|
|
"github.com/docker/engine-api/types/container"
|
|
"github.com/docker/engine-api/types/container"
|
|
networktypes "github.com/docker/engine-api/types/network"
|
|
networktypes "github.com/docker/engine-api/types/network"
|
|
"github.com/docker/engine-api/types/strslice"
|
|
"github.com/docker/engine-api/types/strslice"
|
|
"github.com/docker/go-connections/nat"
|
|
"github.com/docker/go-connections/nat"
|
|
- "github.com/docker/go-units"
|
|
|
|
|
|
+ units "github.com/docker/go-units"
|
|
|
|
+ "github.com/spf13/pflag"
|
|
)
|
|
)
|
|
|
|
|
|
-// Parse parses the specified args for the specified command and generates a Config,
|
|
|
|
|
|
+// ContainerOptions is a data object with all the options for creating a container
|
|
|
|
+// TODO: remove fl prefix
|
|
|
|
+type ContainerOptions struct {
|
|
|
|
+ flAttach opts.ListOpts
|
|
|
|
+ flVolumes opts.ListOpts
|
|
|
|
+ flTmpfs opts.ListOpts
|
|
|
|
+ flBlkioWeightDevice WeightdeviceOpt
|
|
|
|
+ flDeviceReadBps ThrottledeviceOpt
|
|
|
|
+ flDeviceWriteBps ThrottledeviceOpt
|
|
|
|
+ flLinks opts.ListOpts
|
|
|
|
+ flAliases opts.ListOpts
|
|
|
|
+ flDeviceReadIOps ThrottledeviceOpt
|
|
|
|
+ flDeviceWriteIOps ThrottledeviceOpt
|
|
|
|
+ flEnv opts.ListOpts
|
|
|
|
+ flLabels opts.ListOpts
|
|
|
|
+ flDevices opts.ListOpts
|
|
|
|
+ flUlimits *UlimitOpt
|
|
|
|
+ flSysctls *opts.MapOpts
|
|
|
|
+ flPublish opts.ListOpts
|
|
|
|
+ flExpose opts.ListOpts
|
|
|
|
+ flDNS opts.ListOpts
|
|
|
|
+ flDNSSearch opts.ListOpts
|
|
|
|
+ flDNSOptions opts.ListOpts
|
|
|
|
+ flExtraHosts opts.ListOpts
|
|
|
|
+ flVolumesFrom opts.ListOpts
|
|
|
|
+ flEnvFile opts.ListOpts
|
|
|
|
+ flCapAdd opts.ListOpts
|
|
|
|
+ flCapDrop opts.ListOpts
|
|
|
|
+ flGroupAdd opts.ListOpts
|
|
|
|
+ flSecurityOpt opts.ListOpts
|
|
|
|
+ flStorageOpt opts.ListOpts
|
|
|
|
+ flLabelsFile opts.ListOpts
|
|
|
|
+ flLoggingOpts opts.ListOpts
|
|
|
|
+ flPrivileged *bool
|
|
|
|
+ flPidMode *string
|
|
|
|
+ flUTSMode *string
|
|
|
|
+ flUsernsMode *string
|
|
|
|
+ flPublishAll *bool
|
|
|
|
+ flStdin *bool
|
|
|
|
+ flTty *bool
|
|
|
|
+ flOomKillDisable *bool
|
|
|
|
+ flOomScoreAdj *int
|
|
|
|
+ flContainerIDFile *string
|
|
|
|
+ flEntrypoint *string
|
|
|
|
+ flHostname *string
|
|
|
|
+ flMemoryString *string
|
|
|
|
+ flMemoryReservation *string
|
|
|
|
+ flMemorySwap *string
|
|
|
|
+ flKernelMemory *string
|
|
|
|
+ flUser *string
|
|
|
|
+ flWorkingDir *string
|
|
|
|
+ flCPUShares *int64
|
|
|
|
+ flCPUPercent *int64
|
|
|
|
+ flCPUPeriod *int64
|
|
|
|
+ flCPUQuota *int64
|
|
|
|
+ flCpusetCpus *string
|
|
|
|
+ flCpusetMems *string
|
|
|
|
+ flBlkioWeight *uint16
|
|
|
|
+ flIOMaxBandwidth *string
|
|
|
|
+ flIOMaxIOps *uint64
|
|
|
|
+ flSwappiness *int64
|
|
|
|
+ flNetMode *string
|
|
|
|
+ flMacAddress *string
|
|
|
|
+ flIPv4Address *string
|
|
|
|
+ flIPv6Address *string
|
|
|
|
+ flIpcMode *string
|
|
|
|
+ flPidsLimit *int64
|
|
|
|
+ flRestartPolicy *string
|
|
|
|
+ flReadonlyRootfs *bool
|
|
|
|
+ flLoggingDriver *string
|
|
|
|
+ flCgroupParent *string
|
|
|
|
+ flVolumeDriver *string
|
|
|
|
+ flStopSignal *string
|
|
|
|
+ flIsolation *string
|
|
|
|
+ flShmSize *string
|
|
|
|
+ flNoHealthcheck *bool
|
|
|
|
+ flHealthCmd *string
|
|
|
|
+ flHealthInterval *time.Duration
|
|
|
|
+ flHealthTimeout *time.Duration
|
|
|
|
+ flHealthRetries *int
|
|
|
|
+
|
|
|
|
+ Image string
|
|
|
|
+ Args []string
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// AddFlags adds all command line flags that will be used by Parse to the FlagSet
|
|
|
|
+func AddFlags(flags *pflag.FlagSet) *ContainerOptions {
|
|
|
|
+ copts := &ContainerOptions{
|
|
|
|
+ flAttach: opts.NewListOpts(ValidateAttach),
|
|
|
|
+ flVolumes: opts.NewListOpts(nil),
|
|
|
|
+ flTmpfs: opts.NewListOpts(nil),
|
|
|
|
+ flBlkioWeightDevice: NewWeightdeviceOpt(ValidateWeightDevice),
|
|
|
|
+ flDeviceReadBps: NewThrottledeviceOpt(ValidateThrottleBpsDevice),
|
|
|
|
+ flDeviceWriteBps: NewThrottledeviceOpt(ValidateThrottleBpsDevice),
|
|
|
|
+ flLinks: opts.NewListOpts(ValidateLink),
|
|
|
|
+ flAliases: opts.NewListOpts(nil),
|
|
|
|
+ flDeviceReadIOps: NewThrottledeviceOpt(ValidateThrottleIOpsDevice),
|
|
|
|
+ flDeviceWriteIOps: NewThrottledeviceOpt(ValidateThrottleIOpsDevice),
|
|
|
|
+ flEnv: opts.NewListOpts(ValidateEnv),
|
|
|
|
+ flLabels: opts.NewListOpts(ValidateEnv),
|
|
|
|
+ flDevices: opts.NewListOpts(ValidateDevice),
|
|
|
|
+
|
|
|
|
+ flUlimits: NewUlimitOpt(nil),
|
|
|
|
+ flSysctls: opts.NewMapOpts(nil, opts.ValidateSysctl),
|
|
|
|
+
|
|
|
|
+ flPublish: opts.NewListOpts(nil),
|
|
|
|
+ flExpose: opts.NewListOpts(nil),
|
|
|
|
+ flDNS: opts.NewListOpts(opts.ValidateIPAddress),
|
|
|
|
+ flDNSSearch: opts.NewListOpts(opts.ValidateDNSSearch),
|
|
|
|
+ flDNSOptions: opts.NewListOpts(nil),
|
|
|
|
+ flExtraHosts: opts.NewListOpts(ValidateExtraHost),
|
|
|
|
+ flVolumesFrom: opts.NewListOpts(nil),
|
|
|
|
+ flEnvFile: opts.NewListOpts(nil),
|
|
|
|
+ flCapAdd: opts.NewListOpts(nil),
|
|
|
|
+ flCapDrop: opts.NewListOpts(nil),
|
|
|
|
+ flGroupAdd: opts.NewListOpts(nil),
|
|
|
|
+ flSecurityOpt: opts.NewListOpts(nil),
|
|
|
|
+ flStorageOpt: opts.NewListOpts(nil),
|
|
|
|
+ flLabelsFile: opts.NewListOpts(nil),
|
|
|
|
+ flLoggingOpts: opts.NewListOpts(nil),
|
|
|
|
+
|
|
|
|
+ flPrivileged: flags.Bool("privileged", false, "Give extended privileges to this container"),
|
|
|
|
+ flPidMode: flags.String("pid", "", "PID namespace to use"),
|
|
|
|
+ flUTSMode: flags.String("uts", "", "UTS namespace to use"),
|
|
|
|
+ flUsernsMode: flags.String("userns", "", "User namespace to use"),
|
|
|
|
+ flPublishAll: flags.BoolP("publish-all", "P", false, "Publish all exposed ports to random ports"),
|
|
|
|
+ flStdin: flags.BoolP("interactive", "i", false, "Keep STDIN open even if not attached"),
|
|
|
|
+ flTty: flags.BoolP("tty", "t", false, "Allocate a pseudo-TTY"),
|
|
|
|
+ flOomKillDisable: flags.Bool("oom-kill-disable", false, "Disable OOM Killer"),
|
|
|
|
+ flOomScoreAdj: flags.Int("oom-score-adj", 0, "Tune host's OOM preferences (-1000 to 1000)"),
|
|
|
|
+ flContainerIDFile: flags.String("cidfile", "", "Write the container ID to the file"),
|
|
|
|
+ flEntrypoint: flags.String("entrypoint", "", "Overwrite the default ENTRYPOINT of the image"),
|
|
|
|
+ flHostname: flags.StringP("hostname", "h", "", "Container host name"),
|
|
|
|
+ flMemoryString: flags.StringP("memory", "m", "", "Memory limit"),
|
|
|
|
+ flMemoryReservation: flags.String("memory-reservation", "", "Memory soft limit"),
|
|
|
|
+ flMemorySwap: flags.String("memory-swap", "", "Swap limit equal to memory plus swap: '-1' to enable unlimited swap"),
|
|
|
|
+ flKernelMemory: flags.String("kernel-memory", "", "Kernel memory limit"),
|
|
|
|
+ flUser: flags.StringP("user", "u", "", "Username or UID (format: <name|uid>[:<group|gid>])"),
|
|
|
|
+ flWorkingDir: flags.StringP("workdir", "w", "", "Working directory inside the container"),
|
|
|
|
+ flCPUShares: flags.Int64P("cpu-shares", "c", 0, "CPU shares (relative weight)"),
|
|
|
|
+ flCPUPercent: flags.Int64("cpu-percent", 0, "CPU percent (Windows only)"),
|
|
|
|
+ flCPUPeriod: flags.Int64("cpu-period", 0, "Limit CPU CFS (Completely Fair Scheduler) period"),
|
|
|
|
+ flCPUQuota: flags.Int64("cpu-quota", 0, "Limit CPU CFS (Completely Fair Scheduler) quota"),
|
|
|
|
+ flCpusetCpus: flags.String("cpuset-cpus", "", "CPUs in which to allow execution (0-3, 0,1)"),
|
|
|
|
+ flCpusetMems: flags.String("cpuset-mems", "", "MEMs in which to allow execution (0-3, 0,1)"),
|
|
|
|
+ flBlkioWeight: flags.Uint16("blkio-weight", 0, "Block IO (relative weight), between 10 and 1000"),
|
|
|
|
+ flIOMaxBandwidth: flags.String("io-maxbandwidth", "", "Maximum IO bandwidth limit for the system drive (Windows only)"),
|
|
|
|
+ flIOMaxIOps: flags.Uint64("io-maxiops", 0, "Maximum IOps limit for the system drive (Windows only)"),
|
|
|
|
+ flSwappiness: flags.Int64("memory-swappiness", -1, "Tune container memory swappiness (0 to 100)"),
|
|
|
|
+ flNetMode: flags.String("net", "default", "Connect a container to a network"),
|
|
|
|
+ flMacAddress: flags.String("mac-address", "", "Container MAC address (e.g. 92:d0:c6:0a:29:33)"),
|
|
|
|
+ flIPv4Address: flags.String("ip", "", "Container IPv4 address (e.g. 172.30.100.104)"),
|
|
|
|
+ flIPv6Address: flags.String("ip6", "", "Container IPv6 address (e.g. 2001:db8::33)"),
|
|
|
|
+ flIpcMode: flags.String("ipc", "", "IPC namespace to use"),
|
|
|
|
+ flPidsLimit: flags.Int64("pids-limit", 0, "Tune container pids limit (set -1 for unlimited)"),
|
|
|
|
+ flRestartPolicy: flags.String("restart", "no", "Restart policy to apply when a container exits"),
|
|
|
|
+ flReadonlyRootfs: flags.Bool("read-only", false, "Mount the container's root filesystem as read only"),
|
|
|
|
+ flLoggingDriver: flags.String("log-driver", "", "Logging driver for container"),
|
|
|
|
+ flCgroupParent: flags.String("cgroup-parent", "", "Optional parent cgroup for the container"),
|
|
|
|
+ flVolumeDriver: flags.String("volume-driver", "", "Optional volume driver for the container"),
|
|
|
|
+ flStopSignal: flags.String("stop-signal", signal.DefaultStopSignal, fmt.Sprintf("Signal to stop a container, %v by default", signal.DefaultStopSignal)),
|
|
|
|
+ flIsolation: flags.String("isolation", "", "Container isolation technology"),
|
|
|
|
+ flShmSize: flags.String("shm-size", "", "Size of /dev/shm, default value is 64MB"),
|
|
|
|
+ flNoHealthcheck: cmd.Bool([]string{"-no-healthcheck"}, false, "Disable any container-specified HEALTHCHECK"),
|
|
|
|
+ flHealthCmd: cmd.String([]string{"-health-cmd"}, "", "Command to run to check health"),
|
|
|
|
+ flHealthInterval: cmd.Duration([]string{"-health-interval"}, 0, "Time between running the check"),
|
|
|
|
+ flHealthTimeout: cmd.Duration([]string{"-health-timeout"}, 0, "Maximum time to allow one check to run"),
|
|
|
|
+ flHealthRetries: cmd.Int([]string{"-health-retries"}, 0, "Consecutive failures needed to report unhealthy"),
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ flags.VarP(&copts.flAttach, "attach", "a", "Attach to STDIN, STDOUT or STDERR")
|
|
|
|
+ flags.Var(&copts.flBlkioWeightDevice, "blkio-weight-device", "Block IO weight (relative device weight)")
|
|
|
|
+ flags.Var(&copts.flDeviceReadBps, "device-read-bps", "Limit read rate (bytes per second) from a device")
|
|
|
|
+ flags.Var(&copts.flDeviceWriteBps, "device-write-bps", "Limit write rate (bytes per second) to a device")
|
|
|
|
+ flags.Var(&copts.flDeviceReadIOps, "device-read-iops", "Limit read rate (IO per second) from a device")
|
|
|
|
+ flags.Var(&copts.flDeviceWriteIOps, "device-write-iops", "Limit write rate (IO per second) to a device")
|
|
|
|
+ flags.VarP(&copts.flVolumes, "volume", "v", "Bind mount a volume")
|
|
|
|
+ flags.Var(&copts.flTmpfs, "tmpfs", "Mount a tmpfs directory")
|
|
|
|
+ flags.Var(&copts.flLinks, "link", "Add link to another container")
|
|
|
|
+ flags.Var(&copts.flAliases, "net-alias", "Add network-scoped alias for the container")
|
|
|
|
+ flags.Var(&copts.flDevices, "device", "Add a host device to the container")
|
|
|
|
+ flags.VarP(&copts.flLabels, "label", "l", "Set meta data on a container")
|
|
|
|
+ flags.Var(&copts.flLabelsFile, "label-file", "Read in a line delimited file of labels")
|
|
|
|
+ flags.VarP(&copts.flEnv, "env", "e", "Set environment variables")
|
|
|
|
+ flags.Var(&copts.flEnvFile, "env-file", "Read in a file of environment variables")
|
|
|
|
+ flags.VarP(&copts.flPublish, "publish", "p", "Publish a container's port(s) to the host")
|
|
|
|
+ flags.Var(&copts.flExpose, "expose", "Expose a port or a range of ports")
|
|
|
|
+ flags.Var(&copts.flDNS, "dns", "Set custom DNS servers")
|
|
|
|
+ flags.Var(&copts.flDNSSearch, "dns-search", "Set custom DNS search domains")
|
|
|
|
+ flags.Var(&copts.flDNSOptions, "dns-opt", "Set DNS options")
|
|
|
|
+ flags.Var(&copts.flExtraHosts, "add-host", "Add a custom host-to-IP mapping (host:ip)")
|
|
|
|
+ flags.Var(&copts.flVolumesFrom, "volumes-from", "Mount volumes from the specified container(s)")
|
|
|
|
+ flags.Var(&copts.flCapAdd, "cap-add", "Add Linux capabilities")
|
|
|
|
+ flags.Var(&copts.flCapDrop, "cap-drop", "Drop Linux capabilities")
|
|
|
|
+ flags.Var(&copts.flGroupAdd, "group-add", "Add additional groups to join")
|
|
|
|
+ flags.Var(&copts.flSecurityOpt, "security-opt", "Security Options")
|
|
|
|
+ flags.Var(&copts.flStorageOpt, "storage-opt", "Set storage driver options per container")
|
|
|
|
+ flags.Var(copts.flUlimits, "ulimit", "Ulimit options")
|
|
|
|
+ flags.Var(copts.flSysctls, "sysctl", "Sysctl options")
|
|
|
|
+ flags.Var(&copts.flLoggingOpts, "log-opt", "Log driver options")
|
|
|
|
+
|
|
|
|
+ return copts
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Parse parses the args for the specified command and generates a Config,
|
|
// a HostConfig and returns them with the specified command.
|
|
// a HostConfig and returns them with the specified command.
|
|
// If the specified args are not valid, it will return an error.
|
|
// If the specified args are not valid, it will return an error.
|
|
-func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.HostConfig, *networktypes.NetworkingConfig, *flag.FlagSet, error) {
|
|
|
|
- var (
|
|
|
|
- // FIXME: use utils.ListOpts for attach and volumes?
|
|
|
|
- flAttach = opts.NewListOpts(ValidateAttach)
|
|
|
|
- flVolumes = opts.NewListOpts(nil)
|
|
|
|
- flTmpfs = opts.NewListOpts(nil)
|
|
|
|
- flBlkioWeightDevice = NewWeightdeviceOpt(ValidateWeightDevice)
|
|
|
|
- flDeviceReadBps = NewThrottledeviceOpt(ValidateThrottleBpsDevice)
|
|
|
|
- flDeviceWriteBps = NewThrottledeviceOpt(ValidateThrottleBpsDevice)
|
|
|
|
- flLinks = opts.NewListOpts(ValidateLink)
|
|
|
|
- flAliases = opts.NewListOpts(nil)
|
|
|
|
- flDeviceReadIOps = NewThrottledeviceOpt(ValidateThrottleIOpsDevice)
|
|
|
|
- flDeviceWriteIOps = NewThrottledeviceOpt(ValidateThrottleIOpsDevice)
|
|
|
|
- flEnv = opts.NewListOpts(ValidateEnv)
|
|
|
|
- flLabels = opts.NewListOpts(ValidateEnv)
|
|
|
|
- flDevices = opts.NewListOpts(ValidateDevice)
|
|
|
|
-
|
|
|
|
- flUlimits = NewUlimitOpt(nil)
|
|
|
|
- flSysctls = opts.NewMapOpts(nil, opts.ValidateSysctl)
|
|
|
|
-
|
|
|
|
- flPublish = opts.NewListOpts(nil)
|
|
|
|
- flExpose = opts.NewListOpts(nil)
|
|
|
|
- flDNS = opts.NewListOpts(opts.ValidateIPAddress)
|
|
|
|
- flDNSSearch = opts.NewListOpts(opts.ValidateDNSSearch)
|
|
|
|
- flDNSOptions = opts.NewListOpts(nil)
|
|
|
|
- flExtraHosts = opts.NewListOpts(ValidateExtraHost)
|
|
|
|
- flVolumesFrom = opts.NewListOpts(nil)
|
|
|
|
- flEnvFile = opts.NewListOpts(nil)
|
|
|
|
- flCapAdd = opts.NewListOpts(nil)
|
|
|
|
- flCapDrop = opts.NewListOpts(nil)
|
|
|
|
- flGroupAdd = opts.NewListOpts(nil)
|
|
|
|
- flSecurityOpt = opts.NewListOpts(nil)
|
|
|
|
- flStorageOpt = opts.NewListOpts(nil)
|
|
|
|
- flLabelsFile = opts.NewListOpts(nil)
|
|
|
|
- flLoggingOpts = opts.NewListOpts(nil)
|
|
|
|
- flPrivileged = cmd.Bool([]string{"-privileged"}, false, "Give extended privileges to this container")
|
|
|
|
- flPidMode = cmd.String([]string{"-pid"}, "", "PID namespace to use")
|
|
|
|
- flUTSMode = cmd.String([]string{"-uts"}, "", "UTS namespace to use")
|
|
|
|
- flUsernsMode = cmd.String([]string{"-userns"}, "", "User namespace to use")
|
|
|
|
- flPublishAll = cmd.Bool([]string{"P", "-publish-all"}, false, "Publish all exposed ports to random ports")
|
|
|
|
- flStdin = cmd.Bool([]string{"i", "-interactive"}, false, "Keep STDIN open even if not attached")
|
|
|
|
- flTty = cmd.Bool([]string{"t", "-tty"}, false, "Allocate a pseudo-TTY")
|
|
|
|
- flOomKillDisable = cmd.Bool([]string{"-oom-kill-disable"}, false, "Disable OOM Killer")
|
|
|
|
- flOomScoreAdj = cmd.Int([]string{"-oom-score-adj"}, 0, "Tune host's OOM preferences (-1000 to 1000)")
|
|
|
|
- flContainerIDFile = cmd.String([]string{"-cidfile"}, "", "Write the container ID to the file")
|
|
|
|
- flEntrypoint = cmd.String([]string{"-entrypoint"}, "", "Overwrite the default ENTRYPOINT of the image")
|
|
|
|
- flHostname = cmd.String([]string{"h", "-hostname"}, "", "Container host name")
|
|
|
|
- flMemoryString = cmd.String([]string{"m", "-memory"}, "", "Memory limit")
|
|
|
|
- flMemoryReservation = cmd.String([]string{"-memory-reservation"}, "", "Memory soft limit")
|
|
|
|
- flMemorySwap = cmd.String([]string{"-memory-swap"}, "", "Swap limit equal to memory plus swap: '-1' to enable unlimited swap")
|
|
|
|
- flKernelMemory = cmd.String([]string{"-kernel-memory"}, "", "Kernel memory limit")
|
|
|
|
- flUser = cmd.String([]string{"u", "-user"}, "", "Username or UID (format: <name|uid>[:<group|gid>])")
|
|
|
|
- flWorkingDir = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container")
|
|
|
|
- flCPUShares = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
|
|
|
|
- flCPUPercent = cmd.Int64([]string{"-cpu-percent"}, 0, "CPU percent (Windows only)")
|
|
|
|
- flCPUPeriod = cmd.Int64([]string{"-cpu-period"}, 0, "Limit CPU CFS (Completely Fair Scheduler) period")
|
|
|
|
- flCPUQuota = cmd.Int64([]string{"-cpu-quota"}, 0, "Limit CPU CFS (Completely Fair Scheduler) quota")
|
|
|
|
- flCpusetCpus = cmd.String([]string{"-cpuset-cpus"}, "", "CPUs in which to allow execution (0-3, 0,1)")
|
|
|
|
- flCpusetMems = cmd.String([]string{"-cpuset-mems"}, "", "MEMs in which to allow execution (0-3, 0,1)")
|
|
|
|
- flBlkioWeight = cmd.Uint16([]string{"-blkio-weight"}, 0, "Block IO (relative weight), between 10 and 1000")
|
|
|
|
- flIOMaxBandwidth = cmd.String([]string{"-io-maxbandwidth"}, "", "Maximum IO bandwidth limit for the system drive (Windows only)")
|
|
|
|
- flIOMaxIOps = cmd.Uint64([]string{"-io-maxiops"}, 0, "Maximum IOps limit for the system drive (Windows only)")
|
|
|
|
- flSwappiness = cmd.Int64([]string{"-memory-swappiness"}, -1, "Tune container memory swappiness (0 to 100)")
|
|
|
|
- flNetMode = cmd.String([]string{"-net"}, "default", "Connect a container to a network")
|
|
|
|
- flMacAddress = cmd.String([]string{"-mac-address"}, "", "Container MAC address (e.g. 92:d0:c6:0a:29:33)")
|
|
|
|
- flIPv4Address = cmd.String([]string{"-ip"}, "", "Container IPv4 address (e.g. 172.30.100.104)")
|
|
|
|
- flIPv6Address = cmd.String([]string{"-ip6"}, "", "Container IPv6 address (e.g. 2001:db8::33)")
|
|
|
|
- flIpcMode = cmd.String([]string{"-ipc"}, "", "IPC namespace to use")
|
|
|
|
- flPidsLimit = cmd.Int64([]string{"-pids-limit"}, 0, "Tune container pids limit (set -1 for unlimited)")
|
|
|
|
- flRestartPolicy = cmd.String([]string{"-restart"}, "no", "Restart policy to apply when a container exits")
|
|
|
|
- flReadonlyRootfs = cmd.Bool([]string{"-read-only"}, false, "Mount the container's root filesystem as read only")
|
|
|
|
- flLoggingDriver = cmd.String([]string{"-log-driver"}, "", "Logging driver for container")
|
|
|
|
- flCgroupParent = cmd.String([]string{"-cgroup-parent"}, "", "Optional parent cgroup for the container")
|
|
|
|
- flVolumeDriver = cmd.String([]string{"-volume-driver"}, "", "Optional volume driver for the container")
|
|
|
|
- flStopSignal = cmd.String([]string{"-stop-signal"}, signal.DefaultStopSignal, fmt.Sprintf("Signal to stop a container, %v by default", signal.DefaultStopSignal))
|
|
|
|
- flIsolation = cmd.String([]string{"-isolation"}, "", "Container isolation technology")
|
|
|
|
- flShmSize = cmd.String([]string{"-shm-size"}, "", "Size of /dev/shm, default value is 64MB")
|
|
|
|
- // Healthcheck
|
|
|
|
- flNoHealthcheck = cmd.Bool([]string{"-no-healthcheck"}, false, "Disable any container-specified HEALTHCHECK")
|
|
|
|
- flHealthCmd = cmd.String([]string{"-health-cmd"}, "", "Command to run to check health")
|
|
|
|
- flHealthInterval = cmd.Duration([]string{"-health-interval"}, 0, "Time between running the check")
|
|
|
|
- flHealthTimeout = cmd.Duration([]string{"-health-timeout"}, 0, "Maximum time to allow one check to run")
|
|
|
|
- flHealthRetries = cmd.Int([]string{"-health-retries"}, 0, "Consecutive failures needed to report unhealthy")
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
- cmd.Var(&flAttach, []string{"a", "-attach"}, "Attach to STDIN, STDOUT or STDERR")
|
|
|
|
- cmd.Var(&flBlkioWeightDevice, []string{"-blkio-weight-device"}, "Block IO weight (relative device weight)")
|
|
|
|
- cmd.Var(&flDeviceReadBps, []string{"-device-read-bps"}, "Limit read rate (bytes per second) from a device")
|
|
|
|
- cmd.Var(&flDeviceWriteBps, []string{"-device-write-bps"}, "Limit write rate (bytes per second) to a device")
|
|
|
|
- cmd.Var(&flDeviceReadIOps, []string{"-device-read-iops"}, "Limit read rate (IO per second) from a device")
|
|
|
|
- cmd.Var(&flDeviceWriteIOps, []string{"-device-write-iops"}, "Limit write rate (IO per second) to a device")
|
|
|
|
- cmd.Var(&flVolumes, []string{"v", "-volume"}, "Bind mount a volume")
|
|
|
|
- cmd.Var(&flTmpfs, []string{"-tmpfs"}, "Mount a tmpfs directory")
|
|
|
|
- cmd.Var(&flLinks, []string{"-link"}, "Add link to another container")
|
|
|
|
- cmd.Var(&flAliases, []string{"-net-alias"}, "Add network-scoped alias for the container")
|
|
|
|
- cmd.Var(&flDevices, []string{"-device"}, "Add a host device to the container")
|
|
|
|
- cmd.Var(&flLabels, []string{"l", "-label"}, "Set meta data on a container")
|
|
|
|
- cmd.Var(&flLabelsFile, []string{"-label-file"}, "Read in a line delimited file of labels")
|
|
|
|
- cmd.Var(&flEnv, []string{"e", "-env"}, "Set environment variables")
|
|
|
|
- cmd.Var(&flEnvFile, []string{"-env-file"}, "Read in a file of environment variables")
|
|
|
|
- cmd.Var(&flPublish, []string{"p", "-publish"}, "Publish a container's port(s) to the host")
|
|
|
|
- cmd.Var(&flExpose, []string{"-expose"}, "Expose a port or a range of ports")
|
|
|
|
- cmd.Var(&flDNS, []string{"-dns"}, "Set custom DNS servers")
|
|
|
|
- cmd.Var(&flDNSSearch, []string{"-dns-search"}, "Set custom DNS search domains")
|
|
|
|
- cmd.Var(&flDNSOptions, []string{"-dns-opt"}, "Set DNS options")
|
|
|
|
- cmd.Var(&flExtraHosts, []string{"-add-host"}, "Add a custom host-to-IP mapping (host:ip)")
|
|
|
|
- cmd.Var(&flVolumesFrom, []string{"-volumes-from"}, "Mount volumes from the specified container(s)")
|
|
|
|
- cmd.Var(&flCapAdd, []string{"-cap-add"}, "Add Linux capabilities")
|
|
|
|
- cmd.Var(&flCapDrop, []string{"-cap-drop"}, "Drop Linux capabilities")
|
|
|
|
- cmd.Var(&flGroupAdd, []string{"-group-add"}, "Add additional groups to join")
|
|
|
|
- cmd.Var(&flSecurityOpt, []string{"-security-opt"}, "Security Options")
|
|
|
|
- cmd.Var(&flStorageOpt, []string{"-storage-opt"}, "Set storage driver options per container")
|
|
|
|
- cmd.Var(flUlimits, []string{"-ulimit"}, "Ulimit options")
|
|
|
|
- cmd.Var(flSysctls, []string{"-sysctl"}, "Sysctl options")
|
|
|
|
- cmd.Var(&flLoggingOpts, []string{"-log-opt"}, "Log driver options")
|
|
|
|
-
|
|
|
|
- cmd.Require(flag.Min, 1)
|
|
|
|
-
|
|
|
|
- if err := cmd.ParseFlags(args, true); err != nil {
|
|
|
|
- return nil, nil, nil, cmd, err
|
|
|
|
- }
|
|
|
|
|
|
+func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *container.HostConfig, *networktypes.NetworkingConfig, error) {
|
|
|
|
|
|
var (
|
|
var (
|
|
- attachStdin = flAttach.Get("stdin")
|
|
|
|
- attachStdout = flAttach.Get("stdout")
|
|
|
|
- attachStderr = flAttach.Get("stderr")
|
|
|
|
|
|
+ attachStdin = copts.flAttach.Get("stdin")
|
|
|
|
+ attachStdout = copts.flAttach.Get("stdout")
|
|
|
|
+ attachStderr = copts.flAttach.Get("stderr")
|
|
)
|
|
)
|
|
|
|
|
|
// Validate the input mac address
|
|
// Validate the input mac address
|
|
- if *flMacAddress != "" {
|
|
|
|
- if _, err := ValidateMACAddress(*flMacAddress); err != nil {
|
|
|
|
- return nil, nil, nil, cmd, fmt.Errorf("%s is not a valid mac address", *flMacAddress)
|
|
|
|
|
|
+ if *copts.flMacAddress != "" {
|
|
|
|
+ if _, err := ValidateMACAddress(*copts.flMacAddress); err != nil {
|
|
|
|
+ return nil, nil, nil, fmt.Errorf("%s is not a valid mac address", *copts.flMacAddress)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- if *flStdin {
|
|
|
|
|
|
+ if *copts.flStdin {
|
|
attachStdin = true
|
|
attachStdin = true
|
|
}
|
|
}
|
|
// If -a is not set, attach to stdout and stderr
|
|
// If -a is not set, attach to stdout and stderr
|
|
- if flAttach.Len() == 0 {
|
|
|
|
|
|
+ if copts.flAttach.Len() == 0 {
|
|
attachStdout = true
|
|
attachStdout = true
|
|
attachStderr = true
|
|
attachStderr = true
|
|
}
|
|
}
|
|
@@ -169,83 +254,83 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
|
|
var err error
|
|
var err error
|
|
|
|
|
|
var flMemory int64
|
|
var flMemory int64
|
|
- if *flMemoryString != "" {
|
|
|
|
- flMemory, err = units.RAMInBytes(*flMemoryString)
|
|
|
|
|
|
+ if *copts.flMemoryString != "" {
|
|
|
|
+ flMemory, err = units.RAMInBytes(*copts.flMemoryString)
|
|
if err != nil {
|
|
if err != nil {
|
|
- return nil, nil, nil, cmd, err
|
|
|
|
|
|
+ return nil, nil, nil, err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
var MemoryReservation int64
|
|
var MemoryReservation int64
|
|
- if *flMemoryReservation != "" {
|
|
|
|
- MemoryReservation, err = units.RAMInBytes(*flMemoryReservation)
|
|
|
|
|
|
+ if *copts.flMemoryReservation != "" {
|
|
|
|
+ MemoryReservation, err = units.RAMInBytes(*copts.flMemoryReservation)
|
|
if err != nil {
|
|
if err != nil {
|
|
- return nil, nil, nil, cmd, err
|
|
|
|
|
|
+ return nil, nil, nil, err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
var memorySwap int64
|
|
var memorySwap int64
|
|
- if *flMemorySwap != "" {
|
|
|
|
- if *flMemorySwap == "-1" {
|
|
|
|
|
|
+ if *copts.flMemorySwap != "" {
|
|
|
|
+ if *copts.flMemorySwap == "-1" {
|
|
memorySwap = -1
|
|
memorySwap = -1
|
|
} else {
|
|
} else {
|
|
- memorySwap, err = units.RAMInBytes(*flMemorySwap)
|
|
|
|
|
|
+ memorySwap, err = units.RAMInBytes(*copts.flMemorySwap)
|
|
if err != nil {
|
|
if err != nil {
|
|
- return nil, nil, nil, cmd, err
|
|
|
|
|
|
+ return nil, nil, nil, err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
var KernelMemory int64
|
|
var KernelMemory int64
|
|
- if *flKernelMemory != "" {
|
|
|
|
- KernelMemory, err = units.RAMInBytes(*flKernelMemory)
|
|
|
|
|
|
+ if *copts.flKernelMemory != "" {
|
|
|
|
+ KernelMemory, err = units.RAMInBytes(*copts.flKernelMemory)
|
|
if err != nil {
|
|
if err != nil {
|
|
- return nil, nil, nil, cmd, err
|
|
|
|
|
|
+ return nil, nil, nil, err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- swappiness := *flSwappiness
|
|
|
|
|
|
+ swappiness := *copts.flSwappiness
|
|
if swappiness != -1 && (swappiness < 0 || swappiness > 100) {
|
|
if swappiness != -1 && (swappiness < 0 || swappiness > 100) {
|
|
- return nil, nil, nil, cmd, fmt.Errorf("invalid value: %d. Valid memory swappiness range is 0-100", swappiness)
|
|
|
|
|
|
+ return nil, nil, nil, fmt.Errorf("invalid value: %d. Valid memory swappiness range is 0-100", swappiness)
|
|
}
|
|
}
|
|
|
|
|
|
var shmSize int64
|
|
var shmSize int64
|
|
- if *flShmSize != "" {
|
|
|
|
- shmSize, err = units.RAMInBytes(*flShmSize)
|
|
|
|
|
|
+ if *copts.flShmSize != "" {
|
|
|
|
+ shmSize, err = units.RAMInBytes(*copts.flShmSize)
|
|
if err != nil {
|
|
if err != nil {
|
|
- return nil, nil, nil, cmd, err
|
|
|
|
|
|
+ return nil, nil, nil, err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// TODO FIXME units.RAMInBytes should have a uint64 version
|
|
// TODO FIXME units.RAMInBytes should have a uint64 version
|
|
var maxIOBandwidth int64
|
|
var maxIOBandwidth int64
|
|
- if *flIOMaxBandwidth != "" {
|
|
|
|
- maxIOBandwidth, err = units.RAMInBytes(*flIOMaxBandwidth)
|
|
|
|
|
|
+ if *copts.flIOMaxBandwidth != "" {
|
|
|
|
+ maxIOBandwidth, err = units.RAMInBytes(*copts.flIOMaxBandwidth)
|
|
if err != nil {
|
|
if err != nil {
|
|
- return nil, nil, nil, cmd, err
|
|
|
|
|
|
+ return nil, nil, nil, err
|
|
}
|
|
}
|
|
if maxIOBandwidth < 0 {
|
|
if maxIOBandwidth < 0 {
|
|
- return nil, nil, nil, cmd, fmt.Errorf("invalid value: %s. Maximum IO Bandwidth must be positive", *flIOMaxBandwidth)
|
|
|
|
|
|
+ return nil, nil, nil, fmt.Errorf("invalid value: %s. Maximum IO Bandwidth must be positive", *copts.flIOMaxBandwidth)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
var binds []string
|
|
var binds []string
|
|
// add any bind targets to the list of container volumes
|
|
// add any bind targets to the list of container volumes
|
|
- for bind := range flVolumes.GetMap() {
|
|
|
|
|
|
+ for bind := range copts.flVolumes.GetMap() {
|
|
if arr := volumeSplitN(bind, 2); len(arr) > 1 {
|
|
if arr := volumeSplitN(bind, 2); len(arr) > 1 {
|
|
- // after creating the bind mount we want to delete it from the flVolumes values because
|
|
|
|
|
|
+ // after creating the bind mount we want to delete it from the copts.flVolumes values because
|
|
// we do not want bind mounts being committed to image configs
|
|
// we do not want bind mounts being committed to image configs
|
|
binds = append(binds, bind)
|
|
binds = append(binds, bind)
|
|
- flVolumes.Delete(bind)
|
|
|
|
|
|
+ copts.flVolumes.Delete(bind)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Can't evaluate options passed into --tmpfs until we actually mount
|
|
// Can't evaluate options passed into --tmpfs until we actually mount
|
|
tmpfs := make(map[string]string)
|
|
tmpfs := make(map[string]string)
|
|
- for _, t := range flTmpfs.GetAll() {
|
|
|
|
|
|
+ for _, t := range copts.flTmpfs.GetAll() {
|
|
if arr := strings.SplitN(t, ":", 2); len(arr) > 1 {
|
|
if arr := strings.SplitN(t, ":", 2); len(arr) > 1 {
|
|
if _, _, err := mount.ParseTmpfsOptions(arr[1]); err != nil {
|
|
if _, _, err := mount.ParseTmpfsOptions(arr[1]); err != nil {
|
|
- return nil, nil, nil, cmd, err
|
|
|
|
|
|
+ return nil, nil, nil, err
|
|
}
|
|
}
|
|
tmpfs[arr[0]] = arr[1]
|
|
tmpfs[arr[0]] = arr[1]
|
|
} else {
|
|
} else {
|
|
@@ -254,27 +339,25 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
|
|
}
|
|
}
|
|
|
|
|
|
var (
|
|
var (
|
|
- parsedArgs = cmd.Args()
|
|
|
|
runCmd strslice.StrSlice
|
|
runCmd strslice.StrSlice
|
|
entrypoint strslice.StrSlice
|
|
entrypoint strslice.StrSlice
|
|
- image = cmd.Arg(0)
|
|
|
|
)
|
|
)
|
|
- if len(parsedArgs) > 1 {
|
|
|
|
- runCmd = strslice.StrSlice(parsedArgs[1:])
|
|
|
|
|
|
+ if len(copts.Args) > 0 {
|
|
|
|
+ runCmd = strslice.StrSlice(copts.Args)
|
|
}
|
|
}
|
|
- if *flEntrypoint != "" {
|
|
|
|
- entrypoint = strslice.StrSlice{*flEntrypoint}
|
|
|
|
|
|
+ if *copts.flEntrypoint != "" {
|
|
|
|
+ entrypoint = strslice.StrSlice{*copts.flEntrypoint}
|
|
}
|
|
}
|
|
|
|
|
|
- ports, portBindings, err := nat.ParsePortSpecs(flPublish.GetAll())
|
|
|
|
|
|
+ ports, portBindings, err := nat.ParsePortSpecs(copts.flPublish.GetAll())
|
|
if err != nil {
|
|
if err != nil {
|
|
- return nil, nil, nil, cmd, err
|
|
|
|
|
|
+ return nil, nil, nil, err
|
|
}
|
|
}
|
|
|
|
|
|
// Merge in exposed ports to the map of published ports
|
|
// Merge in exposed ports to the map of published ports
|
|
- for _, e := range flExpose.GetAll() {
|
|
|
|
|
|
+ for _, e := range copts.flExpose.GetAll() {
|
|
if strings.Contains(e, ":") {
|
|
if strings.Contains(e, ":") {
|
|
- return nil, nil, nil, cmd, fmt.Errorf("invalid port format for --expose: %s", e)
|
|
|
|
|
|
+ return nil, nil, nil, fmt.Errorf("invalid port format for --expose: %s", e)
|
|
}
|
|
}
|
|
//support two formats for expose, original format <portnum>/[<proto>] or <startport-endport>/[<proto>]
|
|
//support two formats for expose, original format <portnum>/[<proto>] or <startport-endport>/[<proto>]
|
|
proto, port := nat.SplitProtoPort(e)
|
|
proto, port := nat.SplitProtoPort(e)
|
|
@@ -282,12 +365,12 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
|
|
//if expose a port, the start and end port are the same
|
|
//if expose a port, the start and end port are the same
|
|
start, end, err := nat.ParsePortRange(port)
|
|
start, end, err := nat.ParsePortRange(port)
|
|
if err != nil {
|
|
if err != nil {
|
|
- return nil, nil, nil, cmd, fmt.Errorf("invalid range format for --expose: %s, error: %s", e, err)
|
|
|
|
|
|
+ return nil, nil, nil, fmt.Errorf("invalid range format for --expose: %s, error: %s", e, err)
|
|
}
|
|
}
|
|
for i := start; i <= end; i++ {
|
|
for i := start; i <= end; i++ {
|
|
p, err := nat.NewPort(proto, strconv.FormatUint(i, 10))
|
|
p, err := nat.NewPort(proto, strconv.FormatUint(i, 10))
|
|
if err != nil {
|
|
if err != nil {
|
|
- return nil, nil, nil, cmd, err
|
|
|
|
|
|
+ return nil, nil, nil, err
|
|
}
|
|
}
|
|
if _, exists := ports[p]; !exists {
|
|
if _, exists := ports[p]; !exists {
|
|
ports[p] = struct{}{}
|
|
ports[p] = struct{}{}
|
|
@@ -297,64 +380,64 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
|
|
|
|
|
|
// parse device mappings
|
|
// parse device mappings
|
|
deviceMappings := []container.DeviceMapping{}
|
|
deviceMappings := []container.DeviceMapping{}
|
|
- for _, device := range flDevices.GetAll() {
|
|
|
|
|
|
+ for _, device := range copts.flDevices.GetAll() {
|
|
deviceMapping, err := ParseDevice(device)
|
|
deviceMapping, err := ParseDevice(device)
|
|
if err != nil {
|
|
if err != nil {
|
|
- return nil, nil, nil, cmd, err
|
|
|
|
|
|
+ return nil, nil, nil, err
|
|
}
|
|
}
|
|
deviceMappings = append(deviceMappings, deviceMapping)
|
|
deviceMappings = append(deviceMappings, deviceMapping)
|
|
}
|
|
}
|
|
|
|
|
|
// collect all the environment variables for the container
|
|
// collect all the environment variables for the container
|
|
- envVariables, err := readKVStrings(flEnvFile.GetAll(), flEnv.GetAll())
|
|
|
|
|
|
+ envVariables, err := readKVStrings(copts.flEnvFile.GetAll(), copts.flEnv.GetAll())
|
|
if err != nil {
|
|
if err != nil {
|
|
- return nil, nil, nil, cmd, err
|
|
|
|
|
|
+ return nil, nil, nil, err
|
|
}
|
|
}
|
|
|
|
|
|
// collect all the labels for the container
|
|
// collect all the labels for the container
|
|
- labels, err := readKVStrings(flLabelsFile.GetAll(), flLabels.GetAll())
|
|
|
|
|
|
+ labels, err := readKVStrings(copts.flLabelsFile.GetAll(), copts.flLabels.GetAll())
|
|
if err != nil {
|
|
if err != nil {
|
|
- return nil, nil, nil, cmd, err
|
|
|
|
|
|
+ return nil, nil, nil, err
|
|
}
|
|
}
|
|
|
|
|
|
- ipcMode := container.IpcMode(*flIpcMode)
|
|
|
|
|
|
+ ipcMode := container.IpcMode(*copts.flIpcMode)
|
|
if !ipcMode.Valid() {
|
|
if !ipcMode.Valid() {
|
|
- return nil, nil, nil, cmd, fmt.Errorf("--ipc: invalid IPC mode")
|
|
|
|
|
|
+ return nil, nil, nil, fmt.Errorf("--ipc: invalid IPC mode")
|
|
}
|
|
}
|
|
|
|
|
|
- pidMode := container.PidMode(*flPidMode)
|
|
|
|
|
|
+ pidMode := container.PidMode(*copts.flPidMode)
|
|
if !pidMode.Valid() {
|
|
if !pidMode.Valid() {
|
|
- return nil, nil, nil, cmd, fmt.Errorf("--pid: invalid PID mode")
|
|
|
|
|
|
+ return nil, nil, nil, fmt.Errorf("--pid: invalid PID mode")
|
|
}
|
|
}
|
|
|
|
|
|
- utsMode := container.UTSMode(*flUTSMode)
|
|
|
|
|
|
+ utsMode := container.UTSMode(*copts.flUTSMode)
|
|
if !utsMode.Valid() {
|
|
if !utsMode.Valid() {
|
|
- return nil, nil, nil, cmd, fmt.Errorf("--uts: invalid UTS mode")
|
|
|
|
|
|
+ return nil, nil, nil, fmt.Errorf("--uts: invalid UTS mode")
|
|
}
|
|
}
|
|
|
|
|
|
- usernsMode := container.UsernsMode(*flUsernsMode)
|
|
|
|
|
|
+ usernsMode := container.UsernsMode(*copts.flUsernsMode)
|
|
if !usernsMode.Valid() {
|
|
if !usernsMode.Valid() {
|
|
- return nil, nil, nil, cmd, fmt.Errorf("--userns: invalid USER mode")
|
|
|
|
|
|
+ return nil, nil, nil, fmt.Errorf("--userns: invalid USER mode")
|
|
}
|
|
}
|
|
|
|
|
|
- restartPolicy, err := ParseRestartPolicy(*flRestartPolicy)
|
|
|
|
|
|
+ restartPolicy, err := ParseRestartPolicy(*copts.flRestartPolicy)
|
|
if err != nil {
|
|
if err != nil {
|
|
- return nil, nil, nil, cmd, err
|
|
|
|
|
|
+ return nil, nil, nil, err
|
|
}
|
|
}
|
|
|
|
|
|
- loggingOpts, err := parseLoggingOpts(*flLoggingDriver, flLoggingOpts.GetAll())
|
|
|
|
|
|
+ loggingOpts, err := parseLoggingOpts(*copts.flLoggingDriver, copts.flLoggingOpts.GetAll())
|
|
if err != nil {
|
|
if err != nil {
|
|
- return nil, nil, nil, cmd, err
|
|
|
|
|
|
+ return nil, nil, nil, err
|
|
}
|
|
}
|
|
|
|
|
|
- securityOpts, err := parseSecurityOpts(flSecurityOpt.GetAll())
|
|
|
|
|
|
+ securityOpts, err := parseSecurityOpts(copts.flSecurityOpt.GetAll())
|
|
if err != nil {
|
|
if err != nil {
|
|
- return nil, nil, nil, cmd, err
|
|
|
|
|
|
+ return nil, nil, nil, err
|
|
}
|
|
}
|
|
|
|
|
|
- storageOpts, err := parseStorageOpts(flStorageOpt.GetAll())
|
|
|
|
|
|
+ storageOpts, err := parseStorageOpts(copts.flStorageOpt.GetAll())
|
|
if err != nil {
|
|
if err != nil {
|
|
- return nil, nil, nil, cmd, err
|
|
|
|
|
|
+ return nil, nil, nil, err
|
|
}
|
|
}
|
|
|
|
|
|
// Healthcheck
|
|
// Healthcheck
|
|
@@ -391,96 +474,96 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
|
|
}
|
|
}
|
|
|
|
|
|
resources := container.Resources{
|
|
resources := container.Resources{
|
|
- CgroupParent: *flCgroupParent,
|
|
|
|
|
|
+ CgroupParent: *copts.flCgroupParent,
|
|
Memory: flMemory,
|
|
Memory: flMemory,
|
|
MemoryReservation: MemoryReservation,
|
|
MemoryReservation: MemoryReservation,
|
|
MemorySwap: memorySwap,
|
|
MemorySwap: memorySwap,
|
|
- MemorySwappiness: flSwappiness,
|
|
|
|
|
|
+ MemorySwappiness: copts.flSwappiness,
|
|
KernelMemory: KernelMemory,
|
|
KernelMemory: KernelMemory,
|
|
- OomKillDisable: flOomKillDisable,
|
|
|
|
- CPUPercent: *flCPUPercent,
|
|
|
|
- CPUShares: *flCPUShares,
|
|
|
|
- CPUPeriod: *flCPUPeriod,
|
|
|
|
- CpusetCpus: *flCpusetCpus,
|
|
|
|
- CpusetMems: *flCpusetMems,
|
|
|
|
- CPUQuota: *flCPUQuota,
|
|
|
|
- PidsLimit: *flPidsLimit,
|
|
|
|
- BlkioWeight: *flBlkioWeight,
|
|
|
|
- BlkioWeightDevice: flBlkioWeightDevice.GetList(),
|
|
|
|
- BlkioDeviceReadBps: flDeviceReadBps.GetList(),
|
|
|
|
- BlkioDeviceWriteBps: flDeviceWriteBps.GetList(),
|
|
|
|
- BlkioDeviceReadIOps: flDeviceReadIOps.GetList(),
|
|
|
|
- BlkioDeviceWriteIOps: flDeviceWriteIOps.GetList(),
|
|
|
|
- IOMaximumIOps: *flIOMaxIOps,
|
|
|
|
|
|
+ OomKillDisable: copts.flOomKillDisable,
|
|
|
|
+ CPUPercent: *copts.flCPUPercent,
|
|
|
|
+ CPUShares: *copts.flCPUShares,
|
|
|
|
+ CPUPeriod: *copts.flCPUPeriod,
|
|
|
|
+ CpusetCpus: *copts.flCpusetCpus,
|
|
|
|
+ CpusetMems: *copts.flCpusetMems,
|
|
|
|
+ CPUQuota: *copts.flCPUQuota,
|
|
|
|
+ PidsLimit: *copts.flPidsLimit,
|
|
|
|
+ BlkioWeight: *copts.flBlkioWeight,
|
|
|
|
+ BlkioWeightDevice: copts.flBlkioWeightDevice.GetList(),
|
|
|
|
+ BlkioDeviceReadBps: copts.flDeviceReadBps.GetList(),
|
|
|
|
+ BlkioDeviceWriteBps: copts.flDeviceWriteBps.GetList(),
|
|
|
|
+ BlkioDeviceReadIOps: copts.flDeviceReadIOps.GetList(),
|
|
|
|
+ BlkioDeviceWriteIOps: copts.flDeviceWriteIOps.GetList(),
|
|
|
|
+ IOMaximumIOps: *copts.flIOMaxIOps,
|
|
IOMaximumBandwidth: uint64(maxIOBandwidth),
|
|
IOMaximumBandwidth: uint64(maxIOBandwidth),
|
|
- Ulimits: flUlimits.GetList(),
|
|
|
|
|
|
+ Ulimits: copts.flUlimits.GetList(),
|
|
Devices: deviceMappings,
|
|
Devices: deviceMappings,
|
|
}
|
|
}
|
|
|
|
|
|
config := &container.Config{
|
|
config := &container.Config{
|
|
- Hostname: *flHostname,
|
|
|
|
|
|
+ Hostname: *copts.flHostname,
|
|
ExposedPorts: ports,
|
|
ExposedPorts: ports,
|
|
- User: *flUser,
|
|
|
|
- Tty: *flTty,
|
|
|
|
|
|
+ User: *copts.flUser,
|
|
|
|
+ Tty: *copts.flTty,
|
|
// TODO: deprecated, it comes from -n, --networking
|
|
// TODO: deprecated, it comes from -n, --networking
|
|
// it's still needed internally to set the network to disabled
|
|
// it's still needed internally to set the network to disabled
|
|
// if e.g. bridge is none in daemon opts, and in inspect
|
|
// if e.g. bridge is none in daemon opts, and in inspect
|
|
NetworkDisabled: false,
|
|
NetworkDisabled: false,
|
|
- OpenStdin: *flStdin,
|
|
|
|
|
|
+ OpenStdin: *copts.flStdin,
|
|
AttachStdin: attachStdin,
|
|
AttachStdin: attachStdin,
|
|
AttachStdout: attachStdout,
|
|
AttachStdout: attachStdout,
|
|
AttachStderr: attachStderr,
|
|
AttachStderr: attachStderr,
|
|
Env: envVariables,
|
|
Env: envVariables,
|
|
Cmd: runCmd,
|
|
Cmd: runCmd,
|
|
- Image: image,
|
|
|
|
- Volumes: flVolumes.GetMap(),
|
|
|
|
- MacAddress: *flMacAddress,
|
|
|
|
|
|
+ Image: copts.Image,
|
|
|
|
+ Volumes: copts.flVolumes.GetMap(),
|
|
|
|
+ MacAddress: *copts.flMacAddress,
|
|
Entrypoint: entrypoint,
|
|
Entrypoint: entrypoint,
|
|
- WorkingDir: *flWorkingDir,
|
|
|
|
|
|
+ WorkingDir: *copts.flWorkingDir,
|
|
Labels: ConvertKVStringsToMap(labels),
|
|
Labels: ConvertKVStringsToMap(labels),
|
|
Healthcheck: healthConfig,
|
|
Healthcheck: healthConfig,
|
|
}
|
|
}
|
|
- if cmd.IsSet("-stop-signal") {
|
|
|
|
- config.StopSignal = *flStopSignal
|
|
|
|
|
|
+ if flags.Changed("stop-signal") {
|
|
|
|
+ config.StopSignal = *copts.flStopSignal
|
|
}
|
|
}
|
|
|
|
|
|
hostConfig := &container.HostConfig{
|
|
hostConfig := &container.HostConfig{
|
|
Binds: binds,
|
|
Binds: binds,
|
|
- ContainerIDFile: *flContainerIDFile,
|
|
|
|
- OomScoreAdj: *flOomScoreAdj,
|
|
|
|
- Privileged: *flPrivileged,
|
|
|
|
|
|
+ ContainerIDFile: *copts.flContainerIDFile,
|
|
|
|
+ OomScoreAdj: *copts.flOomScoreAdj,
|
|
|
|
+ Privileged: *copts.flPrivileged,
|
|
PortBindings: portBindings,
|
|
PortBindings: portBindings,
|
|
- Links: flLinks.GetAll(),
|
|
|
|
- PublishAllPorts: *flPublishAll,
|
|
|
|
|
|
+ Links: copts.flLinks.GetAll(),
|
|
|
|
+ PublishAllPorts: *copts.flPublishAll,
|
|
// Make sure the dns fields are never nil.
|
|
// Make sure the dns fields are never nil.
|
|
// New containers don't ever have those fields nil,
|
|
// New containers don't ever have those fields nil,
|
|
// but pre created containers can still have those nil values.
|
|
// but pre created containers can still have those nil values.
|
|
// See https://github.com/docker/docker/pull/17779
|
|
// See https://github.com/docker/docker/pull/17779
|
|
// for a more detailed explanation on why we don't want that.
|
|
// for a more detailed explanation on why we don't want that.
|
|
- DNS: flDNS.GetAllOrEmpty(),
|
|
|
|
- DNSSearch: flDNSSearch.GetAllOrEmpty(),
|
|
|
|
- DNSOptions: flDNSOptions.GetAllOrEmpty(),
|
|
|
|
- ExtraHosts: flExtraHosts.GetAll(),
|
|
|
|
- VolumesFrom: flVolumesFrom.GetAll(),
|
|
|
|
- NetworkMode: container.NetworkMode(*flNetMode),
|
|
|
|
|
|
+ DNS: copts.flDNS.GetAllOrEmpty(),
|
|
|
|
+ DNSSearch: copts.flDNSSearch.GetAllOrEmpty(),
|
|
|
|
+ DNSOptions: copts.flDNSOptions.GetAllOrEmpty(),
|
|
|
|
+ ExtraHosts: copts.flExtraHosts.GetAll(),
|
|
|
|
+ VolumesFrom: copts.flVolumesFrom.GetAll(),
|
|
|
|
+ NetworkMode: container.NetworkMode(*copts.flNetMode),
|
|
IpcMode: ipcMode,
|
|
IpcMode: ipcMode,
|
|
PidMode: pidMode,
|
|
PidMode: pidMode,
|
|
UTSMode: utsMode,
|
|
UTSMode: utsMode,
|
|
UsernsMode: usernsMode,
|
|
UsernsMode: usernsMode,
|
|
- CapAdd: strslice.StrSlice(flCapAdd.GetAll()),
|
|
|
|
- CapDrop: strslice.StrSlice(flCapDrop.GetAll()),
|
|
|
|
- GroupAdd: flGroupAdd.GetAll(),
|
|
|
|
|
|
+ CapAdd: strslice.StrSlice(copts.flCapAdd.GetAll()),
|
|
|
|
+ CapDrop: strslice.StrSlice(copts.flCapDrop.GetAll()),
|
|
|
|
+ GroupAdd: copts.flGroupAdd.GetAll(),
|
|
RestartPolicy: restartPolicy,
|
|
RestartPolicy: restartPolicy,
|
|
SecurityOpt: securityOpts,
|
|
SecurityOpt: securityOpts,
|
|
StorageOpt: storageOpts,
|
|
StorageOpt: storageOpts,
|
|
- ReadonlyRootfs: *flReadonlyRootfs,
|
|
|
|
- LogConfig: container.LogConfig{Type: *flLoggingDriver, Config: loggingOpts},
|
|
|
|
- VolumeDriver: *flVolumeDriver,
|
|
|
|
- Isolation: container.Isolation(*flIsolation),
|
|
|
|
|
|
+ ReadonlyRootfs: *copts.flReadonlyRootfs,
|
|
|
|
+ LogConfig: container.LogConfig{Type: *copts.flLoggingDriver, Config: loggingOpts},
|
|
|
|
+ VolumeDriver: *copts.flVolumeDriver,
|
|
|
|
+ Isolation: container.Isolation(*copts.flIsolation),
|
|
ShmSize: shmSize,
|
|
ShmSize: shmSize,
|
|
Resources: resources,
|
|
Resources: resources,
|
|
Tmpfs: tmpfs,
|
|
Tmpfs: tmpfs,
|
|
- Sysctls: flSysctls.GetAll(),
|
|
|
|
|
|
+ Sysctls: copts.flSysctls.GetAll(),
|
|
}
|
|
}
|
|
|
|
|
|
// When allocating stdin in attached mode, close stdin at client disconnect
|
|
// When allocating stdin in attached mode, close stdin at client disconnect
|
|
@@ -492,11 +575,11 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
|
|
EndpointsConfig: make(map[string]*networktypes.EndpointSettings),
|
|
EndpointsConfig: make(map[string]*networktypes.EndpointSettings),
|
|
}
|
|
}
|
|
|
|
|
|
- if *flIPv4Address != "" || *flIPv6Address != "" {
|
|
|
|
|
|
+ if *copts.flIPv4Address != "" || *copts.flIPv6Address != "" {
|
|
networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = &networktypes.EndpointSettings{
|
|
networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = &networktypes.EndpointSettings{
|
|
IPAMConfig: &networktypes.EndpointIPAMConfig{
|
|
IPAMConfig: &networktypes.EndpointIPAMConfig{
|
|
- IPv4Address: *flIPv4Address,
|
|
|
|
- IPv6Address: *flIPv6Address,
|
|
|
|
|
|
+ IPv4Address: *copts.flIPv4Address,
|
|
|
|
+ IPv6Address: *copts.flIPv6Address,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -511,17 +594,17 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
|
|
networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = epConfig
|
|
networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = epConfig
|
|
}
|
|
}
|
|
|
|
|
|
- if flAliases.Len() > 0 {
|
|
|
|
|
|
+ if copts.flAliases.Len() > 0 {
|
|
epConfig := networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)]
|
|
epConfig := networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)]
|
|
if epConfig == nil {
|
|
if epConfig == nil {
|
|
epConfig = &networktypes.EndpointSettings{}
|
|
epConfig = &networktypes.EndpointSettings{}
|
|
}
|
|
}
|
|
- epConfig.Aliases = make([]string, flAliases.Len())
|
|
|
|
- copy(epConfig.Aliases, flAliases.GetAll())
|
|
|
|
|
|
+ epConfig.Aliases = make([]string, copts.flAliases.Len())
|
|
|
|
+ copy(epConfig.Aliases, copts.flAliases.GetAll())
|
|
networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = epConfig
|
|
networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = epConfig
|
|
}
|
|
}
|
|
|
|
|
|
- return config, hostConfig, networkingConfig, cmd, nil
|
|
|
|
|
|
+ return config, hostConfig, networkingConfig, nil
|
|
}
|
|
}
|
|
|
|
|
|
// reads a file of line terminated key=value pairs, and overrides any keys
|
|
// reads a file of line terminated key=value pairs, and overrides any keys
|