diff --git a/builder/docker/driver.go b/builder/docker/driver.go index 09da054f3..7359a667d 100644 --- a/builder/docker/driver.go +++ b/builder/docker/driver.go @@ -20,7 +20,7 @@ type Driver interface { Export(id string, dst io.Writer) error // Import imports a container from a tar file - Import(path, repo string) (string, error) + Import(path string, changes []string, repo string) (string, error) // IPAddress returns the address of the container that can be used // for external access. diff --git a/builder/docker/driver_docker.go b/builder/docker/driver_docker.go index 50a2b9920..918dfdb2c 100644 --- a/builder/docker/driver_docker.go +++ b/builder/docker/driver_docker.go @@ -97,12 +97,23 @@ func (d *DockerDriver) Export(id string, dst io.Writer) error { return nil } -func (d *DockerDriver) Import(path string, repo string) (string, error) { +func (d *DockerDriver) Import(path string, changes []string, repo string) (string, error) { var stdout, stderr bytes.Buffer - cmd := exec.Command("docker", "import", "-", repo) + + args := []string{"import"} + + for _, change := range changes { + args = append(args, "--change", change) + } + + args = append(args, "-") + args = append(args, repo) + + cmd := exec.Command("docker", args...) cmd.Stdout = &stdout cmd.Stderr = &stderr stdin, err := cmd.StdinPipe() + if err != nil { return "", err } @@ -114,6 +125,8 @@ func (d *DockerDriver) Import(path string, repo string) (string, error) { } defer file.Close() + log.Printf("Importing tarball with args: %v", args) + if err := cmd.Start(); err != nil { return "", err } diff --git a/builder/docker/driver_mock.go b/builder/docker/driver_mock.go index 5193f21ee..4cca3325b 100644 --- a/builder/docker/driver_mock.go +++ b/builder/docker/driver_mock.go @@ -101,7 +101,7 @@ func (d *MockDriver) Export(id string, dst io.Writer) error { return d.ExportError } -func (d *MockDriver) Import(path, repo string) (string, error) { +func (d *MockDriver) Import(path string, changes []string, repo string) (string, error) { d.ImportCalled = true d.ImportPath = path d.ImportRepo = repo diff --git a/post-processor/docker-import/post-processor.go b/post-processor/docker-import/post-processor.go index 80b99c8b3..eac920f06 100644 --- a/post-processor/docker-import/post-processor.go +++ b/post-processor/docker-import/post-processor.go @@ -16,8 +16,9 @@ const BuilderId = "packer.post-processor.docker-import" type Config struct { common.PackerConfig `mapstructure:",squash"` - Repository string `mapstructure:"repository"` - Tag string `mapstructure:"tag"` + Repository string `mapstructure:"repository"` + Tag string `mapstructure:"tag"` + Changes []string `mapstructure:"changes"` ctx interpolate.Context } @@ -62,7 +63,7 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac ui.Message("Importing image: " + artifact.Id()) ui.Message("Repository: " + importRepo) - id, err := driver.Import(artifact.Files()[0], importRepo) + id, err := driver.Import(artifact.Files()[0], p.config.Changes, importRepo) if err != nil { return nil, false, err } diff --git a/website/source/docs/post-processors/docker-import.html.md b/website/source/docs/post-processors/docker-import.html.md index 00add79e6..1d3e413d7 100644 --- a/website/source/docs/post-processors/docker-import.html.md +++ b/website/source/docs/post-processors/docker-import.html.md @@ -25,11 +25,20 @@ registry. The configuration for this post-processor only requires a `repository`, a `tag` is optional. +### Required: + - `repository` (string) - The repository of the imported image. - `tag` (string) - The tag for the imported image. By default this is not set. +### Optional: + +- `changes` (array of strings) - Dockerfile instructions to add to the + commit. Example of instructions are `CMD`, `ENTRYPOINT`, `ENV`, and + `EXPOSE`. Example: `[ "USER ubuntu", "WORKDIR /app", "EXPOSE 8080" ]` + + ## Example An example is shown below, showing only the post-processor configuration: @@ -48,3 +57,68 @@ into the local Docker process with a name of `hashicorp/packer:0.7`. Following this, you can use the [docker-push](/docs/post-processors/docker-push.html) post-processor to push it to a registry, if you want. + +## Changing Metadata + +Below is an example using the changes argument of the post-processor. This +feature allows the tarball metadata to be changed when imported into the +Docker environment. It is derived from the `docker import --change` command +line [option to +Docker](https://docs.docker.com/engine/reference/commandline/import/). + +Example uses of all of the options, assuming one is building an NGINX image +from ubuntu as an simple example: + +``` json +{ + "type": "docker-import", + "repository": "local/centos6", + "tag": "latest", + "changes": [ + "USER www-data", + "WORKDIR /var/www", + "ENV HOSTNAME www.example.com", + "VOLUME /test1 /test2", + "EXPOSE 80 443", + "LABEL version=1.0", + "ONBUILD RUN date", + "CMD [\"nginx\", \"-g\", \"daemon off;\"]", + "ENTRYPOINT /var/www/start.sh" + ] +} +``` + +Allowed metadata fields that can be changed are: + +- CMD + - String, supports both array (escaped) and string form + - EX: `"CMD [\"nginx\", \"-g\", \"daemon off;\"]"` + - EX: `"CMD nginx -g daemon off;"` +- ENTRYPOINT + - String + - EX: `"ENTRYPOINT /var/www/start.sh"` +- ENV + - String, note there is no equal sign: + - EX: `"ENV HOSTNAME www.example.com"` not + `"ENV HOSTNAME=www.example.com"` +- EXPOSE + - String, space separated ports + - EX: `"EXPOSE 80 443"` +- LABEL + - String, space separated key=value pairs + - EX: `"LABEL version=1.0"` +- ONBUILD + - String + - EX: `"ONBUILD RUN date"` +- MAINTAINER + - String, deprecated in Docker version 1.13.0 + - EX: `"MAINTAINER NAME"` +- USER + - String + - EX: `"USER USERNAME"` +- VOLUME + - String + - EX: `"VOLUME FROM TO"` +- WORKDIR + - String + - EX: `"WORKDIR PATH"`