Kitura/swift-ubuntu-docker

swift-slim ?

ralph-tice opened this issue · 13 comments

Hi,

Is there any interest in building a docker container with the swift dependencies built into a statically compiled binary? 1.2GB from ubuntu guts and the full gcc buildchain is kind of rough.

I don't think there are plans at the moment for this. Having said that, please feel free to elaborate. Thanks.

My basic idea here is to use one image for building and another for shipping the resulting binaries as a self-contained image, FROM scratch. It doesn't look like swift is doing me many favors based on some brief research that turned up things like this: https://github.com/ksm/SwiftInFlux#static-libraries

We can surely do better than ibmcom/swift-runtime latest 30412f643874 11 weeks ago 1.26 GB, but at least the layers currently in use are pretty popular.

@ralph-tice
I have been working on a similar idea. The slimming of a Swift Docker image could be broken into 2 phases.

Phase 1

Currently Apple is not bundling libdispatch into the Swift Ubuntu binaries on swift.org. Since Kitura and other Swift projects depend on libdispatch, the current ibmcom/swift-ubuntu Docker image brings in all the dependencies in order to build, link and install libdispatch. This results in a current Docker image of 1.508 GB.

I have a fork of this project here that does the following:

  1. Create an image of swift3-base which adds all Apple built binaires
  2. Create a dependent swift3-libdispatch image which builds libdispatch and tars the binaries
  3. Create an image swift3-slim from swift3-base and copies in the libdispatch binaries

This results in Docker image of 1.296 GB. A 200 MB savings.
Note: this is working in progress and has had limited testing.

Phase 2

Where I would like to see this go is the use of Alpine Linux as a base image. Alpine has a lot of momentum due to it's tiny footprint - 5 MB.

Several official Docker images now have Alpine versions including:

  • nginx:alpine - 60.65 MB
  • redis:alpine - 20.42 MB
  • python:alpine - 71.68 MB

However, this would require an overhaul of the Apple Swift Ubuntu build system. If anyone has started work on an Alpine port, let us know.

At first glance, it appears that glib, libblocksruntime and libkqueue are not available on Alpine yet. Workarounds do exist for glib:
https://developer.atlassian.com/blog/2015/08/minimal-java-docker-containers/

So it appears that any swift-slim Docker image would need to be derived from a base image that is libdispatch compatible.

I reported issues back to Alpine previously about the glibc hack causing a crash for JVM processes, it's really pretty scary to have libmusl and glibc in the same environment, so I don't advise using Alpine as a base in this case... gliderlabs/docker-alpine#11 (comment)

@dsperling, the proper way to do Phase 1 (and how all of the other slim images work) is to – in one RUN step – install the build deps, compile the binary, and remove the build deps.

@conradev, Apple is now including libdispatch binaries in Ubuntu releases, so the need for Phase 1 has solved itself. But yes, your idea of a single RUN step is the right way and much simpler than what I was working on prior.

@dsperling Wouldn't it make more sense to use the glib version of BusyBox, rather than focusing on Alpine?

@siilime The original thought was to align a slim Swift image with the direction Docker themselves are headed with Alpine:
https://www.brianchristner.io/docker-is-moving-to-alpine-linux/

Since we have started this thread, Docker has created an official Swift image, although it is still based on Ubuntu 16.04.
https://hub.docker.com/_/swift/

@dsperling And as much as I agree with that, I think some of the changes for this to be possible need to come from the internal development stream.

I've created my own Docker image for running Swift programs, rather than building. Building isn't too much of a concern for me as my customers won't be affected by a slow build as much as they would be by a slow recovering production environment.

As far as I'm aware, Alpine is based on BusyBox, which is why I suggested starting there. It's the base for Alpine and has a glibc supported setup, as well as a musl setup. Meaning the transition to Alpine should be smoother, than it would be trying to go from Ubuntu, to a musl-based Alpine.

I could be entirely wrong; just the thought of trying to get Swift onto Alpine gives me a headache, but it seems logical to me.

All, I am closing this issue for now:

  1. We recently released a second docker image, swift-ubuntu-runtime, (see README) that is much smaller than the swift-ubuntu development image. This second image does not have any of the builds tools; instead it is meant to be used only for running Swift apps. For more details, see the README.

  2. Though it is true that a different linux base image could be used (such as Alpine), that’s not within our scope now. The main purpose of the docker image we maintain here is to provide an environment that uses Ubuntu 14.04 which is the same Linux flavor used by Cloud Foundry-based offerings. We have seen several cases where developers use docker images based on Ubuntu 16.04 or 15.10 or other linux flavors and then run into unexpected problems when running their apps on cloud offerings based on Cloud Foundry.

It would be great to have a link to swift-ubuntu-runtime from this.

it is already in-repo and documented in the README -- https://github.com/IBM-Swift/swift-ubuntu-docker#ibmcomswift-ubuntu-runtime