问题
I'm trying to create one image for different architectures, namely for amd64 and arm64.
The Dockerfile I've created is identical in its contents.
When I build from this Dockerfile on my main machine, which is on amd64, the resultant image will run on all other amd64 machines. However, when I attempt to run this image on arm64, I will see exec errors.
The main culprit seems to stem from my use of Ubuntu as the base image (FROM: ubuntu:latest
), which somehow "knows" which architecture on which I'm building. As a result, I end up with a different image depending on the architecture I'm building on.
This isn't an issue in itself. After all, I can build once on amd64 and again on arm64.
What I'd like to do is be able to push one image for each architecture and have them pull to other machines automatically, without having to configure two sets of Dockerfiles. Another way to put it is I'd really like to know how the team at Ubuntu configures their images so that :latest pulls the latest version and the correct architecture.
Any advice would be appreciated!
Edit: For reference, I'm using Docker 19.03.5. The Dockerfile looks like this:
FROM ubuntu:latest
COPY /requirements.txt /tmp/
RUN apt-get update && \
apt-get install -y python3-pip python3-dev build-essential libssl-dev libffi-dev libxml2-dev libxslt1-dev && \
apt-get install -y libtiff5-dev libjpeg8-dev zlib1g-dev
RUN cd /usr/local/bin && \
ln -s /usr/bin/python3 python && \
pip3 install --upgrade pip
RUN pip install lxml && \
pip install -r /tmp/requirements.txt && \
pip install gunicorn
回答1:
I'd recommend using BuildKit with buildx which is available in 19.03. First you probably want some setup on a Linux host using qemu and binfmt_misc for cross compiling. Without it, you would need a build node for each platform you want to build. With binfmt_misc, you need two important details to work inside of a container, first is you need the static user binaries, and second is the --fix-binary
flag needs to be used when injecting them into the kernel. For the first, that comes down to the package name you install, e.g. on Debian the package name is qemu-user-static. And for the second, this may require a version of the package from from an unstable release. E.g. here are a few bug reports to get the change included:
- https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=868030
- https://bugs.launchpad.net/ubuntu/+source/qemu/+bug/1815100
Once you've done this, you can verify the --fix-binary
result by looking for the F
flag in /proc/sys/fs/binfmt_misc/*
.
Next, you need to setup a buildx worker. That can be done with:
docker buildx create --driver docker-container --name local --use \
unix:///var/run/docker.sock
docker buildx inspect --bootstrap local
You should see something like the following from the inspect, note the multiple platforms:
$ docker buildx inspect --bootstrap local
[+] Building 54.1s (1/1) FINISHED
=> [internal] booting buildkit 54.1s
=> => pulling image moby/buildkit:buildx-stable-1 45.4s
=> => creating container buildx_buildkit_local0 8.7s
Name: local
Driver: docker-container
Nodes:
Name: local0
Endpoint: unix:///var/run/docker.sock
Status: running
Platforms: linux/amd64, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
Now you can perform a build for multiple architectures. The $image_and_tag
must be an external registry where buildx can push the image. You cannot have a multi-arch image locally because docker images locally must be a single platform, but the registry like Docker Hub does support multi-arch manifests:
docker buildx build --platform linux/amd64,linux/arm64 \
--output type=registry -t $image_and_tag .
And you can even test those other images using the qemu cross platform support:
docker container run --platform linux/arm64 $image_and_tag
Note that you may need to enable experimental CLI options in docker, I forget which features have not made it to GA yet. In ~/.docker/config.json
, add:
{
"auths": {
...
},
"experimental": "enabled"
}
Or you can export a variable (adding to your .bashrc to make it persistent):
export DOCKER_CLI_EXPERIMENTAL=enabled
Note: docker desktop has included settings for qemu/binfmt_misc for a while, so you can skip straight to the buildx steps in that environment. Buildx can also be run as a standalone tool. See the repo for more details: https://github.com/docker/buildx
来源:https://stackoverflow.com/questions/59365141/pushing-images-to-docker-hub-for-multiple-architectures-e-g-amd64-arm64-and