Add an Alpine docker image

It would be great to have a pre-configured docker:alpine image that we can use in devcontainers. This would allow us to share the same code in our development environment and in production.

The Swift compiler has various requirements on Glibc so as things currently stand, you can't compile Swift code on Alpine. You need to use one of the supported images.

You can however deploy to Alpine using the Linux SDKs

1 Like

There are multiple known issues when building the Swift toolchain on Alpine Linux (@al45tair could correct me if I'm wrong or missing something):

  • Musl headers currently have issues when used in Clang modules, which requires patching. This is done in existing Swift SDKs, but unclear how to reliably address this on Alpine. Patching (or shadowing with a patched version) of system headers is an option one would have to consider carefully before implementing.
  • Stack size with Musl is not large enough to build some Swift code:

The default stack size for new threads on glibc is determined based on the resource limit governing the main thread’s stack (RLIMIT_STACK). It generally ends up being 2-10 MB.

musl provides a default thread stack size of 128k (80k prior to 1.1.21)

I've seen this when building some SwiftPM/TSC code. There are certain LLVM passes relying on recursion, which for LLVM IR generated for this Swift code in TSC causes stack overflows. One way to work around it is to tweak the stack size in ELF files of a freshly built Swift toolchain linked with Musl, setting it to multiple megabytes similarly to what you get with glibc. The "proper way" to fix it is to rewrite that LLVM pass in an iterative and not recursive style, but last time I looked at it, it wasn't trivial.

None of this precludes you from deploying statically linked binaries on Alpine, which you can already do. The issues I've list above only block bootstrapping of the Swift toolchain on Alpine, which I've previously attempted a few years ago.

We actually have the same problem with Glibc — it's just that we currently mostly get away with it there, whereas from memory on Musl it's easier to run into problems. There's been some talk about what to do about it, because in both cases we need to make significant adjustments somehow, but in a way that won't break in the presence of future changes to Glibc/Musl. In Musl's case, at least, it's possible that we could contribute changes upstream, though I've had rather mixed success at that. In Glibc's case that probably isn't an option for various reasons.