diff --git a/builder/docker/builder.go b/builder/docker/builder.go index 0b343c0db..09c5826a7 100644 --- a/builder/docker/builder.go +++ b/builder/docker/builder.go @@ -41,6 +41,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe &StepPull{}, &StepRun{}, &StepProvision{}, + &StepExport{}, } // Setup the state bag and initial state for the steps diff --git a/builder/docker/config.go b/builder/docker/config.go index 4bab81bdd..86f3da982 100644 --- a/builder/docker/config.go +++ b/builder/docker/config.go @@ -8,7 +8,8 @@ import ( type Config struct { common.PackerConfig `mapstructure:",squash"` - Image string + ExportPath string `mapstructure:"export_path"` + Image string tpl *packer.ConfigTemplate } diff --git a/builder/docker/step_export.go b/builder/docker/step_export.go new file mode 100644 index 000000000..de50844b9 --- /dev/null +++ b/builder/docker/step_export.go @@ -0,0 +1,61 @@ +package docker + +import ( + "bytes" + "fmt" + "github.com/mitchellh/multistep" + "github.com/mitchellh/packer/packer" + "log" + "os" + "os/exec" +) + +// StepExport exports the container to a flat tar file. +type StepExport struct{} + +func (s *StepExport) Run(state multistep.StateBag) multistep.StepAction { + config := state.Get("config").(*Config) + containerId := state.Get("container_id").(string) + ui := state.Get("ui").(packer.Ui) + + ui.Say("Exporting the container") + + // Args that we're going to pass to Docker + args := []string{"export", containerId} + + // Open the file that we're going to write to + f, err := os.Create(config.ExportPath) + if err != nil { + err := fmt.Errorf("Error creating output file: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + defer f.Close() + + // Export the thing, take stderr and point it to the file + var stderr bytes.Buffer + cmd := exec.Command("docker", args...) + cmd.Stdout = f + cmd.Stderr = &stderr + + log.Printf("Starting container with args: %v", args) + if err := cmd.Start(); err != nil { + err := fmt.Errorf("Error exporting: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + + if err := cmd.Wait(); err != nil { + err := fmt.Errorf("Error exporting: %s\nStderr: %s", + err, stderr.String()) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + + return multistep.ActionContinue +} + +func (s *StepExport) Cleanup(state multistep.StateBag) {}