mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-23 11:00:25 +00:00
Merge pull request #3804 from giggsoff/allow-docker-multiarch
Allow store to docker multiarch builds
This commit is contained in:
commit
4e7f87e1ea
@ -191,20 +191,6 @@ func (p Pkg) Build(bos ...BuildOpt) error {
|
|||||||
return errors.New("must provide linuxkit build cache directory")
|
return errors.New("must provide linuxkit build cache directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
// if targeting docker, be sure local arch is a build target
|
|
||||||
if bo.targetDocker {
|
|
||||||
var found bool
|
|
||||||
for _, platform := range bo.platforms {
|
|
||||||
if platform.Architecture == arch {
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
return fmt.Errorf("must build for local platform 'linux/%s' when targeting docker", arch)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.git != nil && bo.push && bo.release == "" {
|
if p.git != nil && bo.push && bo.release == "" {
|
||||||
r, err := p.git.commitTag("HEAD")
|
r, err := p.git.commitTag("HEAD")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -243,6 +229,24 @@ func (p Pkg) Build(bos ...BuildOpt) error {
|
|||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(writer, "%s not found\n", ref)
|
fmt.Fprintf(writer, "%s not found\n", ref)
|
||||||
}
|
}
|
||||||
|
if bo.targetDocker {
|
||||||
|
notFound := false
|
||||||
|
for _, platform := range bo.platforms {
|
||||||
|
archRef, err := reference.Parse(fmt.Sprintf("%s-%s", p.FullTag(), platform.Architecture))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(writer, "checking for %s in local cache, fallback to remote registry...\n", archRef)
|
||||||
|
if _, err := c.ImagePull(&archRef, "", platform.Architecture, false); err == nil {
|
||||||
|
fmt.Fprintf(writer, "%s found or pulled\n", archRef)
|
||||||
|
skipBuild = true
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(writer, "%s not found\n", archRef)
|
||||||
|
notFound = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
skipBuild = skipBuild && !notFound
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !skipBuild {
|
if !skipBuild {
|
||||||
@ -327,14 +331,28 @@ func (p Pkg) Build(bos ...BuildOpt) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if requested docker, load the image up
|
// if requested docker, load the image up
|
||||||
|
// we will store images with arch suffix, i.e. -amd64
|
||||||
|
// if one of the arch equals with system, we will add tag without suffix
|
||||||
if bo.targetDocker {
|
if bo.targetDocker {
|
||||||
cacheSource := c.NewSource(&ref, arch, desc)
|
for _, platform := range bo.platforms {
|
||||||
reader, err := cacheSource.V1TarReader()
|
archRef, err := reference.Parse(fmt.Sprintf("%s-%s", p.FullTag(), platform.Architecture))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to get reader from cache: %v", err)
|
return err
|
||||||
}
|
}
|
||||||
if err := d.load(reader); err != nil {
|
cacheSource := c.NewSource(&archRef, platform.Architecture, desc)
|
||||||
return err
|
reader, err := cacheSource.V1TarReader()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to get reader from cache: %v", err)
|
||||||
|
}
|
||||||
|
if err := d.load(reader); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if platform.Architecture == arch {
|
||||||
|
err = d.tag(fmt.Sprintf("%s-%s", p.FullTag(), platform.Architecture), p.FullTag())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,9 +393,18 @@ func (p Pkg) Build(bos ...BuildOpt) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// tag in docker, if requested
|
// tag in docker, if requested
|
||||||
|
// will tag all images with arch suffix
|
||||||
|
// if one of the arch equals with system will add tag without suffix
|
||||||
if bo.targetDocker {
|
if bo.targetDocker {
|
||||||
if err := d.tag(p.FullTag(), fullRelTag); err != nil {
|
for _, platform := range bo.platforms {
|
||||||
return err
|
if err := d.tag(fmt.Sprintf("%s-%s", p.FullTag(), platform.Architecture), fmt.Sprintf("%s-%s", fullRelTag, platform.Architecture)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if platform.Architecture == arch {
|
||||||
|
if err := d.tag(fmt.Sprintf("%s-%s", p.FullTag(), platform.Architecture), fullRelTag); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -116,7 +115,7 @@ func (c *cacheMocker) ImageLoad(ref *reference.Spec, architecture string, r io.R
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *cacheMocker) imageWriteStream(ref *reference.Spec, architecture string, r io.Reader) (lktspec.ImageSource, error) {
|
func (c *cacheMocker) imageWriteStream(ref *reference.Spec, architecture string, r io.Reader) (lktspec.ImageSource, error) {
|
||||||
image := ref.String()
|
image := fmt.Sprintf("%s-%s", ref.String(), architecture)
|
||||||
|
|
||||||
// make some random data for a layer
|
// make some random data for a layer
|
||||||
b, err := ioutil.ReadAll(r)
|
b, err := ioutil.ReadAll(r)
|
||||||
@ -154,10 +153,14 @@ func (c *cacheMocker) imageWriteStream(ref *reference.Spec, architecture string,
|
|||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
imagespec.AnnotationRefName: image,
|
imagespec.AnnotationRefName: image,
|
||||||
},
|
},
|
||||||
|
Platform: ®istry.Platform{
|
||||||
|
OS: "linux",
|
||||||
|
Architecture: architecture,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
c.appendImage(image, desc)
|
c.appendImage(image, desc)
|
||||||
|
|
||||||
return c.NewSource(ref, "", &desc), nil
|
return c.NewSource(ref, architecture, &desc), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cacheMocker) IndexWrite(ref *reference.Spec, descriptors ...registry.Descriptor) (lktspec.ImageSource, error) {
|
func (c *cacheMocker) IndexWrite(ref *reference.Spec, descriptors ...registry.Descriptor) (lktspec.ImageSource, error) {
|
||||||
@ -273,7 +276,13 @@ func (c cacheMockerSource) TarReader() (io.ReadCloser, error) {
|
|||||||
return nil, errors.New("unsupported")
|
return nil, errors.New("unsupported")
|
||||||
}
|
}
|
||||||
func (c cacheMockerSource) V1TarReader() (io.ReadCloser, error) {
|
func (c cacheMockerSource) V1TarReader() (io.ReadCloser, error) {
|
||||||
return nil, errors.New("unsupported")
|
_, found := c.c.images[c.ref.String()]
|
||||||
|
if !found {
|
||||||
|
return nil, fmt.Errorf("no image found with ref: %s", c.ref.String())
|
||||||
|
}
|
||||||
|
b := make([]byte, 256)
|
||||||
|
rand.Read(b)
|
||||||
|
return io.NopCloser(bytes.NewReader(b)), nil
|
||||||
}
|
}
|
||||||
func (c cacheMockerSource) Descriptor() *registry.Descriptor {
|
func (c cacheMockerSource) Descriptor() *registry.Descriptor {
|
||||||
return c.descriptor
|
return c.descriptor
|
||||||
@ -281,14 +290,8 @@ func (c cacheMockerSource) Descriptor() *registry.Descriptor {
|
|||||||
|
|
||||||
func TestBuild(t *testing.T) {
|
func TestBuild(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
nonLocal string
|
|
||||||
cacheDir = "somecachedir"
|
cacheDir = "somecachedir"
|
||||||
)
|
)
|
||||||
if runtime.GOARCH == "amd64" {
|
|
||||||
nonLocal = "arm64"
|
|
||||||
} else {
|
|
||||||
nonLocal = "amd64"
|
|
||||||
}
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
msg string
|
msg string
|
||||||
p Pkg
|
p Pkg
|
||||||
@ -302,7 +305,7 @@ func TestBuild(t *testing.T) {
|
|||||||
{"not at head", Pkg{org: "foo", image: "bar", hash: "abc", arches: []string{"amd64"}, commitHash: "foo"}, nil, []string{"amd64"}, &dockerMocker{supportContexts: false}, &cacheMocker{}, "Cannot build from commit hash != HEAD"},
|
{"not at head", Pkg{org: "foo", image: "bar", hash: "abc", arches: []string{"amd64"}, commitHash: "foo"}, nil, []string{"amd64"}, &dockerMocker{supportContexts: false}, &cacheMocker{}, "Cannot build from commit hash != HEAD"},
|
||||||
{"no build cache", Pkg{org: "foo", image: "bar", hash: "abc", arches: []string{"amd64"}, commitHash: "HEAD"}, nil, []string{"amd64"}, &dockerMocker{supportContexts: false}, &cacheMocker{}, "must provide linuxkit build cache"},
|
{"no build cache", Pkg{org: "foo", image: "bar", hash: "abc", arches: []string{"amd64"}, commitHash: "HEAD"}, nil, []string{"amd64"}, &dockerMocker{supportContexts: false}, &cacheMocker{}, "must provide linuxkit build cache"},
|
||||||
{"unsupported contexts", Pkg{org: "foo", image: "bar", hash: "abc", arches: []string{"amd64"}, commitHash: "HEAD"}, []BuildOpt{WithBuildCacheDir(cacheDir)}, []string{"amd64"}, &dockerMocker{supportContexts: false}, &cacheMocker{}, "contexts not supported, check docker version"},
|
{"unsupported contexts", Pkg{org: "foo", image: "bar", hash: "abc", arches: []string{"amd64"}, commitHash: "HEAD"}, []BuildOpt{WithBuildCacheDir(cacheDir)}, []string{"amd64"}, &dockerMocker{supportContexts: false}, &cacheMocker{}, "contexts not supported, check docker version"},
|
||||||
{"load docker without local platform", Pkg{org: "foo", image: "bar", hash: "abc", arches: []string{"amd64", "arm64"}, commitHash: "HEAD"}, []BuildOpt{WithBuildCacheDir(cacheDir), WithBuildTargetDockerCache()}, []string{nonLocal}, &dockerMocker{supportContexts: false}, &cacheMocker{}, "must build for local platform"},
|
{"load docker without local platform", Pkg{org: "foo", image: "bar", hash: "abc", arches: []string{"amd64", "arm64"}, commitHash: "HEAD"}, []BuildOpt{WithBuildCacheDir(cacheDir), WithBuildTargetDockerCache()}, []string{"amd64", "arm64"}, &dockerMocker{supportContexts: true, enableBuild: true, images: map[string][]byte{}, enableTag: true}, &cacheMocker{enableImagePull: false, enableImageLoad: true, enableIndexWrite: true}, ""},
|
||||||
{"amd64", Pkg{org: "foo", image: "bar", hash: "abc", arches: []string{"amd64", "arm64"}, commitHash: "HEAD"}, []BuildOpt{WithBuildCacheDir(cacheDir)}, []string{"amd64"}, &dockerMocker{supportContexts: true, enableBuild: true}, &cacheMocker{enableImagePull: false, enableImageLoad: true, enableIndexWrite: true}, ""},
|
{"amd64", Pkg{org: "foo", image: "bar", hash: "abc", arches: []string{"amd64", "arm64"}, commitHash: "HEAD"}, []BuildOpt{WithBuildCacheDir(cacheDir)}, []string{"amd64"}, &dockerMocker{supportContexts: true, enableBuild: true}, &cacheMocker{enableImagePull: false, enableImageLoad: true, enableIndexWrite: true}, ""},
|
||||||
{"arm64", Pkg{org: "foo", image: "bar", hash: "abc", arches: []string{"amd64", "arm64"}, commitHash: "HEAD"}, []BuildOpt{WithBuildCacheDir(cacheDir)}, []string{"arm64"}, &dockerMocker{supportContexts: true, enableBuild: true}, &cacheMocker{enableImagePull: false, enableImageLoad: true, enableIndexWrite: true}, ""},
|
{"arm64", Pkg{org: "foo", image: "bar", hash: "abc", arches: []string{"amd64", "arm64"}, commitHash: "HEAD"}, []BuildOpt{WithBuildCacheDir(cacheDir)}, []string{"arm64"}, &dockerMocker{supportContexts: true, enableBuild: true}, &cacheMocker{enableImagePull: false, enableImageLoad: true, enableIndexWrite: true}, ""},
|
||||||
{"amd64 and arm64", Pkg{org: "foo", image: "bar", hash: "abc", arches: []string{"amd64", "arm64"}, commitHash: "HEAD"}, []BuildOpt{WithBuildCacheDir(cacheDir)}, []string{"amd64", "arm64"}, &dockerMocker{supportContexts: true, enableBuild: true}, &cacheMocker{enableImagePull: false, enableImageLoad: true, enableIndexWrite: true}, ""},
|
{"amd64 and arm64", Pkg{org: "foo", image: "bar", hash: "abc", arches: []string{"amd64", "arm64"}, commitHash: "HEAD"}, []BuildOpt{WithBuildCacheDir(cacheDir)}, []string{"amd64", "arm64"}, &dockerMocker{supportContexts: true, enableBuild: true}, &cacheMocker{enableImagePull: false, enableImageLoad: true, enableIndexWrite: true}, ""},
|
||||||
|
@ -288,7 +288,7 @@ func (dr *dockerRunnerImpl) builderEnsureContainer(ctx context.Context, name, im
|
|||||||
}
|
}
|
||||||
// create the builder
|
// create the builder
|
||||||
args := []string{"container", "run", "-d", "--name", name, "--privileged", image, "--allow-insecure-entitlement", "network.host", "--addr", fmt.Sprintf("unix://%s", buildkitSocketPath), "--debug"}
|
args := []string{"container", "run", "-d", "--name", name, "--privileged", image, "--allow-insecure-entitlement", "network.host", "--addr", fmt.Sprintf("unix://%s", buildkitSocketPath), "--debug"}
|
||||||
msg := fmt.Sprintf("creating builder container '%s' in context '%s", name, dockerContext)
|
msg := fmt.Sprintf("creating builder container '%s' in context '%s'", name, dockerContext)
|
||||||
fmt.Println(msg)
|
fmt.Println(msg)
|
||||||
if err := dr.command(nil, ioutil.Discard, ioutil.Discard, args...); err != nil {
|
if err := dr.command(nil, ioutil.Discard, ioutil.Discard, args...); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
Loading…
Reference in New Issue
Block a user