7107898d5c
Fixes #8942 Current behavior is that volumes aren't initialized until start. Volumes still need to be initialized on start since VolumesFrom and Binds can be passed in as part of HostConfig on start, however anything that's already been initialized will just be skipped as is the current behavior. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
108 lines
3.1 KiB
Go
108 lines
3.1 KiB
Go
package daemon
|
|
|
|
import (
|
|
"github.com/docker/docker/engine"
|
|
"github.com/docker/docker/graph"
|
|
"github.com/docker/docker/pkg/parsers"
|
|
"github.com/docker/docker/runconfig"
|
|
)
|
|
|
|
func (daemon *Daemon) ContainerCreate(job *engine.Job) engine.Status {
|
|
var name string
|
|
if len(job.Args) == 1 {
|
|
name = job.Args[0]
|
|
} else if len(job.Args) > 1 {
|
|
return job.Errorf("Usage: %s", job.Name)
|
|
}
|
|
config := runconfig.ContainerConfigFromJob(job)
|
|
if config.Memory != 0 && config.Memory < 4194304 {
|
|
return job.Errorf("Minimum memory limit allowed is 4MB")
|
|
}
|
|
if config.Memory > 0 && !daemon.SystemConfig().MemoryLimit {
|
|
job.Errorf("Your kernel does not support memory limit capabilities. Limitation discarded.\n")
|
|
config.Memory = 0
|
|
}
|
|
if config.Memory > 0 && !daemon.SystemConfig().SwapLimit {
|
|
job.Errorf("Your kernel does not support swap limit capabilities. Limitation discarded.\n")
|
|
config.MemorySwap = -1
|
|
}
|
|
|
|
var hostConfig *runconfig.HostConfig
|
|
if job.EnvExists("HostConfig") {
|
|
hostConfig = runconfig.ContainerHostConfigFromJob(job)
|
|
} else {
|
|
// Older versions of the API don't provide a HostConfig.
|
|
hostConfig = nil
|
|
}
|
|
|
|
container, buildWarnings, err := daemon.Create(config, hostConfig, name)
|
|
if err != nil {
|
|
if daemon.Graph().IsNotExist(err) {
|
|
_, tag := parsers.ParseRepositoryTag(config.Image)
|
|
if tag == "" {
|
|
tag = graph.DEFAULTTAG
|
|
}
|
|
return job.Errorf("No such image: %s (tag: %s)", config.Image, tag)
|
|
}
|
|
return job.Error(err)
|
|
}
|
|
if !container.Config.NetworkDisabled && daemon.SystemConfig().IPv4ForwardingDisabled {
|
|
job.Errorf("IPv4 forwarding is disabled.\n")
|
|
}
|
|
container.LogEvent("create")
|
|
// FIXME: this is necessary because daemon.Create might return a nil container
|
|
// with a non-nil error. This should not happen! Once it's fixed we
|
|
// can remove this workaround.
|
|
if container != nil {
|
|
job.Printf("%s\n", container.ID)
|
|
}
|
|
for _, warning := range buildWarnings {
|
|
job.Errorf("%s\n", warning)
|
|
}
|
|
|
|
return engine.StatusOK
|
|
}
|
|
|
|
// Create creates a new container from the given configuration with a given name.
|
|
func (daemon *Daemon) Create(config *runconfig.Config, hostConfig *runconfig.HostConfig, name string) (*Container, []string, error) {
|
|
var (
|
|
container *Container
|
|
warnings []string
|
|
)
|
|
|
|
img, err := daemon.repositories.LookupImage(config.Image)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if err := img.CheckDepth(); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if warnings, err = daemon.mergeAndVerifyConfig(config, img); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if container, err = daemon.newContainer(name, config, img); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if err := daemon.Register(container); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if err := daemon.createRootfs(container, img); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if hostConfig != nil {
|
|
if err := daemon.setHostConfig(container, hostConfig); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
}
|
|
if err := container.Mount(); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
defer container.Unmount()
|
|
if err := container.prepareVolumes(); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if err := container.ToDisk(); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return container, warnings, nil
|
|
}
|