-
Notifications
You must be signed in to change notification settings - Fork 16
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
Add support for multi-platform images #54
Conversation
README.rst
Outdated
@@ -432,6 +432,13 @@ shows the different configuration options available: | |||
<or> | |||
platform: linux/arm64/v8 # an apple m1 architecture | |||
|
|||
# Multi-platform images | |||
# Specify a list of platforms to build for, and buildrunner will build a manifest | |||
# list image with the given platforms |
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 think we need to make it clear that this uses the builders configured in build for these platforms, which may or may not be emulated.
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 agree this should be more clear. But I am not sure what you mean by this uses the builders configured in build for these platforms
. Can you elaborate on that some more?
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.
builders configured in buildx is what I meant.
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.
Oh I see what you mean. Right now, it doesn't use any configured buildx builders
, it just uses the default builder. In the future we may use different builders.
However, for now how about this for the comment?
# For Multi-platform images please specify a list of platforms to build for
# and buildrunner will build images with the given platforms.
# Please note that these may be built using emulated architectures which
# will be slower than native builds.
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.
Updated this, but let me know if you think it still needs work.
@@ -573,85 +574,92 @@ def run(self): # pylint: disable=too-many-statements,too-many-branches,too-many | |||
|
|||
exit_explanation = None | |||
try: # pylint: disable=too-many-nested-blocks | |||
with MultiplatformImageBuilder(keep_images=not self.cleanup_images) as multi_platform: |
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.
Does this always end up starting the local registry, or just when multiple platforms are specified?
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.
Good catch! This is a bad design, since this will create a local registry every time. I'll need to make an update to parse the config to see if there are any multi-platform images in the platform.
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.
Added new commit to fix this.
) | ||
if exit_code != 0 or not builder.image: | ||
raise BuildRunnerProcessingError('Error building image') | ||
if isinstance(self.platform, list): |
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 think this should be:
if isinstance(self.platform, list) and len(self.platform) > 1:
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.
done
|
||
assert len(built_images) == len(self.platform), \ | ||
f'Number of built images ({len(built_images)}) does not match ' \ | ||
'the number of platforms ({len(self.platform)})' |
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.
when splitting a string you need the f
prefix on every formatted string
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.
done
buildrunner/steprunner/tasks/push.py
Outdated
for repo in self._repos: | ||
# Always add default tag | ||
repo.tags.append(default_tag) | ||
self.step_runner.multi_platform.tag_single_platform(name=self.get_unique_build_name(), |
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.
Personally I feel like this kind of parameter indentation can be hard to read, especially with very long prefixes. I much prefer something like this:
self.step_runner.multi_platform.tag_single_platform(
name=self.get_unique_build_name(),
tags=repo.tags,
dest_name=repo.repository,
)
I'm not asking you to change this, I just thought I should mention it as I think it's much easier to parse what's going on since you don't have to read across the entire line for the indent.
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 like your suggestion better.
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.
done
tests/test_multiplatform.py
Outdated
missing_images.append(expected_image) | ||
return missing_images | ||
|
||
def test_use_local_registry(): |
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.
Should have two lines in between methods.
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.
done
|
||
# FIXME: These tests can be broken if a custom buildx builder is set as default # pylint: disable=fixme | ||
|
||
def actual_images_match_expected(actual_images, expected_images) -> List[str]: |
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.
Should have two lines in between methods/declarations.
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.
done
tests/test_multiplatform.py
Outdated
assert not docker.volume.exists(volume_name) | ||
|
||
@pytest.mark.parametrize("name, in_mock_os, in_mock_arch, built_images, expected_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.
This indent seems a little much... but maybe it's just github doing weird things.
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.
No you are right, it is extreme. I'll make it less.
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.
done
README.rst
Outdated
@@ -432,6 +432,14 @@ shows the different configuration options available: | |||
<or> | |||
platform: linux/arm64/v8 # an apple m1 architecture | |||
|
|||
# For Multi-platform images please specify a list of platforms to build for |
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.
How about this instead?
To build multi-platform images, add each platform to be built to this list and buildrunner will use docker buildx
to build and tag a single image containing all architectures specified. Note that buildx may be configured to
build some platforms with emulation and therefore builds may take longer with this option specified.
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 made a minor change to that.
buildrunner will use docker buildx to build and provide a single tag containing all architectures specified.
docker buildx will actually create multiple images, one for each architecture, and then combine them into a single tag.
Description
Adds support for docker multi-platform images using docker buildx. Because a common use case in buildrunner is to build a image locally, run some tests in the new image and then push the newly built image to a remote registry if the tests pass some specially steps had to be taken. In it's simplest form you can do
docker buildx build --platform <list of platforms> -t <tag> --push .
which will build and push a multi-platform image in a single command (but you may need to create a new builder for this). However, using this way will not allow for intermediate testing on the image prior to pushing it to a remote registry. For this reason the following methodology was contrived:During testing the local docker registry container was used since it appeared that a manifest was never created unless the
--push
flag was used. And the finalpush
in step 5 is done by usingdocker buildx imagetools create
which creates a list of existing manifests.Related Issue
Motivation and Context
Multi-platform images are becoming for common and the standard for many images. As well as a push by some to begin to use
ARM
images.How Has This Been Tested?
Unit tests have been created for the
MultiplatformImageBuilder
class which does most of this logic. I also created and used a simple repo with abuildrunner.yaml
config to build and push single and multiple platform images.Screenshots (if appropriate):
Types of changes
Checklist: