Commit e4dc5d31 authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

builder/docker: support volumes

parent 2e4882f0
...@@ -16,6 +16,7 @@ FEATURES: ...@@ -16,6 +16,7 @@ FEATURES:
binaries named `packer-TYPE-NAME`. binaries named `packer-TYPE-NAME`.
* builder/docker: Images can now be committed instead of exported. [GH-1198] * builder/docker: Images can now be committed instead of exported. [GH-1198]
* builder/docker: Can now specify login credentials to pull images. * builder/docker: Can now specify login credentials to pull images.
* builder/docker: Support mounting additional volumes. [GH-1430]
* builder/virtualbox-ovf: New `import_flags` setting can be used to add * builder/virtualbox-ovf: New `import_flags` setting can be used to add
new command line flags to `VBoxManage import` to allow things such new command line flags to `VBoxManage import` to allow things such
as EULAs to be accepted. [GH-1383] as EULAs to be accepted. [GH-1383]
......
...@@ -14,6 +14,7 @@ type Config struct { ...@@ -14,6 +14,7 @@ type Config struct {
Image string Image string
Pull bool Pull bool
RunCommand []string `mapstructure:"run_command"` RunCommand []string `mapstructure:"run_command"`
Volumes map[string]string
Login bool Login bool
LoginEmail string `mapstructure:"login_email"` LoginEmail string `mapstructure:"login_email"`
...@@ -41,9 +42,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { ...@@ -41,9 +42,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
// Defaults // Defaults
if len(c.RunCommand) == 0 { if len(c.RunCommand) == 0 {
c.RunCommand = []string{ c.RunCommand = []string{
"run",
"-d", "-i", "-t", "-d", "-i", "-t",
"-v", "{{.Volumes}}",
"{{.Image}}", "{{.Image}}",
"/bin/bash", "/bin/bash",
} }
...@@ -82,6 +81,17 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { ...@@ -82,6 +81,17 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
} }
} }
for k, v := range c.Volumes {
var err error
v, err = c.tpl.Process(v, nil)
if err != nil {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("Error processing volumes[%s]: %s", k, err))
}
c.Volumes[k] = v
}
if c.Image == "" { if c.Image == "" {
errs = packer.MultiErrorAppend(errs, errs = packer.MultiErrorAppend(errs,
fmt.Errorf("image must be specified")) fmt.Errorf("image must be specified"))
......
...@@ -60,5 +60,4 @@ type ContainerConfig struct { ...@@ -60,5 +60,4 @@ type ContainerConfig struct {
// This is the template that is used for the RunCommand in the ContainerConfig. // This is the template that is used for the RunCommand in the ContainerConfig.
type startContainerTemplate struct { type startContainerTemplate struct {
Image string Image string
Volumes string
} }
...@@ -185,23 +185,19 @@ func (d *DockerDriver) StartContainer(config *ContainerConfig) (string, error) { ...@@ -185,23 +185,19 @@ func (d *DockerDriver) StartContainer(config *ContainerConfig) (string, error) {
// Build up the template data // Build up the template data
var tplData startContainerTemplate var tplData startContainerTemplate
tplData.Image = config.Image tplData.Image = config.Image
if len(config.Volumes) > 0 {
volumes := make([]string, 0, len(config.Volumes))
for host, guest := range config.Volumes {
volumes = append(volumes, fmt.Sprintf("%s:%s", host, guest))
}
tplData.Volumes = strings.Join(volumes, ",")
}
// Args that we're going to pass to Docker // Args that we're going to pass to Docker
args := config.RunCommand args := []string{"run"}
for i, v := range args { for host, guest := range config.Volumes {
var err error args = append(args, "-v", fmt.Sprintf("%s:%s", host, guest))
args[i], err = d.Tpl.Process(v, &tplData) }
for _, v := range config.RunCommand {
v, err := d.Tpl.Process(v, &tplData)
if err != nil { if err != nil {
return "", err return "", err
} }
args = append(args, v)
} }
d.Ui.Message(fmt.Sprintf( d.Ui.Message(fmt.Sprintf(
"Run command: docker %s", strings.Join(args, " "))) "Run command: docker %s", strings.Join(args, " ")))
......
...@@ -19,11 +19,14 @@ func (s *StepRun) Run(state multistep.StateBag) multistep.StepAction { ...@@ -19,11 +19,14 @@ func (s *StepRun) Run(state multistep.StateBag) multistep.StepAction {
runConfig := ContainerConfig{ runConfig := ContainerConfig{
Image: config.Image, Image: config.Image,
RunCommand: config.RunCommand, RunCommand: config.RunCommand,
Volumes: map[string]string{ Volumes: make(map[string]string),
tempDir: "/packer-files",
},
} }
for host, container := range config.Volumes {
runConfig.Volumes[host] = container
}
runConfig.Volumes[tempDir] = "/packer-files"
ui.Say("Starting docker container...") ui.Say("Starting docker container...")
containerId, err := driver.StartContainer(&runConfig) containerId, err := driver.StartContainer(&runConfig)
if err != nil { if err != nil {
......
...@@ -95,6 +95,10 @@ described. ...@@ -95,6 +95,10 @@ described.
`["run", "-d", "-i", "-t", "-v", "{{.Volumes}}", "{{.Image}}", "/bin/bash"]`. `["run", "-d", "-i", "-t", "-v", "{{.Volumes}}", "{{.Image}}", "/bin/bash"]`.
As you can see, you have a couple template variables to customize, as well. As you can see, you have a couple template variables to customize, as well.
* `volumes` (map of strings to strings) - A mapping of additional volumes
to mount into this container. The key of the object is the host path,
the value is the container path.
## Using the Artifact: Export ## Using the Artifact: Export
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