Skip to content

Commit 1f93eab

Browse files
authored
Merge pull request linuxkit#3600 from deitch/build-target
build images to cache with buildx
2 parents 4cdf6bc + 9633d23 commit 1f93eab

File tree

178 files changed

+2787
-379
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

178 files changed

+2787
-379
lines changed

docs/packages.md

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ We do not want the builds to happen with each CI run for two reasons:
2323
1. It is slower to do a package build than to just pull the latest image.
2424
2. If any of the steps of the build fails, e.g. a `curl` download that depends on an intermittent target, it can cause all of CI to fail.
2525

26-
Thus, if, as a maintainer, you merge any commits into a `pkg/`, even if the change is documentation alone, please do a `linuxkit package push`.
26+
Thus, if, as a maintainer, you merge any commits into a `pkg/`, even if the change is documentation alone, please do a `linuxkit pkg push`.
2727

2828

2929
## Package source
@@ -54,8 +54,8 @@ A package source consists of a directory containing at least two files:
5454
### Prerequisites
5555

5656
Before you can build packages you need:
57-
- Docker version 17.06 or newer. If you are on a Mac you also need
58-
`docker-credential-osxkeychain.bin`, which comes with Docker for Mac.
57+
- Docker version 19.03 or newer, which includes [buildx](https://docs.docker.com/buildx/working-with-buildx/)
58+
- If you are on a Mac you also need `docker-credential-osxkeychain.bin`, which comes with Docker for Mac.
5959
- `make`, `notary`, `base64`, `jq`, and `expect`
6060
- A *recent* version of `manifest-tool` which you can build with `make
6161
bin/manifest-tool`, or `go get github.com:estesp/manifest-tool`, or
@@ -67,6 +67,35 @@ Further, when building packages you need to be logged into hub with
6767
`docker login` as some of the tooling extracts your hub credentials
6868
during the build.
6969

70+
### Build Targets
71+
72+
LinuxKit builds packages as docker images. It deposits the built package as a docker image in one of two targets:
73+
74+
* the linuxkit cache `~/.linuxkit/` (configurable) - default option
75+
* the docker image cache
76+
77+
If you want to build images and test and run them _in a standalone_ fashion locally, then you should pick the docker image cache. Otherwise, you should use the default linuxkit cache. LinuxKit defaults to building OS images using docker images from this cache,\
78+
only looking in the docker cache if instructed to via `linuxkit build --docker`.
79+
80+
When using the linuxkit cache as the package build target, it creates all of the layers, the manifest that can be uploaded
81+
to a registry, and the multi-architecture index. If an image already exists for a different architecture in the cache,
82+
it updates the index to include additional manifests created.
83+
84+
As of this writing, `linuxkit pkg build` only builds packages for the platform on which it is running; it does not (yet) support cross-building the packages for other architectures.
85+
86+
Note that the local docker option is available _only_ when building without pushing to a remote registry, i.e.:
87+
88+
```
89+
linuxkit pkg build
90+
linuxkit pkg build --docker
91+
```
92+
93+
If you push to a registry, it _always_ uses the linuxkit cache only:
94+
95+
```
96+
linuxkit pkg push
97+
```
98+
7099
### Build packages as a maintainer
71100

72101
If you have write access to the `linuxkit` organisation on hub, you

src/cmd/linuxkit/cache/find.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,25 @@ func findImage(p layout.Path, imageName, architecture string) (v1.Image, error)
4848
}
4949
return nil, fmt.Errorf("no image found for %s", imageName)
5050
}
51+
52+
// FindDescriptor get the first descriptor pointed to by the image name
53+
func FindDescriptor(dir string, name string) (*v1.Descriptor, error) {
54+
p, err := Get(dir)
55+
if err != nil {
56+
return nil, err
57+
}
58+
index, err := p.ImageIndex()
59+
// if there is no root index, we are broken
60+
if err != nil {
61+
return nil, fmt.Errorf("invalid image cache: %v", err)
62+
}
63+
64+
descs, err := partial.FindManifests(index, match.Name(name))
65+
if err != nil {
66+
return nil, err
67+
}
68+
if len(descs) < 1 {
69+
return nil, nil
70+
}
71+
return &descs[0], nil
72+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package cache
2+
3+
import (
4+
"io"
5+
)
6+
7+
type nopCloserWriter struct {
8+
writer io.Writer
9+
}
10+
11+
func (n nopCloserWriter) Write(b []byte) (int, error) {
12+
return n.writer.Write(b)
13+
}
14+
15+
func (n nopCloserWriter) Close() error {
16+
return nil
17+
}
18+
19+
// NopCloserWriter wrap an io.Writer with a no-op Closer
20+
func NopCloserWriter(writer io.Writer) io.WriteCloser {
21+
return nopCloserWriter{writer}
22+
}

src/cmd/linuxkit/cache/pull.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/containerd/containerd/reference"
77
"github.com/google/go-containerregistry/pkg/v1"
8+
"github.com/google/go-containerregistry/pkg/v1/partial"
89
"github.com/google/go-containerregistry/pkg/v1/validate"
910
)
1011

@@ -15,17 +16,24 @@ func ValidateImage(ref *reference.Spec, cacheDir, architecture string) (ImageSou
1516
imageIndex v1.ImageIndex
1617
image v1.Image
1718
imageName = ref.String()
19+
desc *v1.Descriptor
1820
)
1921
// next try the local cache
2022
root, err := FindRoot(cacheDir, imageName)
2123
if err == nil {
2224
img, err := root.Image()
2325
if err == nil {
2426
image = img
27+
if desc, err = partial.Descriptor(img); err != nil {
28+
return ImageSource{}, errors.New("image could not create valid descriptor")
29+
}
2530
} else {
2631
ii, err := root.ImageIndex()
2732
if err == nil {
2833
imageIndex = ii
34+
if desc, err = partial.Descriptor(ii); err != nil {
35+
return ImageSource{}, errors.New("index could not create valid descriptor")
36+
}
2937
}
3038
}
3139
}
@@ -45,6 +53,7 @@ func ValidateImage(ref *reference.Spec, cacheDir, architecture string) (ImageSou
4553
ref,
4654
cacheDir,
4755
architecture,
56+
desc,
4857
), nil
4958
}
5059
return ImageSource{}, errors.New("invalid index")
@@ -55,6 +64,7 @@ func ValidateImage(ref *reference.Spec, cacheDir, architecture string) (ImageSou
5564
ref,
5665
cacheDir,
5766
architecture,
67+
desc,
5868
), nil
5969
}
6070
return ImageSource{}, errors.New("invalid image")

src/cmd/linuxkit/cache/push.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package cache
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/google/go-containerregistry/pkg/authn"
7+
namepkg "github.com/google/go-containerregistry/pkg/name"
8+
"github.com/google/go-containerregistry/pkg/v1/remote"
9+
"github.com/linuxkit/linuxkit/src/cmd/linuxkit/registry"
10+
)
11+
12+
// PushWithManifest push an image along with, optionally, a multi-arch index.
13+
func PushWithManifest(dir string, name, suffix string, pushImage, pushManifest, trust, sign bool) error {
14+
var (
15+
digest string
16+
l int
17+
err error
18+
options []remote.Option
19+
)
20+
p, err := Get(dir)
21+
if err != nil {
22+
return err
23+
}
24+
25+
imageName := name + suffix
26+
ref, err := namepkg.ParseReference(imageName)
27+
if err != nil {
28+
return err
29+
}
30+
31+
if pushImage {
32+
fmt.Printf("Pushing %s\n", imageName)
33+
// do we even have the given one?
34+
root, err := findRootFromLayout(p, imageName)
35+
if err != nil {
36+
return err
37+
}
38+
options = append(options, remote.WithAuthFromKeychain(authn.DefaultKeychain))
39+
img, err1 := root.Image()
40+
ii, err2 := root.ImageIndex()
41+
switch {
42+
case err1 == nil:
43+
if err := remote.Write(ref, img, options...); err != nil {
44+
return err
45+
}
46+
fmt.Printf("Pushed image %s\n", imageName)
47+
case err2 == nil:
48+
if err := remote.WriteIndex(ref, ii, options...); err != nil {
49+
return err
50+
}
51+
fmt.Printf("Pushed index %s\n", imageName)
52+
default:
53+
return fmt.Errorf("name %s unknown in cache", imageName)
54+
}
55+
} else {
56+
fmt.Print("Image push disabled, skipping...\n")
57+
}
58+
59+
auth, err := registry.GetDockerAuth()
60+
if err != nil {
61+
return fmt.Errorf("failed to get auth: %v", err)
62+
}
63+
64+
if pushManifest {
65+
fmt.Printf("Pushing %s to manifest %s\n", imageName, name)
66+
digest, l, err = registry.PushManifest(imageName, auth)
67+
if err != nil {
68+
return err
69+
}
70+
} else {
71+
fmt.Print("Manifest push disabled, skipping...\n")
72+
}
73+
74+
// if trust is not enabled, nothing more to do
75+
if !trust {
76+
fmt.Println("trust disabled, not signing")
77+
return nil
78+
}
79+
if !sign {
80+
fmt.Println("signing disabled, not signing")
81+
return nil
82+
}
83+
fmt.Printf("Signing manifest for %s\n", imageName)
84+
return registry.SignTag(name, digest, l, auth)
85+
}

src/cmd/linuxkit/cache/source.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"io"
77

88
"github.com/containerd/containerd/reference"
9+
"github.com/google/go-containerregistry/pkg/v1"
910
"github.com/google/go-containerregistry/pkg/v1/layout"
1011
"github.com/google/go-containerregistry/pkg/v1/mutate"
1112
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
@@ -17,16 +18,18 @@ type ImageSource struct {
1718
ref *reference.Spec
1819
cache layout.Path
1920
architecture string
21+
descriptor *v1.Descriptor
2022
}
2123

2224
// NewSource return an ImageSource for a specific ref and architecture in the given
2325
// cache directory.
24-
func NewSource(ref *reference.Spec, dir string, architecture string) ImageSource {
26+
func NewSource(ref *reference.Spec, dir string, architecture string, descriptor *v1.Descriptor) ImageSource {
2527
p, _ := Get(dir)
2628
return ImageSource{
2729
ref: ref,
2830
cache: p,
2931
architecture: architecture,
32+
descriptor: descriptor,
3033
}
3134
}
3235

@@ -67,3 +70,8 @@ func (c ImageSource) TarReader() (io.ReadCloser, error) {
6770

6871
return mutate.Extract(image), nil
6972
}
73+
74+
// Descriptor return the descriptor of the image.
75+
func (c ImageSource) Descriptor() *v1.Descriptor {
76+
return c.descriptor
77+
}

0 commit comments

Comments
 (0)