Arm64 Swift Docker Images?

With the Docker Tech Preview available (and working quite well as far as I can tell), I was wondering if there are any plans to publish arm64 swift docker images.

I.e. I'd love to get this to work on an M1 Mac:

❯ docker run swift:5.3
Unable to find image 'swift:5.3' locally
5.3: Pulling from library/swift
docker: no matching manifest for linux/arm64/v8 in the manifest list entries.
❯ docker --version
Docker version 20.10.1, build 831ebea

I looked around a bit yesterday to see if I could build an image myself and found these instructions here: https://github.com/futurejones/swift-arm64/blob/master/swift-ci-docker/README.md

That fails pretty soon with

[27/29][ 93%][2.023s] AR build/libninja.a
[28/29][ 96%][2.329s] CXX build/ninja.o
[29/29][100%][2.393s] LINK ninja
bootstrapping ninja...
warning: A compatible version of re2c (>= 0.11.3) was not found; changes to src/*.in.cc will not affect your build.
wrote build.ninja.
bootstrap complete.  rebuilding...
+ popd
[./swift/utils/build-script] ERROR: can't find source directory for libicu (tried /home/build-user/icu)
ERROR: command terminated with a non-zero exit status 1, aborting

and before going further down that particular rabbit hole I wanted to see if anyone knows if this is even the right rabbit hole or if there are other, nicer ones to explore :sweat_smile:

2 Likes

This is a really good question. Is there any official support for linux/arm64 platform support planned for Swift? So far the official downloads from swift.org are only amd64

There is https://github.com/futurejones/swift-arm64/releases which provides the Swift Toolchain for linux/arm64.

As a proof of concept, I took the latest release from futurejones/swift-arm64 and built Docker images from it and combined them with the official Docker images from https://hub.docker.com/_/swift: https://hub.docker.com/r/th089/swift

So you can do on your M1 or an intel Mac or a linux box:

$ docker run -it --rm th089/swift:5.3.2-bionic swift --version
5.3.2-bionic: Pulling from th089/swift
Digest: sha256:8574d9ee4e03d8be93d0ca26ae1dc4c3f3641eb33f6baee8a1f4712b60afa809
Status: Downloaded newer image for th089/swift:5.3.2-bionic
Swift version 5.3.2 (swift-5.3.2-RELEASE)
Target: aarch64-unknown-linux-gnu
2 Likes

this would be a great addition to https://github.com/apple/swift-docker/tree/main/swift-ci which is how we create docker images for linux. after the Dockerfiles are in place, we would then need to work with @mishal_shah and team to have CI jobs to utilize the new flavors

That's great, thanks for sharing that image, Tobias!

When you say you built docker images from the releases on futurejones, do you mean you built swift following their instructions or did you install their Swift releases in an arm64 linux base image?

I'd love to see the details so I can try and set it up for other Swift version.

did you install their Swift releases in an arm64 linux base image?

This. I’ll share some details later!

One thing that might be of interest to anyone on an M1 machine looking to use a nightly toolchain or any other Swift release in the interim: you can always run the intel images in Rosetta via:

docker run --platform linux/amd64 --rm -it swift:5.3

Given how well Rosetta works, this should help in a lot of typical Docker use-cases where convenience is more important than the last ounce of performance.

Edit: this does not actually work (yet?):

❯ docker run --platform linux/amd64 --rm -it swift:5.3 swift --version
Stack dump:
0.	Program arguments: /usr/bin/swift --version
1.	Swift version 5.3.2 (swift-5.3.2-RELEASE)
/usr/bin/swift[0x51fa1c4]
/usr/bin/swift[0x51f7dbe]
/usr/bin/swift[0x51fa49c]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x12980)[0x4000a45980]
/usr/bin/swift[0x192e333]
/usr/bin/swift[0x192735f]
/usr/bin/swift[0x4e9956]
/usr/bin/swift[0x4e8ce8]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xe7)[0x4002247bf7]
/usr/bin/swift[0x4e888a]
qemu: uncaught target signal 4 (Illegal instruction) - core dumped

I used to do various Raspberry Pi Docker images over here https://hub.docker.com/repository/docker/helje5, e.g. https://hub.docker.com/repository/docker/helje5/arm64v8-swift-dev. Based on various methods provided by the community (e.g. some on Future Jones stuff', some based on packages provided by Uraimo, etc.). They are not very up2date anymore but maybe useful to someone ;-)

I'm no expert on this, but I think an issue is ARM compatibility. To be honest I was surprised that M1's can even run ARM Linux out of the box. The problem is that ARM is not ARM, the vendors can add/remove features at will.
E.g. 2 years ago or so I tried to build Swift on the ARM instances provided by Scaleway. That didn't work out, because their boards had a different feature set (different Neon version? Something like that).

In other words, the question is what the Swift provided image would be. Is it an M1 optimised one which only works in M1 Docker? One which also works on Raspi's? Or on other boards? Which one?
(but again: I'm no expert on ARM, maybe that's a non-issue today, e.g. Graviton also seems to work out of the box?).

Just tried it, and this just works:

helge@M1ni ~ $ docker run helje5/arm64v8-swift-dev:5.0-latest swift --version
Swift version 5.0 (swift-5.0-RELEASE)
Target: aarch64-unknown-linux-gnu

This is the GitHub repo used for building the images: https://github.com/helje5/dockSwiftOnARM.

And another update: I've pushed 5.3.2 images based on FutureJones' build. This allows me to build Macro.swift directly in Docker on the M1:

helge@M1ni MacroExpress $ docker run --rm -v "$HOME/dev/Swift/Macro/MacroExpress:/src" -v "$HOME/dev/Swift/Macro/MacroExpress/.docker.build:/src/.build" helje5/arm64v8-swift-dev:5.3.2 bash -c 'cd /src && swift build -c release'
Fetching https://github.com/apple/swift-nio.git
Fetching https://github.com/apple/swift-log.git
Fetching https://github.com/AlwaysRightInstitute/mustache.git
Fetching https://github.com/Macro-swift/Macro.git
Cloning https://github.com/apple/swift-log.git
Resolving https://github.com/apple/swift-log.git at 1.4.0
Cloning https://github.com/AlwaysRightInstitute/mustache.git
Resolving https://github.com/AlwaysRightInstitute/mustache.git at 0.5.9
Cloning https://github.com/Macro-swift/Macro.git
Resolving https://github.com/Macro-swift/Macro.git at 0.6.2
Cloning https://github.com/apple/swift-nio.git
Resolving https://github.com/apple/swift-nio.git at 2.25.1
[1/12] Compiling mime MIME.swift
[2/12] Compiling CNIOWindows shim.c
[3/12] Compiling CNIOWindows WSAStartup.c
[4/12] Compiling CNIOSHA1 c_nio_sha1.c
[5/12] Compiling CNIOLinux shim.c
[6/12] Compiling xsys Module.swift
[7/12] Compiling Logging Locks.swift
[8/12] Compiling CNIODarwin shim.c
[9/12] Compiling CNIOHTTPParser c_nio_http_parser.c
[10/12] Compiling mustache HTMLEscape.swift
[11/12] Compiling c-nioatomics.c
[12/12] Compiling c-atomics.c
[13/13] Compiling NIOConcurrencyHelpers NIOAtomic.swift
[14/14] Compiling NIO AddressedEnvelope.swift
[15/16] Compiling NIOFoundationCompat ByteBuffer-foundation.swift
[16/17] Compiling MacroCore Buffer.swift
[17/18] Compiling NIOHTTP1 ByteCollectionUtils.swift
[18/19] Compiling fs Directory.swift
[19/20] Compiling dotenv dotenv.swift
[20/20] Compiling http Agent.swift
[21/21] Compiling connect BodyParser.swift
[22/22] Compiling express BasicAuth.swift
[23/23] Compiling MacroExpress MacroExpress.swift
helge@M1ni MacroExpress $ du -sh .docker.build/aarch64-unknown-linux-gnu/release/
 35M	.docker.build/aarch64-unknown-linux-gnu/release/
1 Like

I don’t think this is Rosetta. I think this will use QEMU emulation in the virtual machine that hosts the docker daemon.

1 Like

Yes, you’re right! It actually says so in the last line where the core is dumped :)

I've just uploaded the Dockerfiles I used to create the images here:

Let me know what you think!

2 Likes

Hey, @tomerd, not sure I follow. I believe the existing Dockerfiles are just fine. I didn't check all the base images but at least for ubuntu and amazonlinux, the base images already support arm64 as-is. So, all you need to do, is add one or more arm64 nodes to the swift-ci (eg. an AWS m6g instance should work really well) and run the builds. I tested the ubuntu:20.04 Dockerfile on a m6g.xlarge: after approx 2h it completed the swift-5.3.2-RELEASE build with

cp -r /source/* /home/build-user/
./swift/utils/build-script --preset buildbot_linux,no_test \
        install_destdir=/home/build-user/install \
        installable_package=/home/build-user/install/swift-5.3.2-RELEASE-ubuntu-20.04-arm64.tar.gz

Once you have the arm64 tarballs in place you can change the existing swift dockerfiles to fetch the platform specific archive:

Eg:

# ...
&& SWIFT_BIN_URL="$SWIFT_WEBDIR/$SWIFT_VERSION/$SWIFT_VERSION-$SWIFT_PLATFORM-$SWIFT_ARCH.tar.gz" \
# ...

Where SWIFT_ARCH can be defined in the Dockerfile as:

ARG TARGETARCH
ARG SWIFT_ARCH=${TARGETARCH}

If you then run the docker build on an amd64 instance SWIFT_ARCH will be amd64 and on arm64 instance, it will be arm64, respectively.

2 Likes

ping @tomerd @mishal_shah
Is this something that could be looked into from your end?

1 Like

thanks for the clarification, my [wrong] assumption was that we would need to make changes to the Dockerfiles to get this to work, happy to learn they work as-is

This is def something I think we should pursue, would need to work with @mishal_shah and team to figure out when we can support it

4 Likes
Terms of Service

Privacy Policy

Cookie Policy