diff --git a/builder/docker/builder.go b/builder/docker/builder.go index 1c7d8d2..981930d 100644 --- a/builder/docker/builder.go +++ b/builder/docker/builder.go @@ -89,6 +89,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) log.Print("[DEBUG] Container will be discarded") } else if b.config.Commit { log.Print("[DEBUG] Container will be committed") + steps = append(steps, &StepSetDefaults{}) steps = append(steps, &StepCommit{ GeneratedData: generatedData, }) diff --git a/builder/docker/driver_docker.go b/builder/docker/driver_docker.go index 662665a..ff1c1ef 100644 --- a/builder/docker/driver_docker.go +++ b/builder/docker/driver_docker.go @@ -214,6 +214,40 @@ func (d *DockerDriver) Digest(id string) (string, error) { return strings.TrimSpace(stdout.String()), nil } +func (d *DockerDriver) Cmd(id string) (string, error) { + var stderr, stdout bytes.Buffer + cmd := exec.Command( + "docker", + "inspect", + "--format", + "{{if .Config.Cmd}} {{json .Config.Cmd}} {{else}} [] {{end}}", + id) + cmd.Stdout = &stdout + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + return "", fmt.Errorf("Error: %s\n\nStderr: %s", err, stderr.String()) + } + + return strings.TrimSpace(stdout.String()), nil +} + +func (d *DockerDriver) Entrypoint(id string) (string, error) { + var stderr, stdout bytes.Buffer + cmd := exec.Command( + "docker", + "inspect", + "--format", + "{{if .Config.Entrypoint}} {{json .Config.Entrypoint}} {{else}} [] {{end}}", + id) + cmd.Stdout = &stdout + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + return "", fmt.Errorf("Error: %s\n\nStderr: %s", err, stderr.String()) + } + + return strings.TrimSpace(stdout.String()), nil +} + func (d *DockerDriver) Login(repo, user, pass string) error { d.l.Lock() diff --git a/builder/docker/step_set_defaults.go b/builder/docker/step_set_defaults.go new file mode 100644 index 0000000..88ac8ca --- /dev/null +++ b/builder/docker/step_set_defaults.go @@ -0,0 +1,40 @@ +package docker + +import ( + "context" + "strings" + + "github.com/hashicorp/packer-plugin-sdk/multistep" +) + +type StepSetDefaults struct{} + +func (s *StepSetDefaults) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { + driver := state.Get("driver").(*DockerDriver) + config := state.Get("config").(*Config) + + // Fetch default CMD and ENTRYPOINT + defaultCmd, _ := driver.Cmd(config.Image) + defaultEntrypoint, _ := driver.Entrypoint(config.Image) + + // Set defaults if not provided by the user + hasCmd, hasEntrypoint := false, false + for _, change := range config.Changes { + if strings.HasPrefix(change, "CMD") { + hasCmd = true + } else if strings.HasPrefix(change, "ENTRYPOINT") { + hasEntrypoint = true + } + } + + if !hasCmd && defaultCmd != "" { + config.Changes = append(config.Changes, "CMD "+defaultCmd) + } + if !hasEntrypoint && defaultEntrypoint != "" { + config.Changes = append(config.Changes, "ENTRYPOINT "+defaultEntrypoint) + } + + return multistep.ActionContinue +} + +func (s *StepSetDefaults) Cleanup(state multistep.StateBag) {}