Skip to content

Commit 318b403

Browse files
committed
Add support for podman image digests
1 parent 123b8af commit 318b403

File tree

5 files changed

+40
-8
lines changed

5 files changed

+40
-8
lines changed

internal/pkg/cli/deploy/workload.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ func buildArgsPerContainer(name, workspacePath string, img ContainerImageIdentif
512512
CacheFrom: buildArgs.CacheFrom,
513513
Target: aws.StringValue(buildArgs.Target),
514514
Platform: mf.ContainerPlatform(),
515+
Engine: aws.StringValue(buildArgs.Engine),
515516
Tags: tags,
516517
Labels: labels,
517518
}

internal/pkg/docker/dockerengine/dockerengine.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ type BuildArguments struct {
6969
Platform string // Optional. OS/Arch to pass to `docker build`.
7070
Args map[string]string // Optional. Build args to pass via `--build-arg` flags. Equivalent to ARG directives in dockerfile.
7171
Labels map[string]string // Required. Set metadata for an image.
72+
Engine string // Optional. Currently supported options are "docker" and "podman". Defaults to "docker".
7273
}
7374

7475
// GenerateDockerBuildArgs returns command line arguments to be passed to the Docker build command based on the provided BuildArguments.
@@ -170,12 +171,22 @@ func (c DockerCmdClient) Login(uri, username, password string) error {
170171
}
171172

172173
// Push pushes the images with the specified tags and ecr repository URI, and returns the image digest on success.
173-
func (c DockerCmdClient) Push(ctx context.Context, uri string, w io.Writer, tags ...string) (digest string, err error) {
174+
func (c DockerCmdClient) Push(ctx context.Context, uri string, engine string, w io.Writer, tags ...string) (digest string, err error) {
174175
images := []string{}
175176
for _, tag := range tags {
176177
images = append(images, imageName(uri, tag))
177178
}
178179
var args []string
180+
// Podman image digests are based on the compressed image, so need to be gathered from podman.
181+
var digestFile *os.File
182+
if engine == "podman" {
183+
digestFile, err = os.CreateTemp("", "copilot-digest")
184+
if err != nil {
185+
return "", fmt.Errorf("create temp file for digest: %w", err)
186+
}
187+
defer os.Remove(digestFile.Name())
188+
args = append(args, "--digestfile", digestFile.Name())
189+
}
179190
if ci, _ := c.lookupEnv("CI"); ci == "true" {
180191
args = append(args, "--quiet")
181192
}
@@ -185,6 +196,14 @@ func (c DockerCmdClient) Push(ctx context.Context, uri string, w io.Writer, tags
185196
return "", fmt.Errorf("docker push %s: %w", img, err)
186197
}
187198
}
199+
if engine == "podman" {
200+
digest, err := os.ReadFile(digestFile.Name())
201+
if err != nil {
202+
return "", fmt.Errorf("read digest file: %w", err)
203+
}
204+
return string(digest), nil
205+
}
206+
188207
buf := new(strings.Builder)
189208
// The container image will have the same digest regardless of the associated tag.
190209
// Pick the first tag and get the image's digest.

internal/pkg/docker/dockerengine/dockerengine_test.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ func TestDockerCommand_Build(t *testing.T) {
4242
args map[string]string
4343
target string
4444
cacheFrom []string
45+
engine string
4546
envVars map[string]string
4647
labels map[string]string
4748
setupMocks func(controller *gomock.Controller)
@@ -302,7 +303,7 @@ func TestDockerCommand_Push(t *testing.T) {
302303
lookupEnv: emptyLookupEnv,
303304
}
304305
buf := new(strings.Builder)
305-
digest, err := cmd.Push(ctx, "aws_account_id.dkr.ecr.region.amazonaws.com/my-web-app", buf, "latest", "g123bfc")
306+
digest, err := cmd.Push(ctx, "aws_account_id.dkr.ecr.region.amazonaws.com/my-web-app", "docker", buf, "latest", "g123bfc")
306307

307308
// THEN
308309
require.NoError(t, err)
@@ -332,7 +333,7 @@ func TestDockerCommand_Push(t *testing.T) {
332333
},
333334
}
334335
buf := new(strings.Builder)
335-
digest, err := cmd.Push(context.Background(), "aws_account_id.dkr.ecr.region.amazonaws.com/my-web-app", buf, "latest")
336+
digest, err := cmd.Push(context.Background(), "aws_account_id.dkr.ecr.region.amazonaws.com/my-web-app", "docker", buf, "latest")
336337

337338
// THEN
338339
require.NoError(t, err)
@@ -351,7 +352,7 @@ func TestDockerCommand_Push(t *testing.T) {
351352
lookupEnv: emptyLookupEnv,
352353
}
353354
buf := new(strings.Builder)
354-
_, err := cmd.Push(ctx, "uri", buf, "latest")
355+
_, err := cmd.Push(ctx, "uri", "docker", buf, "latest")
355356

356357
// THEN
357358
require.EqualError(t, err, "docker push uri:latest: some error")
@@ -370,7 +371,7 @@ func TestDockerCommand_Push(t *testing.T) {
370371
lookupEnv: emptyLookupEnv,
371372
}
372373
buf := new(strings.Builder)
373-
_, err := cmd.Push(ctx, "uri", buf, "latest")
374+
_, err := cmd.Push(ctx, "uri", "docker", buf, "latest")
374375

375376
// THEN
376377
require.EqualError(t, err, "inspect image digest for uri: some error")
@@ -395,7 +396,7 @@ func TestDockerCommand_Push(t *testing.T) {
395396
lookupEnv: emptyLookupEnv,
396397
}
397398
buf := new(strings.Builder)
398-
_, err := cmd.Push(ctx, "aws_account_id.dkr.ecr.region.amazonaws.com/my-web-app", buf, "latest", "g123bfc")
399+
_, err := cmd.Push(ctx, "aws_account_id.dkr.ecr.region.amazonaws.com/my-web-app", "docker", buf, "latest", "g123bfc")
399400

400401
// THEN
401402
require.EqualError(t, err, "parse the digest from the repo digest ''")

internal/pkg/manifest/workload.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ func (i *ImageLocationOrBuild) BuildConfig(rootDirectory string) *DockerBuildArg
195195
Args: i.args(),
196196
Target: i.target(),
197197
CacheFrom: i.cacheFrom(),
198+
Engine: i.engine(),
198199
}
199200
}
200201

@@ -237,6 +238,14 @@ func (i *ImageLocationOrBuild) cacheFrom() []string {
237238
return i.Build.BuildArgs.CacheFrom
238239
}
239240

241+
// engine returns the engine to use for building the image if it exists, otherwise "docker"
242+
func (i *ImageLocationOrBuild) engine() *string {
243+
if i.Build.BuildArgs.Engine != nil {
244+
return i.Build.BuildArgs.Engine
245+
}
246+
return aws.String("docker")
247+
}
248+
240249
// ImageOverride holds fields that override Dockerfile image defaults.
241250
type ImageOverride struct {
242251
EntryPoint EntryPointOverride `yaml:"entrypoint"`
@@ -397,6 +406,7 @@ type DockerBuildArgs struct {
397406
Args map[string]string `yaml:"args,omitempty"`
398407
Target *string `yaml:"target,omitempty"`
399408
CacheFrom []string `yaml:"cache_from,omitempty"`
409+
Engine *string `yaml:"engine,omitempty"`
400410
}
401411

402412
func (b *DockerBuildArgs) isEmpty() bool {

internal/pkg/repository/repository.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import (
1818
type ContainerLoginBuildPusher interface {
1919
Build(ctx context.Context, args *dockerengine.BuildArguments, w io.Writer) error
2020
Login(uri, username, password string) error
21-
Push(ctx context.Context, uri string, w io.Writer, tags ...string) (digest string, err error)
21+
Push(ctx context.Context, uri string, engine string, w io.Writer, tags ...string) (digest string, err error)
2222
IsEcrCredentialHelperEnabled(uri string) bool
2323
}
2424

@@ -68,10 +68,11 @@ func (r *Repository) BuildAndPush(ctx context.Context, args *dockerengine.BuildA
6868
return "", fmt.Errorf("build Dockerfile at %s: %w", args.Dockerfile, err)
6969
}
7070

71-
digest, err = r.docker.Push(ctx, args.URI, w, args.Tags...)
71+
digest, err = r.docker.Push(ctx, args.URI, args.Engine, w, args.Tags...)
7272
if err != nil {
7373
return "", fmt.Errorf("push to repo %s: %w", r.name, err)
7474
}
75+
7576
return digest, nil
7677
}
7778

0 commit comments

Comments
 (0)