Skip to content

Commit

Permalink
pull: resolve the image config and set it on stored image (genuinetoo…
Browse files Browse the repository at this point in the history
…ls#326)

Previously `pull` would not properly retain the image configuration
which contains the entrypoint, working directory, user, and more. This
resulted in broken images if they were pulled then subsequently pushed.

This commit fetches the image config, which must be done separately, and
then ensures that the configuration is set on the exported image into
the local img state store.
  • Loading branch information
mitchellh authored Feb 12, 2021
1 parent 132b56c commit 3667c6a
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 1 deletion.
27 changes: 26 additions & 1 deletion client/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ import (
"github.com/moby/buildkit/cache"
"github.com/moby/buildkit/exporter"
imageexporter "github.com/moby/buildkit/exporter/containerimage"
"github.com/moby/buildkit/exporter/containerimage/exptypes"
"github.com/moby/buildkit/source"
"github.com/moby/buildkit/source/containerimage"
"github.com/moby/buildkit/util/imageutil"
"github.com/moby/buildkit/util/pull"
)

// Pull retrieves an image from a remote registry.
Expand Down Expand Up @@ -66,6 +69,22 @@ func (c *Client) Pull(ctx context.Context, image string) (*ListedImage, error) {
if err != nil {
return nil, err
}

// Fetch the configuration for the image. src.Resolve below fetches
// all the data layers but does NOT fetch the configuration. We need this
// to set it for export later.
_, configBytes, err := imageutil.Config(
ctx,
image,
pull.NewResolver(ctx, opt.RegistryHosts, sm, opt.ImageStore, source.ResolveModeDefault, image),
opt.ContentStore,
opt.LeaseManager,
nil,
)
if err != nil {
return nil, err
}

s, err := src.Resolve(ctx, identifier, sm)
if err != nil {
return nil, err
Expand Down Expand Up @@ -99,7 +118,13 @@ func (c *Client) Pull(ctx context.Context, image string) (*ListedImage, error) {
if err != nil {
return nil, err
}
if _, err := e.Export(ctx, exporter.Source{Ref: ref}); err != nil {
if _, err := e.Export(ctx, exporter.Source{
Ref: ref,
Metadata: map[string][]byte{
// This sets the image config to preserve entrypoint, workingdir, etc.
exptypes.ExporterImageConfigKey: configBytes,
},
}); err != nil {
return nil, err
}

Expand Down
19 changes: 19 additions & 0 deletions pull_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package main

import (
"encoding/json"
"strings"
"testing"

ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)

func TestPullFromDefaultRegistry(t *testing.T) {
Expand All @@ -29,3 +32,19 @@ func TestPullIsInListOutput(t *testing.T) {
t.Fatalf("expected busybox:latest in ls output, got: %s", out)
}
}

func TestPullRetainsConfig(t *testing.T) {
// Test an official image,
run(t, "pull", "alpine")

out := run(t, "inspect", "alpine")

var image ocispec.Image
if err := json.Unmarshal([]byte(out), &image); err != nil {
t.Fatalf("error decoding JSON: %s", err)
}

if len(image.Config.Cmd) == 0 {
t.Fatal("image config should be populated")
}
}

0 comments on commit 3667c6a

Please sign in to comment.