Devs, I think that I got to a good point in terms of size. To wrapped this post I will share my findings:
First I will like to start with @ahti 's dockefile. This is the current one that gave me the best results (112.58 MB) :
The second lead was was a link from a post from @ratranqu, I had some challenges making it work so I'm going to post the things needed for this.
In my case this method generates an image with a size of 117MB. Which is still damn good and I'm pretty sure you can find a use for it.
The main idea is to extract the needed dependencies of the swift application and compressed them, then use them in the running environment of our choosing, for my case I picked busybox since it was used by the tutorial and is super lightweight.
This is the shell script that takes the name of the binary and optionally the name of an output file, which uses ldd to determine the shared libraries used by the binary and compresses them into a gzipped tar file:
A Minimal Swift Docker Image
Swift With Docker
BIN="$1"
OUTPUT_TAR="${2:-swift_libs.tar.gz}"
TAR_FLAGS="hczvf"
DEPS=$(ldd $BIN | awk 'BEGIN{ORS=" "}$1\
~/^\//{print $1}$3~/^\//{print $3}'\
| sed 's/,$/\n/')
tar $TAR_FLAGS $OUTPUT_TAR $DEPS
make sure to name it "pkg-swift-deps.sh"
Next is the dockerfile:
FROM swift:5.5-focal
# Install OS updates
RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \
&& apt-get -q update \
&& apt-get -q dist-upgrade -y \
&& rm -rf /var/lib/apt/lists/*
# Create the app folder and make it the working directory.
ADD . /app
WORKDIR /app
# Resolve swift packages and build the app with static stdlib.
RUN swift package resolve
RUN swift build -c release --static-swift-stdlib
# Copy the pkg-swift-deps shell script to bin folder
# Use chmod to give permissions as an executable
# Run the shell script. We need to pass the location of the binary of the app, because the script is running for release we have to use ‘.build/release’
COPY pkg-swift-deps.sh /usr/bin/pkg-swift-deps
RUN chmod +x /usr/bin/pkg-swift-deps
RUN pkg-swift-deps .build/release/<NAME_OF_YOUR_APP_EXECUTABLE>
# Use busybox stable glibc. Had to use this stable version due to the ‘rm’ command giving me some issues
FROM busybox:stable-glibc
# Copy the compressed .tar file generated from the script, from=0 means that we are coping this from the first staged (FROM swift:5.5-focal)
# Copy the executable into ‘/usr/bin/‘
COPY --from=0 app/swift_libs.tar.gz /tmp/swift_libs.tar.gz
COPY --from=0 app/.build/release/<NAME_OF_YOUR_APP_EXECUTABLE> /usr/bin/
# Standard user creation for vapor
RUN adduser -Dh /app vapor
# unpack the dependencies from the tar file and remove the temp folder
RUN tar -xzvf /tmp/swift_libs.tar.gz && \
rm -rf /tmp/*
# Ensure all further commands run as the vapor user
USER vapor:vapor
# Let Docker bind to port 8080
EXPOSE 8080
# Start the Vapor service when the image is run, default to listening on 8080 in production environment
ENTRYPOINT ["<NAME OF YOUR EXECUTABLE>"]
CMD ["serve", "--env", "production", "--hostname", "0.0.0.0", "--port", "8080"]
The final lead was the docker file given by @Frizlab (It produced an image of 187 but again is a good example):