diff --git a/content/posts/2022-12-24_using_docker_buildx_for_native_multiarch_builds.md b/content/posts/2022-12-24_using_docker_buildx_for_native_multiarch_builds.md new file mode 100644 index 0000000..404e210 --- /dev/null +++ b/content/posts/2022-12-24_using_docker_buildx_for_native_multiarch_builds.md @@ -0,0 +1,100 @@ +--- +title: "Using Docker buildx for native multiarch builds." +date: 2022-12-24T05:07:00+02:00 +draft: false +--- + +## TL;DR + +I wanted to build multiarch images using multiple machines with different architectures instead of QEMU. + +```bash +# add some amd64 machine that has docker +docker context create bob --docker "host=ssh://bob@10.0.0.2" +# create a buildx builder with your local machine added to it +docker buildx create \ + --name multiarch --node arm64 \ + --platform linux/arm64/v8 \ + default +# add the amd64 machine to it +docker buildx create --append \ + --name multiarch --node amd64 \ + --platform linux/amd64,linux/amd64/v2,linux/386\ + bob +# build & push your image +docker buildx build \ + --builder multiarch \ + --platform linux/amd64,linux/arm64/v8 \ + --push --tag username/imagename . + +# the amd64 image will be build natively on the amd64 machine, +# the arm64 machine will be build natively on the arm64 machine +``` + +## Actual post + +I wanted to build a multiarch image for `linux/arm64/v8` and `linux/amd64`, however the `x86` builds were really slow when running through QEMU on my _Apple Silicon_ laptop. Turns out, you can tell Docker to use another machine (which happens to be `x86_64`), to build the `linux/amd64` images, and use the local Docker Desktop instance for the ARM stuff. + +Here's how: + +1. Set up Docker on a machine (or many machines) that supports the architecture(s) you want to build for. Make sure you can SSH into it without using passwords (use SSH keys, and maybe ssh-agent if keys don't work on their own). + + Also, the user you're SSH-ing into needs to be able to access Docker. + +2. Create a _Docker context_ for the remote machine. + + ```bash + docker context create --docker "host=ssh://@:" + ``` + + `@` can be omitted - your local username will be used. `:` can also be omitted if it's `22`. + + Let's say we have an `amd64` host on ip `10.0.0.2`, and we want to call it bob (the builder). + + ```bash + docker context create bob --docker "host=ssh://bob@10.0.0.2" + ``` + +3. Create a buildx builder for your local computer. In this case, my local machine supports linux/arm64/v8 natively, but it also can build amd64 images through qemu, so I explicitly set `--platform` to just `linux/arm64/v8`. I might also add `linux/arm/v7` for images meant to run on something like a Raspberry Pi here, because even though it will still run via QEMU, I don't have anything better to build for `armv7` anyway. (it's comma separated) + + ```bash + docker buildx create \ + --name multiarch --node arm64 \ + --platform linux/arm64/v8 \ + default + ``` + + `multiarch` will be the name of our builder, `--node` is the name for the node we're adding to the builder (it doesn't have to contain the architecture, it can be anything, only the `--platform` value is taken into consideration by Docker). + + `default` is the name of the default context, which usually is your local machine. If not, replace it with whatever you use. + +4. Now, the fun part - add additional nodes for other architectures! In our example, we want to add `bob` which can build `linux/amd64` images natively. + + ```bash + docker buildx create --append \ + --name multiarch --node amd64 bob + ``` + + Notice the `--append` - it tells Docker to add the node to an existing builder. + + I've omitted `--platform` here, because in my case, `bob` only supports x86 anyways, so I don't have to limit it artificially. This was different for the local node, as Docker Desktop on MacOS comes with cross-platform build support preconfigured. + +5. Set the builder as default (optional, you can use `--builder multiarch` for `docker buildx build` to set the builder manually) + + ```bash + docker buildx use multiarch + ``` + +6. Finally, you can build your images: + + ```bash + docker buildx build \ + --platform linux/amd64,linux/arm64/v8 \ + --push --tag username/imagename . + ``` + + Unfortunately, it's not yet possible to load multiarch images into your local Docker daemon, which means you're gonna have to tag and `--push` to the Docker registry. + + You can still use `--load` instead of `--push` (to load into your local daemon) if you only specify a single `--platform`. Idk, might be useful for testing or something. + +Enjoy. diff --git a/themes/kwolek/static/css/style.css b/themes/kwolek/static/css/style.css index fbb7195..1fb9383 100644 --- a/themes/kwolek/static/css/style.css +++ b/themes/kwolek/static/css/style.css @@ -25,6 +25,10 @@ h2,h3,h4,h5 { padding-bottom: .2em; } +h2 { + line-height: 1.2; +} + header a { color: #fdf6ff; @@ -47,6 +51,7 @@ header > .icons > a { #content { margin-top: 3em; + line-height: 1.4em; } #homepage { @@ -197,16 +202,23 @@ ul.projectUpdateList { font-size: 0.9em; } -pre, .postList .timestamp { font-family: 'Source Code Pro', monospace; font-weight: 200; } -pre { - font-size: 1.2em; +.highlight { + overflow-x: auto; + background-color: #272822; + margin-bottom: 1em; } +pre { + box-sizing: bounding-box; + line-height: 1.2; + font-size: 1.2em; + margin: 1em; +} .seeAll { text-align: right; padding-right: .5em; @@ -218,4 +230,8 @@ pre { .project h3 { font-size: 1.2em; -} \ No newline at end of file +} + +ol > li { + margin-bottom: 2em; +}