Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support --platform docker CLI argument to target the platform specific image architecture #103

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions builder/docker/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ type Config struct {
// running on a windows host. This is necessary for building Windows
// containers, because our normal docker bindings do not work for them.
WindowsContainer bool `mapstructure:"windows_container" required:"false"`
// Set platform if server is multi-platform capable
Platform string `mapstructure:"platform" required:"false"`

// This is used to login to dockerhub to pull a private base container. For
// pushing to dockerhub, see the docker post-processors
Expand Down
2 changes: 2 additions & 0 deletions builder/docker/config.hcl2spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions builder/docker/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type Driver interface {
Export(id string, dst io.Writer) error

// Import imports a container from a tar file
Import(path string, changes []string, repo string) (string, error)
Import(path string, changes []string, repo string, platform string) (string, error)

// IPAddress returns the address of the container that can be used
// for external access.
Expand All @@ -40,10 +40,10 @@ type Driver interface {
Logout(repo string) error

// Pull should pull down the given image.
Pull(image string) error
Pull(image string, platform string) error

// Push pushes an image to a Docker index/registry.
Push(name string) error
Push(name string, platform string) error

// Save an image with the given ID to the given writer.
SaveImage(id string, dst io.Writer) error
Expand Down Expand Up @@ -79,6 +79,7 @@ type ContainerConfig struct {
TmpFs []string
Privileged bool
Runtime string
Platform string
}

// This is the template that is used for the RunCommand in the ContainerConfig.
Expand Down
21 changes: 18 additions & 3 deletions builder/docker/driver_docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func (d *DockerDriver) Export(id string, dst io.Writer) error {
return nil
}

func (d *DockerDriver) Import(path string, changes []string, repo string) (string, error) {
func (d *DockerDriver) Import(path string, changes []string, repo string, platform string) (string, error) {
var stdout, stderr bytes.Buffer

args := []string{"import"}
Expand All @@ -110,6 +110,10 @@ func (d *DockerDriver) Import(path string, changes []string, repo string) (strin
args = append(args, "--change", change)
}

if platform != "" {
args = append(args, "--platform", platform)
}

args = append(args, "-")
args = append(args, repo)

Expand Down Expand Up @@ -275,15 +279,23 @@ func (d *DockerDriver) Logout(repo string) error {
return err
}

func (d *DockerDriver) Pull(image string) error {
func (d *DockerDriver) Pull(image string, platform string) error {
cmd := d.newCommandWithConfig("pull", image)

if platform != "" {
cmd.Args = append(cmd.Args, "--platform", platform)
}

return runAndStream(cmd, d.Ui)
}

func (d *DockerDriver) Push(name string) error {
func (d *DockerDriver) Push(name string, platform string) error {
cmd := d.newCommandWithConfig("push", name)

if platform != "" {
cmd.Args = append(cmd.Args, "--platform", platform)
}

return runAndStream(cmd, d.Ui)
}

Expand Down Expand Up @@ -331,6 +343,9 @@ func (d *DockerDriver) StartContainer(config *ContainerConfig) (string, error) {
if config.Runtime != "" {
args = append(args, "--runtime", config.Runtime)
}
if config.Platform != "" {
args = append(args, "--platform", config.Platform)
}
for _, v := range config.TmpFs {
args = append(args, "--tmpfs", v)
}
Expand Down
28 changes: 17 additions & 11 deletions builder/docker/driver_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ type MockDriver struct {
DeleteImageId string
DeleteImageErr error

ImportCalled bool
ImportPath string
ImportRepo string
ImportId string
ImportErr error
ImportCalled bool
ImportPath string
ImportRepo string
ImportId string
ImportPlatform string
ImportErr error

IPAddressCalled bool
IPAddressID string
Expand Down Expand Up @@ -52,9 +53,10 @@ type MockDriver struct {
LogoutRepo string
LogoutErr error

PushCalled bool
PushName string
PushErr error
PushCalled bool
PushName string
PushPlatform string
PushErr error

SaveImageCalled bool
SaveImageId string
Expand All @@ -79,6 +81,7 @@ type MockDriver struct {
ExportID string
PullCalled bool
PullImage string
PullPlatform string
StartCalled bool
StartConfig *ContainerConfig
StopCalled bool
Expand Down Expand Up @@ -115,10 +118,11 @@ func (d *MockDriver) Export(id string, dst io.Writer) error {
return d.ExportError
}

func (d *MockDriver) Import(path string, changes []string, repo string) (string, error) {
func (d *MockDriver) Import(path string, changes []string, repo string, platform string) (string, error) {
d.ImportCalled = true
d.ImportPath = path
d.ImportRepo = repo
d.ImportPlatform = platform
return d.ImportId, d.ImportErr
}

Expand Down Expand Up @@ -154,15 +158,17 @@ func (d *MockDriver) Logout(r string) error {
return d.LogoutErr
}

func (d *MockDriver) Pull(image string) error {
func (d *MockDriver) Pull(image string, platform string) error {
d.PullCalled = true
d.PullImage = image
d.PullPlatform = platform
return d.PullError
}

func (d *MockDriver) Push(name string) error {
func (d *MockDriver) Push(name string, platform string) error {
d.PushCalled = true
d.PushName = name
d.PushPlatform = platform
return d.PushErr
}

Expand Down
2 changes: 1 addition & 1 deletion builder/docker/step_pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func (s *StepPull) Run(ctx context.Context, state multistep.StateBag) multistep.
}()
}

if err := driver.Pull(config.Image); err != nil {
if err := driver.Pull(config.Image, config.Platform); err != nil {
err := fmt.Errorf("Error pulling Docker image: %s", err)
state.Put("error", err)
ui.Error(err.Error())
Expand Down
1 change: 1 addition & 0 deletions builder/docker/step_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func (s *StepRun) Run(ctx context.Context, state multistep.StateBag) multistep.S
CapDrop: config.CapDrop,
Privileged: config.Privileged,
Runtime: config.Runtime,
Platform: config.Platform,
}

for host, container := range config.Volumes {
Expand Down
2 changes: 2 additions & 0 deletions docs-partials/builder/docker/Config-not-required.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
running on a windows host. This is necessary for building Windows
containers, because our normal docker bindings do not work for them.

- `platform` (string) - Set platform if server is multi-platform capable

- `login` (bool) - This is used to login to dockerhub to pull a private base container. For
pushing to dockerhub, see the docker post-processors

Expand Down
2 changes: 2 additions & 0 deletions docs/builders/docker.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,8 @@ You must specify (only) one of `commit`, `discard`, or `export_path`.
running on a windows host. This is necessary for building Windows
containers, because our normal docker bindings do not work for them.

- `platform` (string) - Set platform if server is multi-platform capable.

- `login` (bool) - This is used to login to dockerhub to pull a private base container. For
pushing to dockerhub, see the docker post-processors

Expand Down
2 changes: 2 additions & 0 deletions docs/post-processors/docker-import.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ is optional.
- `keep_input_artifact` (boolean) - if true, do not delete the source tar
after importing it to docker. Defaults to false.

- `platform` (string) - Set platform if server is multi-platform capable.

## Example

An example is shown below, showing only the post-processor configuration:
Expand Down
2 changes: 2 additions & 0 deletions docs/post-processors/docker-push.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ This post-processor has only optional configuration:
after pushing it to the cloud. Defaults to true, but can be set to false if
you do not need to save your local copy of the docker container.

- `platform` (string) - Set platform if server is multi-platform capable.

- `login` (boolean) - Defaults to false. If true, the post-processor will
login prior to pushing. For log into ECR see `ecr_login`.

Expand Down
3 changes: 2 additions & 1 deletion post-processor/docker-import/post-processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type Config struct {
Repository string `mapstructure:"repository"`
Tag string `mapstructure:"tag"`
Changes []string `mapstructure:"changes"`
Platform string `mapstructure:"platform"`

ctx interpolate.Context
}
Expand Down Expand Up @@ -73,7 +74,7 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packersdk.Ui, artifa

ui.Message("Importing image: " + artifact.Id())
ui.Message("Repository: " + importRepo)
id, err := driver.Import(artifact.Files()[0], p.config.Changes, importRepo)
id, err := driver.Import(artifact.Files()[0], p.config.Changes, importRepo, p.config.Platform)
if err != nil {
return nil, false, false, err
}
Expand Down
2 changes: 2 additions & 0 deletions post-processor/docker-import/post-processor.hcl2spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion post-processor/docker-push/post-processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type Config struct {
LoginPassword string `mapstructure:"login_password"`
LoginServer string `mapstructure:"login_server"`
EcrLogin bool `mapstructure:"ecr_login"`
Platform string `mapstructure:"platform"`
docker.AwsAccessConfig `mapstructure:",squash"`

ctx interpolate.Context
Expand Down Expand Up @@ -147,7 +148,7 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packersdk.Ui, artifa
// Get the name.
for _, name := range names {
ui.Message("Pushing: " + name)
if err := driver.Push(name); err != nil {
if err := driver.Push(name, p.config.Platform); err != nil {
return nil, false, false, err
}
}
Expand Down
2 changes: 2 additions & 0 deletions post-processor/docker-push/post-processor.hcl2spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.