Skip to content
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

Build for multiple architectures #28

Closed
JonasAlfredsson opened this issue Mar 30, 2021 · 5 comments
Closed

Build for multiple architectures #28

JonasAlfredsson opened this issue Mar 30, 2021 · 5 comments
Assignees
Labels
enhancement New feature or request

Comments

@JonasAlfredsson
Copy link
Owner

Our parent container is build for multiple architectures (OS/ARCH), and in issue #24 I was made aware that this container does not successfully build on all arches. So it would be very nice if we could expand this to build for the same set of arches.

@JonasAlfredsson JonasAlfredsson added the enhancement New feature or request label Mar 30, 2021
@JonasAlfredsson JonasAlfredsson self-assigned this Mar 30, 2021
@JonasAlfredsson
Copy link
Owner Author

In order to do this locally, we can use Docker Buildx.

If you have Docker >= 19.03 this should already be included, otherwise the install instructions are found here. One thing that is easy to miss is the part where they mention that you will need to use this image in order to install all the QEMU dependencies used.

So my setup process went something like this:

1 - Install emulators

docker run --privileged --rm tonistiigi/binfmt --install all

2 - Initialize a builder

docker buildx create --name multiarch
docker buildx use multiarch
docker buildx inspect --bootstrap 

3 - Check that it picks up all the emulators

docker buildx ls                                                                                                                                                                                                                                                                                                                                                                                                         

NAME/NODE    DRIVER/ENDPOINT             STATUS  PLATFORMS
multiarch *  docker-container                    
  multiarch0 unix:///var/run/docker.sock running linux/amd64, linux/arm64, linux/386, linux/arm/v7, linux/arm/v6, linux/riscv64, linux/ppc64le, linux/s390x
default      docker                              
  default    default                     running linux/amd64, linux/386

@JonasAlfredsson
Copy link
Owner Author

After the installation is should be as easy as just specifying which platforms you want to build for [1]:

docker buildx build --platform linux/arm64/v8,linux/amd64 --tag jonasal/nginx-certbot-arches .

@JonasAlfredsson
Copy link
Owner Author

A problem with this is that DockerHub does not support multiarch builds (at least what I can find), which means that we need to find another solution. After researching this a bit I landed on GitHub Actions, and managed to create something that I think will work.

I found that this guide was good to get started with: https://docs.docker.com/ci-cd/github-actions/

I also used these two guides to get a better grip of how Workflows function:


After a lot of experimenting I came to the conclusion that I will have two different "action" files in my .github/workflows/ folder. The biggest difference between them is how they are triggered.

In the build_latest.yml file I will have the following on the top:

on:
  push:
    branches:
      - "main"
      - "master"
    paths:
      - "src/**"

which means that this job will only be triggered when something is changed inside the src/ folder on either the "main" or "master" branch, all other changes will be ignored. This should be fine since an edit to the README would not affect the Docker container being built.

In the build_tag.yml file I will have the following on the top:

on:
  push:
    branches-ignore:
      - "**"
    tags:
      - "v[1-9].[0-9]+.[0-9]+-nginx[1-9].[0-9]+.[0-9]+"

This will first ignore any pushes to all branches, while then triggering on any tags being pushed. The semi-regex (it is not normal regex, since "." is treated as a normal period here) will make sure that we only trigger on a very specific set of tags, and in this case it has the form of my release tags.

An important thing to understand with the tag filter is that it will trigger on a valid tag on whichever branch you place it. So if you add a valid tag on the dev branch, the action will checkout that reference and build it. However, the action script being used is the one that is in "main/master", oo changes to the wokflows will only take affect when they are pushed there.

@JonasAlfredsson
Copy link
Owner Author

One really annoying thing I ran into while building all the architectures is that there exist a really specific problem for some low level libraries when they try to read the filesytem while running inside a 32-bit environment that is emulated by QEMU running on a 64-bit host. More info about this exist in issue #30.

JonasAlfredsson added a commit that referenced this issue Mar 31, 2021
Our parent container is build for multiple architectures, so I think
it would be nice if we followed suite. With this change we will be
able to build the following platforms:

- linux/amd64
- linux/386
- linux/arm64
- linux/arm/v7
- linux/mips64le
- linux/s390x
- linux/ppc64le

However, we will only create a push function for the top 4, since
the bottom 3 takes over 30 minutes to build, and none have asked
for these yet.

Instructions on how to set up Docker Buildx (which is required for
this) can be found in [issue #28][1].

The reason for the "32-bit fix" added to the Dockerfile is a very
interesting read, which can be found in [issue #30][2], but the
TL;DR is that there exist a very exotic bug for some low level
libraries when they try to access the filesystem while running inside
a 32-bit environment that is emulated by QEMU running on a 64-bit host.
For this reason we will need to pin the package version to something
that is not being compiled, but this is ONLY necessary if it is inside
a QEMU emulation.

[1]: #28
[2]: #30
JonasAlfredsson added a commit that referenced this issue Mar 31, 2021
This workflow will be triggered when any tag, that match the semi-
regex (it is not normal regex, since "." is treated as a normal
period here), is pushed to the repository. The helper script will
then properly extract the version numbers we are interested in,
before the Docker image is built and tagged properly.

More info about this can be found in issue #28:
#28
JonasAlfredsson added a commit that referenced this issue Mar 31, 2021
This workflow will be triggered when something is changed inside either
the `src/` or the `.github/workflows/` folder on either the "main" or
the "master" branch, all other changes will be ignored. This should
be fine since an edit to the README would not affect how the Docker
container is being built.

More info about this can be found in issue #28:
#28
@JonasAlfredsson
Copy link
Owner Author

It seems I have been successful in this, closing for now :)

JonasAlfredsson added a commit to JonasAlfredsson/network-tools that referenced this issue May 4, 2021
See [issue 28][1] in my other repository for more info about how
this works.

[1]: JonasAlfredsson/docker-nginx-certbot#28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant