mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Validate hostname starting from 1.24 API.
In order to keep a little bit of "sanity" on the API side, validate hostname only starting from v1.24 API version. Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
parent
ad44f49470
commit
6daf3d2a78
13 changed files with 44 additions and 32 deletions
|
@ -32,17 +32,17 @@ type copyBackend interface {
|
||||||
|
|
||||||
// stateBackend includes functions to implement to provide container state lifecycle functionality.
|
// stateBackend includes functions to implement to provide container state lifecycle functionality.
|
||||||
type stateBackend interface {
|
type stateBackend interface {
|
||||||
ContainerCreate(types.ContainerCreateConfig) (types.ContainerCreateResponse, error)
|
ContainerCreate(config types.ContainerCreateConfig, validateHostname bool) (types.ContainerCreateResponse, error)
|
||||||
ContainerKill(name string, sig uint64) error
|
ContainerKill(name string, sig uint64) error
|
||||||
ContainerPause(name string) error
|
ContainerPause(name string) error
|
||||||
ContainerRename(oldName, newName string) error
|
ContainerRename(oldName, newName string) error
|
||||||
ContainerResize(name string, height, width int) error
|
ContainerResize(name string, height, width int) error
|
||||||
ContainerRestart(name string, seconds int) error
|
ContainerRestart(name string, seconds int) error
|
||||||
ContainerRm(name string, config *types.ContainerRmConfig) error
|
ContainerRm(name string, config *types.ContainerRmConfig) error
|
||||||
ContainerStart(name string, hostConfig *container.HostConfig) error
|
ContainerStart(name string, hostConfig *container.HostConfig, validateHostname bool) error
|
||||||
ContainerStop(name string, seconds int) error
|
ContainerStop(name string, seconds int) error
|
||||||
ContainerUnpause(name string) error
|
ContainerUnpause(name string) error
|
||||||
ContainerUpdate(name string, hostConfig *container.HostConfig) ([]string, error)
|
ContainerUpdate(name string, hostConfig *container.HostConfig, validateHostname bool) ([]string, error)
|
||||||
ContainerWait(name string, timeout time.Duration) (int, error)
|
ContainerWait(name string, timeout time.Duration) (int, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,10 +132,10 @@ func (s *containerRouter) postContainersStart(ctx context.Context, w http.Respon
|
||||||
// including r.TransferEncoding
|
// including r.TransferEncoding
|
||||||
// allow a nil body for backwards compatibility
|
// allow a nil body for backwards compatibility
|
||||||
|
|
||||||
|
version := httputils.VersionFromContext(ctx)
|
||||||
var hostConfig *container.HostConfig
|
var hostConfig *container.HostConfig
|
||||||
// A non-nil json object is at least 7 characters.
|
// A non-nil json object is at least 7 characters.
|
||||||
if r.ContentLength > 7 || r.ContentLength == -1 {
|
if r.ContentLength > 7 || r.ContentLength == -1 {
|
||||||
version := httputils.VersionFromContext(ctx)
|
|
||||||
if versions.GreaterThanOrEqualTo(version, "1.24") {
|
if versions.GreaterThanOrEqualTo(version, "1.24") {
|
||||||
return validationError{fmt.Errorf("starting container with HostConfig was deprecated since v1.10 and removed in v1.12")}
|
return validationError{fmt.Errorf("starting container with HostConfig was deprecated since v1.10 and removed in v1.12")}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,8 @@ func (s *containerRouter) postContainersStart(ctx context.Context, w http.Respon
|
||||||
hostConfig = c
|
hostConfig = c
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.backend.ContainerStart(vars["name"], hostConfig); err != nil {
|
validateHostname := versions.GreaterThanOrEqualTo(version, "1.24")
|
||||||
|
if err := s.backend.ContainerStart(vars["name"], hostConfig, validateHostname); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
@ -311,6 +312,7 @@ func (s *containerRouter) postContainerUpdate(ctx context.Context, w http.Respon
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version := httputils.VersionFromContext(ctx)
|
||||||
var updateConfig container.UpdateConfig
|
var updateConfig container.UpdateConfig
|
||||||
|
|
||||||
decoder := json.NewDecoder(r.Body)
|
decoder := json.NewDecoder(r.Body)
|
||||||
|
@ -324,7 +326,8 @@ func (s *containerRouter) postContainerUpdate(ctx context.Context, w http.Respon
|
||||||
}
|
}
|
||||||
|
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
warnings, err := s.backend.ContainerUpdate(name, hostConfig)
|
validateHostname := versions.GreaterThanOrEqualTo(version, "1.24")
|
||||||
|
warnings, err := s.backend.ContainerUpdate(name, hostConfig, validateHostname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -351,13 +354,14 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
|
||||||
version := httputils.VersionFromContext(ctx)
|
version := httputils.VersionFromContext(ctx)
|
||||||
adjustCPUShares := versions.LessThan(version, "1.19")
|
adjustCPUShares := versions.LessThan(version, "1.19")
|
||||||
|
|
||||||
|
validateHostname := versions.GreaterThanOrEqualTo(version, "1.24")
|
||||||
ccr, err := s.backend.ContainerCreate(types.ContainerCreateConfig{
|
ccr, err := s.backend.ContainerCreate(types.ContainerCreateConfig{
|
||||||
Name: name,
|
Name: name,
|
||||||
Config: config,
|
Config: config,
|
||||||
HostConfig: hostConfig,
|
HostConfig: hostConfig,
|
||||||
NetworkingConfig: networkingConfig,
|
NetworkingConfig: networkingConfig,
|
||||||
AdjustCPUShares: adjustCPUShares,
|
AdjustCPUShares: adjustCPUShares,
|
||||||
})
|
}, validateHostname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,7 +116,7 @@ type Backend interface {
|
||||||
// ContainerAttachRaw attaches to container.
|
// ContainerAttachRaw attaches to container.
|
||||||
ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool) error
|
ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool) error
|
||||||
// ContainerCreate creates a new Docker container and returns potential warnings
|
// ContainerCreate creates a new Docker container and returns potential warnings
|
||||||
ContainerCreate(types.ContainerCreateConfig) (types.ContainerCreateResponse, error)
|
ContainerCreate(config types.ContainerCreateConfig, validateHostname bool) (types.ContainerCreateResponse, error)
|
||||||
// ContainerRm removes a container specified by `id`.
|
// ContainerRm removes a container specified by `id`.
|
||||||
ContainerRm(name string, config *types.ContainerRmConfig) error
|
ContainerRm(name string, config *types.ContainerRmConfig) error
|
||||||
// Commit creates a new Docker image from an existing Docker container.
|
// Commit creates a new Docker image from an existing Docker container.
|
||||||
|
@ -124,7 +124,7 @@ type Backend interface {
|
||||||
// ContainerKill stops the container execution abruptly.
|
// ContainerKill stops the container execution abruptly.
|
||||||
ContainerKill(containerID string, sig uint64) error
|
ContainerKill(containerID string, sig uint64) error
|
||||||
// ContainerStart starts a new container
|
// ContainerStart starts a new container
|
||||||
ContainerStart(containerID string, hostConfig *container.HostConfig) error
|
ContainerStart(containerID string, hostConfig *container.HostConfig, validateHostname bool) error
|
||||||
// ContainerWait stops processing until the given container is stopped.
|
// ContainerWait stops processing until the given container is stopped.
|
||||||
ContainerWait(containerID string, timeout time.Duration) (int, error)
|
ContainerWait(containerID string, timeout time.Duration) (int, error)
|
||||||
// ContainerUpdateCmdOnBuild updates container.Path and container.Args
|
// ContainerUpdateCmdOnBuild updates container.Path and container.Args
|
||||||
|
|
|
@ -181,7 +181,7 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowLocalD
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
container, err := b.docker.ContainerCreate(types.ContainerCreateConfig{Config: b.runConfig})
|
container, err := b.docker.ContainerCreate(types.ContainerCreateConfig{Config: b.runConfig}, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -508,7 +508,7 @@ func (b *Builder) create() (string, error) {
|
||||||
c, err := b.docker.ContainerCreate(types.ContainerCreateConfig{
|
c, err := b.docker.ContainerCreate(types.ContainerCreateConfig{
|
||||||
Config: b.runConfig,
|
Config: b.runConfig,
|
||||||
HostConfig: hostConfig,
|
HostConfig: hostConfig,
|
||||||
})
|
}, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -552,7 +552,7 @@ func (b *Builder) run(cID string) (err error) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err := b.docker.ContainerStart(cID, nil); err != nil {
|
if err := b.docker.ContainerStart(cID, nil, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@ type Backend interface {
|
||||||
DeleteManagedNetwork(name string) error
|
DeleteManagedNetwork(name string) error
|
||||||
SetupIngress(req clustertypes.NetworkCreateRequest, nodeIP string) error
|
SetupIngress(req clustertypes.NetworkCreateRequest, nodeIP string) error
|
||||||
PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
|
PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
|
||||||
CreateManagedContainer(types.ContainerCreateConfig) (types.ContainerCreateResponse, error)
|
CreateManagedContainer(config types.ContainerCreateConfig, validateHostname bool) (types.ContainerCreateResponse, error)
|
||||||
ContainerStart(name string, hostConfig *container.HostConfig) error
|
ContainerStart(name string, hostConfig *container.HostConfig, validateHostname bool) error
|
||||||
ContainerStop(name string, seconds int) error
|
ContainerStop(name string, seconds int) error
|
||||||
ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
|
ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
|
||||||
UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error
|
UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error
|
||||||
|
|
|
@ -9,8 +9,10 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
|
"github.com/docker/docker/api/server/httputils"
|
||||||
executorpkg "github.com/docker/docker/daemon/cluster/executor"
|
executorpkg "github.com/docker/docker/daemon/cluster/executor"
|
||||||
"github.com/docker/engine-api/types"
|
"github.com/docker/engine-api/types"
|
||||||
|
"github.com/docker/engine-api/types/versions"
|
||||||
"github.com/docker/libnetwork"
|
"github.com/docker/libnetwork"
|
||||||
"github.com/docker/swarmkit/api"
|
"github.com/docker/swarmkit/api"
|
||||||
"github.com/docker/swarmkit/log"
|
"github.com/docker/swarmkit/log"
|
||||||
|
@ -115,13 +117,16 @@ func (c *containerAdapter) removeNetworks(ctx context.Context) error {
|
||||||
func (c *containerAdapter) create(ctx context.Context, backend executorpkg.Backend) error {
|
func (c *containerAdapter) create(ctx context.Context, backend executorpkg.Backend) error {
|
||||||
var cr types.ContainerCreateResponse
|
var cr types.ContainerCreateResponse
|
||||||
var err error
|
var err error
|
||||||
|
version := httputils.VersionFromContext(ctx)
|
||||||
|
validateHostname := versions.GreaterThanOrEqualTo(version, "1.24")
|
||||||
|
|
||||||
if cr, err = backend.CreateManagedContainer(types.ContainerCreateConfig{
|
if cr, err = backend.CreateManagedContainer(types.ContainerCreateConfig{
|
||||||
Name: c.container.name(),
|
Name: c.container.name(),
|
||||||
Config: c.container.config(),
|
Config: c.container.config(),
|
||||||
HostConfig: c.container.hostConfig(),
|
HostConfig: c.container.hostConfig(),
|
||||||
// Use the first network in container create
|
// Use the first network in container create
|
||||||
NetworkingConfig: c.container.createNetworkingConfig(),
|
NetworkingConfig: c.container.createNetworkingConfig(),
|
||||||
}); err != nil {
|
}, validateHostname); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +150,9 @@ func (c *containerAdapter) create(ctx context.Context, backend executorpkg.Backe
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *containerAdapter) start(ctx context.Context) error {
|
func (c *containerAdapter) start(ctx context.Context) error {
|
||||||
return c.backend.ContainerStart(c.container.name(), nil)
|
version := httputils.VersionFromContext(ctx)
|
||||||
|
validateHostname := versions.GreaterThanOrEqualTo(version, "1.24")
|
||||||
|
return c.backend.ContainerStart(c.container.name(), nil, validateHostname)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *containerAdapter) inspect(ctx context.Context) (types.ContainerJSON, error) {
|
func (c *containerAdapter) inspect(ctx context.Context) (types.ContainerJSON, error) {
|
||||||
|
|
|
@ -203,7 +203,7 @@ func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *
|
||||||
|
|
||||||
// verifyContainerSettings performs validation of the hostconfig and config
|
// verifyContainerSettings performs validation of the hostconfig and config
|
||||||
// structures.
|
// structures.
|
||||||
func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
|
func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool, validateHostname bool) ([]string, error) {
|
||||||
|
|
||||||
// First perform verification of settings common across all platforms.
|
// First perform verification of settings common across all platforms.
|
||||||
if config != nil {
|
if config != nil {
|
||||||
|
@ -222,10 +222,10 @@ func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostCon
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate if the given hostname is RFC 1123 (https://tools.ietf.org/html/rfc1123) compliant.
|
// Validate if the given hostname is RFC 1123 (https://tools.ietf.org/html/rfc1123) compliant.
|
||||||
if len(config.Hostname) > 0 {
|
if validateHostname && len(config.Hostname) > 0 {
|
||||||
// RFC1123 specifies that 63 bytes is the maximium length
|
// RFC1123 specifies that 63 bytes is the maximium length
|
||||||
// Windows has the limitation of 63 bytes in length
|
// Windows has the limitation of 63 bytes in length
|
||||||
// Linux hostname is limited to HOST_NAME_MAX=64, not not including the terminating null byte.
|
// Linux hostname is limited to HOST_NAME_MAX=64, not including the terminating null byte.
|
||||||
// We limit the length to 63 bytes here to match RFC1035 and RFC1123.
|
// We limit the length to 63 bytes here to match RFC1035 and RFC1123.
|
||||||
matched, _ := regexp.MatchString("^(([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])\\.)*([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])$", config.Hostname)
|
matched, _ := regexp.MatchString("^(([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])\\.)*([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])$", config.Hostname)
|
||||||
if len(config.Hostname) > 63 || !matched {
|
if len(config.Hostname) > 63 || !matched {
|
||||||
|
|
|
@ -20,21 +20,21 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateManagedContainer creates a container that is managed by a Service
|
// CreateManagedContainer creates a container that is managed by a Service
|
||||||
func (daemon *Daemon) CreateManagedContainer(params types.ContainerCreateConfig) (types.ContainerCreateResponse, error) {
|
func (daemon *Daemon) CreateManagedContainer(params types.ContainerCreateConfig, validateHostname bool) (types.ContainerCreateResponse, error) {
|
||||||
return daemon.containerCreate(params, true)
|
return daemon.containerCreate(params, true, validateHostname)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerCreate creates a regular container
|
// ContainerCreate creates a regular container
|
||||||
func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig) (types.ContainerCreateResponse, error) {
|
func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig, validateHostname bool) (types.ContainerCreateResponse, error) {
|
||||||
return daemon.containerCreate(params, false)
|
return daemon.containerCreate(params, false, validateHostname)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (daemon *Daemon) containerCreate(params types.ContainerCreateConfig, managed bool) (types.ContainerCreateResponse, error) {
|
func (daemon *Daemon) containerCreate(params types.ContainerCreateConfig, managed bool, validateHostname bool) (types.ContainerCreateResponse, error) {
|
||||||
if params.Config == nil {
|
if params.Config == nil {
|
||||||
return types.ContainerCreateResponse{}, fmt.Errorf("Config cannot be empty in order to create a container")
|
return types.ContainerCreateResponse{}, fmt.Errorf("Config cannot be empty in order to create a container")
|
||||||
}
|
}
|
||||||
|
|
||||||
warnings, err := daemon.verifyContainerSettings(params.HostConfig, params.Config, false)
|
warnings, err := daemon.verifyContainerSettings(params.HostConfig, params.Config, false, validateHostname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.ContainerCreateResponse{Warnings: warnings}, err
|
return types.ContainerCreateResponse{Warnings: warnings}, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ContainerStart starts a container.
|
// ContainerStart starts a container.
|
||||||
func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.HostConfig) error {
|
func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.HostConfig, validateHostname bool) error {
|
||||||
container, err := daemon.GetContainer(name)
|
container, err := daemon.GetContainer(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -68,7 +68,7 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos
|
||||||
|
|
||||||
// check if hostConfig is in line with the current system settings.
|
// check if hostConfig is in line with the current system settings.
|
||||||
// It may happen cgroups are umounted or the like.
|
// It may happen cgroups are umounted or the like.
|
||||||
if _, err = daemon.verifyContainerSettings(container.HostConfig, nil, false); err != nil {
|
if _, err = daemon.verifyContainerSettings(container.HostConfig, nil, false, validateHostname); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Adapt for old containers in case we have updates in this function and
|
// Adapt for old containers in case we have updates in this function and
|
||||||
|
|
|
@ -7,10 +7,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ContainerUpdate updates configuration of the container
|
// ContainerUpdate updates configuration of the container
|
||||||
func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostConfig) ([]string, error) {
|
func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostConfig, validateHostname bool) ([]string, error) {
|
||||||
var warnings []string
|
var warnings []string
|
||||||
|
|
||||||
warnings, err := daemon.verifyContainerSettings(hostConfig, nil, true)
|
warnings, err := daemon.verifyContainerSettings(hostConfig, nil, true, validateHostname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return warnings, err
|
return warnings, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,9 +133,10 @@ This section lists each version from latest to oldest. Each listing includes a
|
||||||
* `POST /containers/{name:.*}/copy` is now removed and errors out starting from this API version.
|
* `POST /containers/{name:.*}/copy` is now removed and errors out starting from this API version.
|
||||||
* API errors are now returned as JSON instead of plain text.
|
* API errors are now returned as JSON instead of plain text.
|
||||||
* `POST /containers/create` and `POST /containers/(id)/start` allow you to configure kernel parameters (sysctls) for use in the container.
|
* `POST /containers/create` and `POST /containers/(id)/start` allow you to configure kernel parameters (sysctls) for use in the container.
|
||||||
* `POST /v1.23/containers/<container ID>/exec` and `POST /v1.23/exec/<exec ID>/start`
|
* `POST /containers/<container ID>/exec` and `POST /exec/<exec ID>/start`
|
||||||
no longer expects a "Container" field to be present. This property was not used
|
no longer expects a "Container" field to be present. This property was not used
|
||||||
and is no longer sent by the docker client.
|
and is no longer sent by the docker client.
|
||||||
|
* `POST /containers/create/` now validates the hostname (should be a valid RFC 1123 hostname).
|
||||||
|
|
||||||
### v1.23 API changes
|
### v1.23 API changes
|
||||||
|
|
||||||
|
|
|
@ -361,7 +361,7 @@ Create a container
|
||||||
**JSON parameters**:
|
**JSON parameters**:
|
||||||
|
|
||||||
- **Hostname** - A string value containing the hostname to use for the
|
- **Hostname** - A string value containing the hostname to use for the
|
||||||
container.
|
container. This must be a valid RFC 1123 hostname.
|
||||||
- **Domainname** - A string value containing the domain name to use
|
- **Domainname** - A string value containing the domain name to use
|
||||||
for the container.
|
for the container.
|
||||||
- **User** - A string value specifying the user inside the container.
|
- **User** - A string value specifying the user inside the container.
|
||||||
|
|
|
@ -362,7 +362,7 @@ Create a container
|
||||||
**JSON parameters**:
|
**JSON parameters**:
|
||||||
|
|
||||||
- **Hostname** - A string value containing the hostname to use for the
|
- **Hostname** - A string value containing the hostname to use for the
|
||||||
container.
|
container. This must be a valid RFC 1123 hostname.
|
||||||
- **Domainname** - A string value containing the domain name to use
|
- **Domainname** - A string value containing the domain name to use
|
||||||
for the container.
|
for the container.
|
||||||
- **User** - A string value specifying the user inside the container.
|
- **User** - A string value specifying the user inside the container.
|
||||||
|
|
Loading…
Add table
Reference in a new issue