in gce-containers-startup/runtime/runtime.go [226:334]
func createContainer(runner ContainerRunner, auth string, spec api.ContainerSpecStruct) (string, error) {
if len(spec.Containers) != 1 {
return "", fmt.Errorf("Exactly one container in declaration expected.")
}
container := spec.Containers[0]
generatedContainerName := fmt.Sprintf("%s-%s-%s", CONTAINER_NAME_PREFIX, container.Name, generateRandomSuffix(4, runner.RandEnv))
log.Printf("Configured container '%s' will be started with name '%s'.\n", container.Name, generatedContainerName)
if err := pullImage(runner.Client, auth, container); err != nil {
return "", err
}
if err := deleteOldContainers(runner.Client, container.Name); err != nil {
return "", err
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
printWarningIfLikelyHasMistake(container.Command, container.Args)
var runCommand dockerstrslice.StrSlice
if container.Command != nil {
runCommand = dockerstrslice.StrSlice(container.Command)
}
var runArgs dockerstrslice.StrSlice
if container.Args != nil {
runArgs = dockerstrslice.StrSlice(container.Args)
}
if err := runner.VolumesEnv.UnmountExistingVolumes(); err != nil {
log.Printf("Error: failed to unmount volumes:\n%v", err)
}
containerVolumeBindingConfigurationMap, volumePrepareError := runner.VolumesEnv.PrepareVolumesAndGetBindings(spec)
if volumePrepareError != nil {
return "", volumePrepareError
}
volumeBindingConfiguration, volumeBindingFound := containerVolumeBindingConfigurationMap[container.Name]
if !volumeBindingFound {
return "", fmt.Errorf("Volume binding configuration for container %s not found in the map. This should not happen.", container.Name)
}
// Docker-API compatible types.
hostPathBinds := []string{}
for _, hostPathBindConfiguration := range volumeBindingConfiguration {
hostPathBind := fmt.Sprintf("%s:%s", hostPathBindConfiguration.HostPath, hostPathBindConfiguration.ContainerPath)
if hostPathBindConfiguration.ReadOnly {
hostPathBind = fmt.Sprintf("%s:ro", hostPathBind)
}
hostPathBinds = append(hostPathBinds, hostPathBind)
}
env := []string{}
for _, envVar := range container.Env {
env = append(env, fmt.Sprintf("%s=%s", envVar.Name, envVar.Value))
}
restartPolicyName := "always"
if spec.RestartPolicy == nil || *spec.RestartPolicy == api.RestartPolicyAlways {
restartPolicyName = "always"
} else if *spec.RestartPolicy == api.RestartPolicyOnFailure {
restartPolicyName = "on-failure"
} else if *spec.RestartPolicy == api.RestartPolicyNever {
restartPolicyName = "no"
} else {
return "", fmt.Errorf(
"Invalid container declaration: Unsupported container restart policy '%s'", *spec.RestartPolicy)
}
opts := dockertypes.ContainerCreateConfig{
Name: generatedContainerName,
Config: &dockercontainer.Config{
Entrypoint: runCommand,
Cmd: runArgs,
Image: container.Image,
Env: env,
OpenStdin: container.StdIn,
Tty: container.Tty,
},
HostConfig: &dockercontainer.HostConfig{
Binds: hostPathBinds,
AutoRemove: false,
NetworkMode: "host",
Privileged: container.SecurityContext.Privileged,
LogConfig: dockercontainer.LogConfig{
Type: "json-file",
Config: map[string]string{
"max-size": "500m",
"max-file": "3",
},
},
RestartPolicy: dockercontainer.RestartPolicy{
Name: restartPolicyName,
},
},
}
createResp, err := runner.Client.ContainerCreate(
ctx, opts.Config, opts.HostConfig, opts.NetworkingConfig, opts.Name)
if ctxErr := contextError(ctx, "Create container"); ctxErr != nil {
return "", ctxErr
}
if err != nil {
return "", err
}
log.Printf("Created a container with name '%s' and ID: %s", generatedContainerName, createResp.ID)
return createResp.ID, nil
}