-
Notifications
You must be signed in to change notification settings - Fork 1k
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
tools: multi-arch support for the base alpine image #2244
Conversation
@justincormack @rn This RP is a key step for us to support ARM64 with LinuxKit mainline code. After that I will clone a brand new LinuxKit repos into different ARM64 platforms to test if we still have some gap to do that. Thanks! |
tools/alpine/.detect-arch-var
Outdated
@@ -0,0 +1,13 @@ | |||
#!/usr/bin/env bash |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please use sh
not bash
. Also having hidden files is kind of annoying, just use a normal one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. I will wrap up all the changes and make a re-push
I think there is a much simpler solution with a single
|
(this would also allow us to override the base image for any architecture, which could be useful for testing alpine |
Ah, cool! let me try that, we can use only one Dockerfile if that works. My docker version is: Server: |
That should be new enough. We are fine with requiring developers to have newest docker versions, we dd that before for multi stage builds too. |
@justincormack yes, it works. So that means we can use one Dockerfile. Now have another issue: |
I think the easiest thing to do is something like:
|
Good point! |
I think move those into |
like this? COPY packages* /tmp/ RUN cat /tmp/packages.$(uname -m) >> /tmp/packages && |
yes thats what I was thinking. |
OK, I will wrap up those changes and re-push it again. Thanks for the good suggestion! |
d9491a6
to
7c121e1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for tackling this. I few more comments/suggestions but overall the shape looks good
tools/alpine/Makefile
Outdated
@@ -2,22 +2,24 @@ | |||
|
|||
ORG?=linuxkit | |||
IMAGE=alpine | |||
BASE=alpine:3.6 | |||
|
|||
BASE := $(shell bash -c 'source detect-arch-var && echo $${BASE}') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we not use bash here and in the next?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very good suggestion. I will drop the 'detect-arch-var' file and transfer its operation into Makefile, so I promise 'bash' will not show again ;-)
tools/alpine/Makefile
Outdated
|
||
default: push | ||
|
||
show-tag: | ||
@sed -n -e '1s/# \(.*\/.*:[0-9a-f]\{40\}\)/\1/p;q' versions | ||
|
||
hash: Dockerfile Makefile packages | ||
DOCKER_CONTENT_TRUST=1 docker pull $(BASE) | ||
docker build --no-cache -t $(IMAGE):build . | ||
DOCKER_CONTENT_TRUST=$(DOCKER_CONT) docker pull $(BASE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be better to copy the pattern used in pkg/package.mk
for setting the content trust.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course. Actually I do think that's will be very elegant, at least looks like - as we'll move all the jobs in 'detect-*" into Makefile.
tools/alpine/detect-arch-var
Outdated
@@ -0,0 +1,11 @@ | |||
#!/usr/bin/env sh |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't this be moved into the Makefile, ie set a makefile variables for uname -m
and then set other makefile variables based off that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, of course! But interesting, for the 'ARG' and ‘FROM’ feature supported by the newer version of Docker, seems there's a potential bug for the DOCKER_CONTENT_TRUST setting:
$export DOCKER_CONTENT_TRUST=1
$docker build --no-cache --build-arg BASE=alpine:3.6 -t alpine:build .
You will get below message:
Sending build context to Docker daemon
error during connect: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.31/build?buildargs=%7B%22BASE%22%3A%22alpine%3A3.6%22%7D&cachefrom=%5B%5D&cgroupparent=&cpuperiod=0&cpuquota=0&cpusetcpus=&cpusetmems=&cpushares=0&dockerfile=Dockerfile&labels=%7B%7D&memory=0&memswap=0&networkmode=default&nocache=1&rm=1&shmsize=0&t=alpine%3Abuild&target=&ulimits=null: invalid reference format: repository name must be lowercase
@justincormack @rn please help double check this, if it's done, my PR will be ready quickly to push...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, yes I filed an issue https://github.com/moby/moby/issues/34199 will try to get it fixed ASAP.
As a temporary workaround, you could omit setting DOCKER_CONTENT_TRUST
on the build step if the build arg is set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great! I will set the DOCKER_CONTENT_TRUST=0 as default in my PR, it will be easy to be tuned once this issue fixed.
7c121e1
to
5bf86e6
Compare
@justincormack @rn The gun is ready to shoot... ;-) |
tools/alpine/Makefile
Outdated
DOCKER_CONTENT_TRUST=1 docker pull $(BASE) | ||
docker build --no-cache -t $(IMAGE):build . | ||
hash: Dockerfile Makefile $(PKG_DEPS) | ||
docker pull $(BASE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can keep the DOCKER_CONTENT_TRUST=1
here (unless the arm64v8 packages are not signed, in which case it needs to be conditional; it was only haveing it set on docker build
that causes issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, ok, the arm64 images are not signed, so I think you can just set NOTRUST
for the arm64 case. But you must not disable for the x86_64 case. This Makefile does not set content trust for build as it already does a trusted pull, so should not run into the bug.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@riyazdf can probably help work out the best arrangement (I am on a train today)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed with @justincormack that we must keep x86_64 trust checking intact.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps we can export DOCKER_CONTENT_TRUST=1
for this Makefile and set NOTRUST
in the arm conditional where we override BASE
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@justincormack @riyazdf
Ah, thanks for the remind! I totally agree with that we need to keep x86_64 trust checking intact, I am missing that. So now I made below changes:
DOCKER_CONTENT_VAR=1
PKG_DEPS=packages
ifeq ($(shell uname -m), x86_64)
BASE=alpine:3.6
PKG_DEPS += packages.x86_64
endif
ifeq ($(shell uname -m), aarch64)
BASE=arm64v8/alpine:3.6
PKG_DEPS += packages.aarch64
DOCKER_CONTENT_VAR=0
endif
default: push
show-tag:
@sed -n -e '1s/# \(.*\/.*:[0-9a-f]\{40\}\)/\1/p;q' versions
hash: Dockerfile Makefile $(PKG_DEPS)
DOCKER_CONTENT_TRUST=$(DOCKER_CONTENT_VAR) docker pull $(BASE)
docker build --no-cache --build-arg BASE=$(BASE) -t $(IMAGE):build .
docker run --rm $(IMAGE):build sh -c 'echo Dockerfile /lib/apk/db/installed $$(find /mirror -name '*.apk' -type f) $$(find /go/bin -type f) | xargs cat | sha1sum' | sed 's/ .*//' >
$@
push: hash
DOCKER_CONTENT_TRUST=$(DOCKER_CONTENT_VAR) docker pull $(ORG)/$(IMAGE):$(shell cat hash) || \
(docker tag $(IMAGE):build $(ORG)/$(IMAGE):$(shell cat hash) && \
DOCKER_CONTENT_TRUST=$(DOCKER_CONTENT_VAR) docker push $(ORG)/$(IMAGE):$(shell cat hash))
For x86_64, it willkeep the same behavior as it does before, for aarch64, the DOCKER_CONTENT_TRUST will be overrided. Does that make sense?
5bf86e6
to
79bcfb2
Compare
would you pls help to review the latest update? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@arm64b I think you also need to have a per arch versions file as that get's checked in and the versions may differ on the architectures.
@@ -25,7 +27,10 @@ RUN cp /mirror/$(uname -m)/APKINDEX.unsigned.tar.gz /mirror/$(uname -m)/APKINDEX | |||
RUN abuild-sign /mirror/$(uname -m)/APKINDEX.tar.gz | |||
|
|||
# fetch OVMF for qemu EFI boot (this is not added as a package) | |||
RUN apk add -X http://dl-cdn.alpinelinux.org/alpine/edge/community ovmf | |||
RUN mkdir -p /usr/share/ovmf && \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be added the same way the wireguard tools were added a yesterday. The way this is currently added (and was in the past) does not record the version number in the versions
file. I know it's not related directly to your PR, so maybe should be addressed separately as it also has implications elsewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am trying to generate a per-arch version file, will double check if the ovmf pkg has been recorded in that file like version.x86_64.
tools/alpine/Makefile
Outdated
(docker tag $(IMAGE):build $(ORG)/$(IMAGE):$(shell cat hash) && \ | ||
DOCKER_CONTENT_TRUST=1 docker push $(ORG)/$(IMAGE):$(shell cat hash)) | ||
DOCKER_CONTENT_TRUST=$(DOCKER_CONTENT_VAR) docker push $(ORG)/$(IMAGE):$(shell cat hash)) | ||
echo "# $(ORG)/$(IMAGE):$(shell cat hash)" > versions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the versions
file probably needs to be per arch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not very sure about the exact usage purpose of this file, if it really needs to generate a per arch, then we can do like this:
... > versions.$(shell uname -m)
But IMO, if you work on a platform, no matter amd64 or arm64, it's easy for you to know that the version file is the list of packages installed for that platform.
I am OK for both.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is checked in and is expected to contain the exact versions present in the image hash in the header. Given that this package is built with network access it might be quite hard to ensure that there is no skew due to arches being built at different times (or even atthe same time if there is skew in the upstream alpine repo).
IMHO it would be best to find a way to build a single arch agnostic base mirror image with a multiarch mirrror in it, but for now I think per arch version files are the minimum we need.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I am making the per-arch version file building test, will generate versions.x86_64 on x86_64 platform, versions.aarch64 on AArch64.
79bcfb2
to
9f3890f
Compare
@rn @justincormack @ijc @riyazdf |
BASE=arm64v8/alpine:3.6 | ||
PKG_DEPS += packages.aarch64 | ||
DOCKER_CONTENT_VAR=0 | ||
endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I lost track of this part, but is there a reason, this is not following the pattern we have elsewhere (pkg/package.mk
) and simply just sets NOTRUST
when on arm?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason is, if we export DOCKER_CONTENT_TRUST=1 for x86, then we will encounter the issue filed by https://github.com/moby/moby/issues/34199 no matter we use:
$docker build --no-cache --build-arg BASE=alpine:3.6 -t alpine:build .
or
$docker build --no-cache -t alpine:build .
That's why we still use the original Makefile content trust mode when building the image.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for reminding me
Needs a rebase (versions changed). |
Will wrap up and edit the commit message in the 1st PR submitted since we have a little big change for now @justincormack |
9f3890f
to
516320b
Compare
@justincormack @riyazdf @rn |
@arm64b apologies, but this needs another rebase. I accidentally merged a later PR which introduced conflicts with this one. Otherwise this looks good to me and I'll merge after the rebase |
Alpine is the base docker image for the LinuxKit, but currently it only supports amd64 architecture. This patch is try to unify the alpine tool docker image build process order to suport other architectures, such as AArch64, by using '--build-arg' to override the alpine base image specified by 'FROM' in the Dockerfile. Also this patch splits the standalone packages into 2 parts: one is common for all archs, another is arch-specific. Signed-off-by: Dennis Chen <dennis.chen@arm.com>
516320b
to
cc14a74
Compare
@rn rebase to the latest code base. it's not a straightforward rebase since we need to take care about the hash value of the versions.* in case installed pkgs changed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for the rebase. will merge this as soon as CI finishes to avoid more hassle
Alpine is the base docker image for the LinuxKit, but currently
it only support amd64 architecture. This patch try to refactor
the alpine docker image build process in order to support other
architectures, such as arm64, by using the new capability of 'ARG'
and 'FROM' in Dockerfile.
Also this patch splits the standalone packages into 2 parts:
one is common for all archs, another is arch-specific.
Signed-off-by: Dennis Chen dennis.chen@arm.com
- What I did
Support muti-arch build for tools/alpine docker image
- How I did it
Take use of the new feature of 'ARG' and 'FROM' supported by newer version of Moby in the Dockerfile, thus we can assign a specific BASE image with '--build-arg BASE=xxx' as the base image used by 'FROM'.
- How to verify it
Navigate into the tools/alpine folder, 'make ORG=your_org' on amd64 and arm64 platform, then we can get a your_org/alpine:xxx image on different platforms, using this image as the LinuxKit base image for other tools and pkgs.
$bin/moby build linuxkit.yml
$bin/linuxkit run ... linuxkit
- Description for the changelog
- A picture of a cute animal (not mandatory but encouraged)