Commit 037a744b authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

builder/docker: customize run command [GH-648]

parent be786108
...@@ -45,6 +45,8 @@ IMPROVEMENTS: ...@@ -45,6 +45,8 @@ IMPROVEMENTS:
"Packer Builder" so that they are easily recognizable. [GH-642] "Packer Builder" so that they are easily recognizable. [GH-642]
* builder/amazon/all: Copying AMIs to multiple regions now happens * builder/amazon/all: Copying AMIs to multiple regions now happens
in parallel. [GH-495] in parallel. [GH-495]
* builder/docker: A "run\_command" can be specified, configuring how
the container is started. [GH-648]
* builder/openstack: In debug mode, the generated SSH keypair is saved * builder/openstack: In debug mode, the generated SSH keypair is saved
so you can SSH into the machine. [GH-746] so you can SSH into the machine. [GH-746]
* builder/qemu: Floppy files are supported. [GH-686] * builder/qemu: Floppy files are supported. [GH-686]
......
...@@ -25,7 +25,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { ...@@ -25,7 +25,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
} }
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) { func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
driver := &DockerDriver{Ui: ui} driver := &DockerDriver{Tpl: b.config.tpl, Ui: ui}
if err := driver.Verify(); err != nil { if err := driver.Verify(); err != nil {
return nil, err return nil, err
} }
......
...@@ -12,6 +12,7 @@ type Config struct { ...@@ -12,6 +12,7 @@ type Config struct {
ExportPath string `mapstructure:"export_path"` ExportPath string `mapstructure:"export_path"`
Image string Image string
Pull bool Pull bool
RunCommand []string `mapstructure:"run_command"`
tpl *packer.ConfigTemplate tpl *packer.ConfigTemplate
} }
...@@ -28,6 +29,17 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { ...@@ -28,6 +29,17 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
return nil, nil, err return nil, nil, err
} }
// Defaults
if len(c.RunCommand) == 0 {
c.RunCommand = []string{
"run",
"-d", "-i", "-t",
"-v", "{{.Volumes}}",
"{{.Image}}",
"/bin/bash",
}
}
// Default Pull if it wasn't set // Default Pull if it wasn't set
hasPull := false hasPull := false
for _, k := range md.Keys { for _, k := range md.Keys {
......
...@@ -28,5 +28,12 @@ type Driver interface { ...@@ -28,5 +28,12 @@ type Driver interface {
// ContainerConfig is the configuration used to start a container. // ContainerConfig is the configuration used to start a container.
type ContainerConfig struct { type ContainerConfig struct {
Image string Image string
RunCommand []string
Volumes map[string]string Volumes map[string]string
} }
// This is the template that is used for the RunCommand in the ContainerConfig.
type startContainerTemplate struct {
Image string
Volumes string
}
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
type DockerDriver struct { type DockerDriver struct {
Ui packer.Ui Ui packer.Ui
Tpl *packer.ConfigTemplate
} }
func (d *DockerDriver) Export(id string, dst io.Writer) error { func (d *DockerDriver) Export(id string, dst io.Writer) error {
...@@ -40,19 +41,29 @@ func (d *DockerDriver) Pull(image string) error { ...@@ -40,19 +41,29 @@ func (d *DockerDriver) Pull(image string) error {
} }
func (d *DockerDriver) StartContainer(config *ContainerConfig) (string, error) { func (d *DockerDriver) StartContainer(config *ContainerConfig) (string, error) {
// Args that we're going to pass to Docker // Build up the template data
args := []string{"run", "-d", "-i", "-t"} var tplData startContainerTemplate
tplData.Image = config.Image
if len(config.Volumes) > 0 { if len(config.Volumes) > 0 {
volumes := make([]string, 0, len(config.Volumes)) volumes := make([]string, 0, len(config.Volumes))
for host, guest := range config.Volumes { for host, guest := range config.Volumes {
volumes = append(volumes, fmt.Sprintf("%s:%s", host, guest)) volumes = append(volumes, fmt.Sprintf("%s:%s", host, guest))
} }
args = append(args, "-v", strings.Join(volumes, ",")) tplData.Volumes = strings.Join(volumes, ",")
} }
args = append(args, config.Image, "/bin/bash") // Args that we're going to pass to Docker
args := config.RunCommand
for i, v := range args {
var err error
args[i], err = d.Tpl.Process(v, &tplData)
if err != nil {
return "", err
}
}
d.Ui.Message(fmt.Sprintf(
"Run command: docker %s", strings.Join(args, " ")))
// Start the container // Start the container
var stdout, stderr bytes.Buffer var stdout, stderr bytes.Buffer
......
...@@ -18,12 +18,13 @@ func (s *StepRun) Run(state multistep.StateBag) multistep.StepAction { ...@@ -18,12 +18,13 @@ func (s *StepRun) Run(state multistep.StateBag) multistep.StepAction {
runConfig := ContainerConfig{ runConfig := ContainerConfig{
Image: config.Image, Image: config.Image,
RunCommand: config.RunCommand,
Volumes: map[string]string{ Volumes: map[string]string{
tempDir: "/packer-files", tempDir: "/packer-files",
}, },
} }
ui.Say("Starting docker container with /bin/bash") ui.Say("Starting docker container...")
containerId, err := driver.StartContainer(&runConfig) containerId, err := driver.StartContainer(&runConfig)
if err != nil { if err != nil {
err := fmt.Errorf("Error running container: %s", err) err := fmt.Errorf("Error running container: %s", err)
......
...@@ -59,6 +59,11 @@ Optional: ...@@ -59,6 +59,11 @@ Optional:
`docker pull` prior to use. Otherwise, it is assumed the image already `docker pull` prior to use. Otherwise, it is assumed the image already
exists and can be used. This defaults to true if not set. exists and can be used. This defaults to true if not set.
* `run_command` (array of strings) - An array of arguments to pass to
`docker` in order to run the container. By default this is set to
`["run", "-d", "-i", "-t", "-v", "{{.Volumes}}", "{{.Image}}", "/bin/bash"]`.
As you can see, you have a couple template variables to customize, as well.
## Using the generated artifact ## Using the generated artifact
Once the tar artifact has been generated, you will likely want to import, tag, Once the tar artifact has been generated, you will likely want to import, tag,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment