Skip to content

Commit a6cffa0

Browse files
authored
[RFC] Shrink musl docker image size by ~50% (#1670)
Here is a proof of concept patchset which reduces the size of the musl images from ~2.4G to ~1.2G, on the two architectures I tried (x86_64 and aarch64). Using aarch64 as a primary testbed, I got these results: * Baseline (edge): image size 2.39G (794M gzipped) * Patch 1 (strip the binaries in musl.sh): 1.55G * Add patch 2 (flatten the output image): 1.31G * Add patch 3 (additional tidyup script): 1.22G (348M gzipped). A space/bandwidth saving of 47% uncompressed, 56% compressed. I've tested the result with my use cases (x86_64 and aarch64). The crate I am cross-compiling depends on `ring` which has a C component. There is almost certainly more squeezing that could be done, but the Law of Diminishing Returns kicks in somewhere. For example, I spotted copies of identical binaries in /usr/local/bin which could be symlinked together to save a few more MB, but coming up with a safe and robust solution there might take a little thought. The majority of these savings are specific to the musl builds. I haven't analysed any of the non-musl images but there could be scope for improvement there as well. If you like this approach, I'll happily copy & paste the tidyup & flatten part into the other dockerfiles. OTOH, there may be other ways to achieve this; happy to discuss.
2 parents 50ccc96 + df33097 commit a6cffa0

18 files changed

+182
-1
lines changed

docker/Dockerfile.aarch64-unknown-linux-musl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ RUN /qemu.sh aarch64
1818
COPY musl.sh /
1919
RUN /musl.sh TARGET=aarch64-linux-musl
2020

21+
COPY tidyup.sh /
22+
RUN /tidyup.sh
23+
24+
FROM scratch AS final
25+
COPY --from=build / /
26+
CMD ["/bin/bash"]
27+
2128
ENV CROSS_TOOLCHAIN_PREFIX=aarch64-linux-musl-
2229
ENV CROSS_SYSROOT=/usr/local/aarch64-linux-musl
2330
COPY musl-symlink.sh /

docker/Dockerfile.arm-unknown-linux-musleabi

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ RUN /musl.sh \
2222
--with-float=soft \
2323
--with-mode=arm"
2424

25+
COPY tidyup.sh /
26+
RUN /tidyup.sh
27+
28+
FROM scratch AS final
29+
COPY --from=build / /
30+
CMD ["/bin/bash"]
31+
2532
ENV CROSS_TOOLCHAIN_PREFIX=arm-linux-musleabi-
2633
ENV CROSS_SYSROOT=/usr/local/arm-linux-musleabi
2734
COPY musl-symlink.sh /

docker/Dockerfile.arm-unknown-linux-musleabihf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ RUN /musl.sh \
2323
--with-float=hard \
2424
--with-mode=arm"
2525

26+
COPY tidyup.sh /
27+
RUN /tidyup.sh
28+
29+
FROM scratch AS final
30+
COPY --from=build / /
31+
CMD ["/bin/bash"]
32+
2633
ENV CROSS_TOOLCHAIN_PREFIX=arm-linux-musleabihf-
2734
ENV CROSS_SYSROOT=/usr/local/arm-linux-musleabihf
2835
COPY musl-symlink.sh /

docker/Dockerfile.armv5te-unknown-linux-musleabi

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ RUN /musl.sh \
2222
--with-float=soft \
2323
--with-mode=arm"
2424

25+
COPY tidyup.sh /
26+
RUN /tidyup.sh
27+
28+
FROM scratch AS final
29+
COPY --from=build / /
30+
CMD ["/bin/bash"]
31+
2532
ENV CROSS_TOOLCHAIN_PREFIX=arm-linux-musleabi-
2633
ENV CROSS_SYSROOT=/usr/local/arm-linux-musleabi
2734
COPY musl-symlink.sh /

docker/Dockerfile.armv7-unknown-linux-musleabi

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ RUN /musl.sh \
2323
--with-mode=thumb \
2424
--with-mode=arm"
2525

26+
COPY tidyup.sh /
27+
RUN /tidyup.sh
28+
29+
FROM scratch AS final
30+
COPY --from=build / /
31+
CMD ["/bin/bash"]
32+
2633
ENV CROSS_TOOLCHAIN_PREFIX=arm-linux-musleabi-
2734
ENV CROSS_SYSROOT=/usr/local/arm-linux-musleabi
2835
COPY musl-symlink.sh /

docker/Dockerfile.armv7-unknown-linux-musleabihf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ RUN /musl.sh \
2323
--with-mode=thumb \
2424
--with-fpu=vfp"
2525

26+
COPY tidyup.sh /
27+
RUN /tidyup.sh
28+
29+
FROM scratch AS final
30+
COPY --from=build / /
31+
CMD ["/bin/bash"]
32+
2633
ENV CROSS_TOOLCHAIN_PREFIX=arm-linux-musleabihf-
2734
ENV CROSS_SYSROOT=/usr/local/arm-linux-musleabihf
2835
COPY musl-symlink.sh /

docker/Dockerfile.i586-unknown-linux-musl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ RUN /musl.sh TARGET=i586-linux-musl
1818
COPY qemu.sh /
1919
RUN /qemu.sh i386
2020

21+
COPY tidyup.sh /
22+
RUN /tidyup.sh
23+
24+
FROM scratch AS final
25+
COPY --from=build / /
26+
CMD ["/bin/bash"]
27+
2128
ENV CROSS_TOOLCHAIN_PREFIX=i586-linux-musl-
2229
ENV CROSS_SYSROOT=/usr/local/i586-linux-musl
2330
COPY musl-symlink.sh /

docker/Dockerfile.i686-unknown-linux-musl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ RUN /musl.sh TARGET=i686-linux-musl
1818
COPY qemu.sh /
1919
RUN /qemu.sh i386
2020

21+
COPY tidyup.sh /
22+
RUN /tidyup.sh
23+
24+
FROM scratch AS final
25+
COPY --from=build / /
26+
CMD ["/bin/bash"]
27+
2128
ENV CROSS_TOOLCHAIN_PREFIX=i686-linux-musl-
2229
ENV CROSS_SYSROOT=/usr/local/i686-linux-musl
2330
COPY musl-symlink.sh /

docker/Dockerfile.loongarch64-unknown-linux-musl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ RUN /qemu.sh loongarch64
2828
COPY qemu-runner base-runner.sh /
2929
COPY toolchain.cmake /opt/toolchain.cmake
3030

31+
COPY tidyup.sh /
32+
RUN /tidyup.sh
33+
34+
FROM scratch AS final
35+
COPY --from=build / /
36+
CMD ["/bin/bash"]
37+
ENV PATH=/x-tools/loongarch64-unknown-linux-musl/bin/:$PATH
38+
3139
ENV CROSS_TOOLCHAIN_PREFIX=loongarch64-unknown-linux-musl-
3240
ENV CROSS_SYSROOT=/x-tools/loongarch64-unknown-linux-musl/loongarch64-unknown-linux-musl/sysroot/
3341
ENV CROSS_TARGET_RUNNER="/qemu-runner loongarch64"

docker/Dockerfile.mips-unknown-linux-musl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ RUN /musl.sh \
2222
TARGET=mips-linux-muslsf \
2323
"COMMON_CONFIG += -with-arch=mips32r2"
2424

25+
COPY tidyup.sh /
26+
RUN /tidyup.sh
27+
28+
FROM scratch AS final
29+
COPY --from=build / /
30+
CMD ["/bin/bash"]
31+
2532
ENV CROSS_TOOLCHAIN_PREFIX=mips-linux-muslsf-
2633
ENV CROSS_SYSROOT=/usr/local/mips-linux-muslsf
2734
COPY musl-symlink.sh /

docker/Dockerfile.mips64-unknown-linux-muslabi64

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ RUN /musl.sh \
2222
TARGET=mips64-linux-musl \
2323
"COMMON_CONFIG += -with-arch=mips64r2"
2424

25+
COPY tidyup.sh /
26+
RUN /tidyup.sh
27+
28+
FROM scratch AS final
29+
COPY --from=build / /
30+
CMD ["/bin/bash"]
31+
2532
ENV CROSS_TOOLCHAIN_PREFIX=mips64-linux-musl-
2633
ENV CROSS_SYSROOT=/usr/local/mips64-linux-musl
2734
COPY musl-symlink.sh /

docker/Dockerfile.mips64el-unknown-linux-muslabi64

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ RUN /musl.sh \
2222
TARGET=mips64el-linux-musl \
2323
"COMMON_CONFIG += -with-arch=mips64r2"
2424

25+
COPY tidyup.sh /
26+
RUN /tidyup.sh
27+
28+
FROM scratch AS final
29+
COPY --from=build / /
30+
CMD ["/bin/bash"]
31+
2532
ENV CROSS_TOOLCHAIN_PREFIX=mips64el-linux-musl-
2633
ENV CROSS_SYSROOT=/usr/local/mips64el-linux-musl
2734
COPY musl-symlink.sh /

docker/Dockerfile.mipsel-unknown-linux-musl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ RUN /musl.sh \
2222
TARGET=mipsel-linux-muslsf \
2323
"COMMON_CONFIG += -with-arch=mips32r2"
2424

25+
COPY tidyup.sh /
26+
RUN /tidyup.sh
27+
28+
FROM scratch AS final
29+
COPY --from=build / /
30+
CMD ["/bin/bash"]
31+
2532
ENV CROSS_TOOLCHAIN_PREFIX=mipsel-linux-muslsf-
2633
ENV CROSS_SYSROOT=/usr/local/mipsel-linux-muslsf
2734
COPY musl-symlink.sh /

docker/Dockerfile.riscv64gc-unknown-linux-musl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ ENV PATH=/x-tools/riscv64-unknown-linux-musl/bin/:$PATH
2626
COPY qemu.sh /
2727
RUN /qemu.sh riscv64
2828

29+
COPY tidyup.sh /
30+
RUN /tidyup.sh
31+
32+
FROM scratch AS final
33+
COPY --from=build / /
34+
CMD ["/bin/bash"]
35+
ENV PATH=/x-tools/riscv64-unknown-linux-musl/bin/:$PATH
36+
2937
COPY qemu-runner base-runner.sh /
3038
COPY toolchain.cmake /opt/toolchain.cmake
3139

docker/Dockerfile.x86_64-unknown-linux-musl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ RUN /musl.sh TARGET=x86_64-linux-musl
1818
COPY qemu.sh /
1919
RUN /qemu.sh x86_64
2020

21+
COPY tidyup.sh /
22+
RUN /tidyup.sh
23+
24+
FROM scratch AS final
25+
COPY --from=build / /
26+
CMD ["/bin/bash"]
27+
2128
ENV CROSS_TOOLCHAIN_PREFIX=x86_64-linux-musl-
2229
ENV CROSS_SYSROOT=/usr/local/x86_64-linux-musl
2330
COPY musl-symlink.sh /

docker/lib.sh

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,62 @@ docker_to_linux_arch() {
174174

175175
eval "${oldstate}"
176176
}
177+
178+
find_argument() {
179+
# Extracts the value from an argument of the form VARIABLE=VALUE
180+
local needle="$1"
181+
local return_var="$2"
182+
shift 2
183+
local prefix="${needle}="
184+
for var in "${@}"; do
185+
case "$var" in
186+
"$prefix"*)
187+
eval "$return_var=${var#"${prefix}"}"
188+
return 0 ;;
189+
*) ;;
190+
esac
191+
done
192+
echo "Missing argument ${needle}"
193+
exit 1
194+
}
195+
196+
symlinkify_if_same() {
197+
local file1="$1"
198+
local file2="$2"
199+
# Only make a symlink if the files are identical, and the destination file isn't already a symlink
200+
if [ ! -L "${file2}" ] && cmp "$file1" "$file2"; then
201+
ln -sf "$file1" "$file2"
202+
fi
203+
}
204+
205+
symlinkify_and_strip_toolchain() {
206+
local target="$1"
207+
local gcc_ver="$2"
208+
209+
local target_bin="/usr/local/${target}/bin"
210+
local local_bin="/usr/local/bin"
211+
212+
# The first set of tools appear as /usr/local/bin/<target>-<tool> and /usr/local/<target>/bin/<tool>
213+
214+
# Special case: ld is itself usually hardlinked to ld.bfd
215+
symlinkify_if_same "${local_bin}/ld" "${local_bin}/ld.bfd"
216+
217+
# Turn hard links or otherwise identical files into symlinks
218+
for tool in ar as ld ld.bfd nm objcopy objdump ranlib readelf strip; do
219+
local src="${local_bin}/${target}-${tool}"
220+
local dest="${target_bin}/${tool}"
221+
symlinkify_if_same "${src}" "${dest}"
222+
strip "${src}"
223+
done
224+
225+
# The second set of tools only appear as /usr/local/bin/<target>-<tool>
226+
227+
# Special case: c++ and g++ are usually the same file
228+
symlinkify_if_same "${local_bin}/${target}-c++" "${local_bin}/${target}-g++"
229+
# Special case: gcc and gcc-<version>
230+
symlinkify_if_same "${local_bin}/${target}-gcc" "${local_bin}/${target}-gcc-${gcc_ver}"
231+
232+
for tool in addr2line c++ c++filt cpp elfedit g++ gcc gcc-${gcc_ver} gcc-ar gcc-nm gcc-ranlib gcov gcov-dump gcov-tool gfortran gprof size strings; do
233+
strip "${local_bin}/${target}-${tool}"
234+
done
235+
}

docker/musl.sh

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ main() {
3636
# Don't depend on the mirrors of sabotage linux that musl-cross-make uses.
3737
local linux_headers_site=https://ci-mirrors.rust-lang.org/rustc/sabotage-linux-tarballs
3838
local linux_ver=headers-4.19.88
39+
local gcc_ver=9.2.0
40+
local target
41+
find_argument TARGET target "${@}"
3942

4043
# alpine GCC is built with `--enable-default-pie`, so we want to
4144
# ensure we use that. we want support for shared runtimes except for
@@ -44,7 +47,7 @@ main() {
4447
# linked, so our behavior has maximum portability, and is consistent
4548
# with popular musl distros.
4649
hide_output make install "-j$(nproc)" \
47-
GCC_VER=9.2.0 \
50+
GCC_VER=${gcc_ver} \
4851
MUSL_VER=1.2.3 \
4952
BINUTILS_VER=2.33.1 \
5053
DL_CMD='curl --retry 3 -sSfL -C - -o' \
@@ -58,6 +61,14 @@ main() {
5861

5962
popd
6063

64+
symlinkify_and_strip_toolchain "${target}" "${gcc_ver}"
65+
66+
for dir in /usr/local/libexec/gcc/"${target}"/*; do
67+
pushd "${dir}" || exit 1
68+
strip cc1 cc1plus collect2 f951 lto1 lto-wrapper liblto_plugin.so.0.0.0
69+
popd || exit 1
70+
done
71+
6172
rm -rf "${td}"
6273
rm "${0}"
6374
}

docker/tidyup.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/usr/bin/env bash
2+
3+
rm -rf /var/lib/apt/lists
4+
rm -rf /usr/local/doc

0 commit comments

Comments
 (0)