Added ability to create image from archive
This commit is contained in:
parent
67cdf21c62
commit
babbe86933
|
@ -51,6 +51,7 @@ type DockerDriverAuth struct {
|
||||||
|
|
||||||
type DockerDriverConfig struct {
|
type DockerDriverConfig struct {
|
||||||
ImageName string `mapstructure:"image"` // Container's Image Name
|
ImageName string `mapstructure:"image"` // Container's Image Name
|
||||||
|
LoadImage string `mapstructure:"load"` // LoadImage is the path to the image archive
|
||||||
Command string `mapstructure:"command"` // The Command/Entrypoint to run when the container starts up
|
Command string `mapstructure:"command"` // The Command/Entrypoint to run when the container starts up
|
||||||
Args []string `mapstructure:"args"` // The arguments to the Command/Entrypoint
|
Args []string `mapstructure:"args"` // The arguments to the Command/Entrypoint
|
||||||
IpcMode string `mapstructure:"ipc_mode"` // The IPC mode of the container - host and none
|
IpcMode string `mapstructure:"ipc_mode"` // The IPC mode of the container - host and none
|
||||||
|
@ -419,48 +420,15 @@ func (d *DockerDriver) Periodic() (bool, time.Duration) {
|
||||||
return true, 15 * time.Second
|
return true, 15 * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DockerDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, error) {
|
func (d *DockerDriver) createImage(driverConfig *DockerDriverConfig, client *docker.Client, taskDir string) error {
|
||||||
var driverConfig DockerDriverConfig
|
|
||||||
if err := mapstructure.WeakDecode(task.Config, &driverConfig); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := driverConfig.Init(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
image := driverConfig.ImageName
|
image := driverConfig.ImageName
|
||||||
|
|
||||||
if err := driverConfig.Validate(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if task.Resources == nil {
|
|
||||||
return nil, fmt.Errorf("Resources are not specified")
|
|
||||||
}
|
|
||||||
if task.Resources.MemoryMB == 0 {
|
|
||||||
return nil, fmt.Errorf("Memory limit cannot be zero")
|
|
||||||
}
|
|
||||||
if task.Resources.CPU == 0 {
|
|
||||||
return nil, fmt.Errorf("CPU limit cannot be zero")
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanupContainer := d.config.ReadBoolDefault("docker.cleanup.container", true)
|
|
||||||
cleanupImage := d.config.ReadBoolDefault("docker.cleanup.image", true)
|
|
||||||
|
|
||||||
// Initialize docker API client
|
|
||||||
client, err := d.dockerClient()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Failed to connect to docker daemon: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
repo, tag := docker.ParseRepositoryTag(image)
|
repo, tag := docker.ParseRepositoryTag(image)
|
||||||
// Make sure tag is always explicitly set. We'll default to "latest" if it
|
|
||||||
// isn't, which is the expected behavior.
|
|
||||||
if tag == "" {
|
if tag == "" {
|
||||||
tag = "latest"
|
tag = "latest"
|
||||||
}
|
}
|
||||||
|
|
||||||
var dockerImage *docker.Image
|
var dockerImage *docker.Image
|
||||||
|
var err error
|
||||||
// We're going to check whether the image is already downloaded. If the tag
|
// We're going to check whether the image is already downloaded. If the tag
|
||||||
// is "latest" we have to check for a new version every time so we don't
|
// is "latest" we have to check for a new version every time so we don't
|
||||||
// bother to check and cache the id here. We'll download first, then cache.
|
// bother to check and cache the id here. We'll download first, then cache.
|
||||||
|
@ -470,6 +438,18 @@ func (d *DockerDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle
|
||||||
|
|
||||||
// Download the image
|
// Download the image
|
||||||
if dockerImage == nil {
|
if dockerImage == nil {
|
||||||
|
if driverConfig.LoadImage != "" {
|
||||||
|
return d.loadImage(driverConfig, client, taskDir)
|
||||||
|
} else if driverConfig.ImageName != "" {
|
||||||
|
return d.pullImage(driverConfig, client, repo, tag)
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("either image name or load image has to be specified")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DockerDriver) pullImage(driverConfig *DockerDriverConfig, client *docker.Client, repo string, tag string) error {
|
||||||
pullOptions := docker.PullImageOptions{
|
pullOptions := docker.PullImageOptions{
|
||||||
Repository: repo,
|
Repository: repo,
|
||||||
Tag: tag,
|
Tag: tag,
|
||||||
|
@ -490,7 +470,7 @@ func (d *DockerDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
var authConfigurations *docker.AuthConfigurations
|
var authConfigurations *docker.AuthConfigurations
|
||||||
if authConfigurations, err = docker.NewAuthConfigurations(f); err != nil {
|
if authConfigurations, err = docker.NewAuthConfigurations(f); err != nil {
|
||||||
return nil, fmt.Errorf("Failed to create docker auth object: %v", err)
|
return fmt.Errorf("Failed to create docker auth object: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
authConfigurationKey := ""
|
authConfigurationKey := ""
|
||||||
|
@ -503,30 +483,70 @@ func (d *DockerDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle
|
||||||
authOptions = authConfiguration
|
authOptions = authConfiguration
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("Failed to open auth config file: %v, error: %v", authConfigFile, err)
|
return fmt.Errorf("Failed to open auth config file: %v, error: %v", authConfigFile, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = client.PullImage(pullOptions, authOptions)
|
err := client.PullImage(pullOptions, authOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.logger.Printf("[ERR] driver.docker: failed pulling container %s:%s: %s", repo, tag, err)
|
d.logger.Printf("[ERR] driver.docker: failed pulling container %s:%s: %s", repo, tag, err)
|
||||||
return nil, d.recoverablePullError(err, image)
|
return d.recoverablePullError(err, driverConfig.ImageName)
|
||||||
}
|
}
|
||||||
d.logger.Printf("[DEBUG] driver.docker: docker pull %s:%s succeeded", repo, tag)
|
d.logger.Printf("[DEBUG] driver.docker: docker pull %s:%s succeeded", repo, tag)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Now that we have the image we can get the image id
|
func (d *DockerDriver) loadImage(driverConfig *DockerDriverConfig, client *docker.Client, taskDir string) error {
|
||||||
dockerImage, err = client.InspectImage(image)
|
archive := filepath.Join(taskDir, allocdir.TaskLocal, driverConfig.LoadImage)
|
||||||
|
d.logger.Printf("[DEBUG] driver.docker: loading image from: %v", archive)
|
||||||
|
f, err := os.Open(archive)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.logger.Printf("[ERR] driver.docker: failed getting image id for %s: %s", image, err)
|
return fmt.Errorf("unable to open image archive: %v", err)
|
||||||
return nil, fmt.Errorf("Failed to determine image id for `%s`: %s", image, err)
|
|
||||||
}
|
}
|
||||||
|
defer f.Close()
|
||||||
|
return client.LoadImage(docker.LoadImageOptions{InputStream: f})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DockerDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, error) {
|
||||||
|
var driverConfig DockerDriverConfig
|
||||||
|
if err := mapstructure.WeakDecode(task.Config, &driverConfig); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := driverConfig.Init(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
image := driverConfig.ImageName
|
||||||
|
|
||||||
|
if err := driverConfig.Validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanupContainer := d.config.ReadBoolDefault("docker.cleanup.container", true)
|
||||||
|
cleanupImage := d.config.ReadBoolDefault("docker.cleanup.image", true)
|
||||||
|
|
||||||
taskDir, ok := ctx.AllocDir.TaskDirs[d.DriverContext.taskName]
|
taskDir, ok := ctx.AllocDir.TaskDirs[d.DriverContext.taskName]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("Could not find task directory for task: %v", d.DriverContext.taskName)
|
return nil, fmt.Errorf("Could not find task directory for task: %v", d.DriverContext.taskName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize docker API client
|
||||||
|
client, err := d.dockerClient()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to connect to docker daemon: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := d.createImage(&driverConfig, client, taskDir); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to pull image: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that we have the image we can get the image id
|
||||||
|
dockerImage, err := client.InspectImage(image)
|
||||||
|
if err != nil {
|
||||||
|
d.logger.Printf("[ERR] driver.docker: failed getting image id for %s: %s", image, err)
|
||||||
|
return nil, fmt.Errorf("Failed to determine image id for `%s`: %s", image, err)
|
||||||
|
}
|
||||||
d.logger.Printf("[DEBUG] driver.docker: identified image %s as %s", image, dockerImage.ID)
|
d.logger.Printf("[DEBUG] driver.docker: identified image %s as %s", image, dockerImage.ID)
|
||||||
|
|
||||||
bin, err := discover.NomadExecutable()
|
bin, err := discover.NomadExecutable()
|
||||||
|
|
Loading…
Reference in a new issue