I am trying to minimize of size of my Docker image as small as possible, the Dockerfile looks like this:
ARG DISTRO=fedora
ARG FEDORA_VERSION=36
#FROM ${DISTRO}:${FEDORA_VERSION} AS dev
FROM ${DISTRO}:${FEDORA_VERSION} AS dev
#Toolchain
RUN dnf -y install \
gcc gcc-c++ \
pkgconfig \
cmake make \
autoconf automake autogen libtool \
flex bison \
git rpm-build
#Dependencies
RUN dnf -y install \
openssl-devel \
#libuuid-devel \
libcurl-devel \
jansson-devel \
spdlog-devel \
fmt-devel \
libconfig-devel \
libusb-devel \
lua-devel \
libnice-devel \
libwebsockets-devel
# Add local and 64-bit locations to linker paths
RUN echo /usr/local/lib >> /etc/ld.so.conf && \
echo /usr/local/lib64 >> /etc/ld.so.conf
ADD packaging/deps.sh /
RUN bash deps.sh
EXPOSE 80
EXPOSE 443
ENV LC_ALL C.UTF-8
ENV LANG C.UTF-8
FROM dev AS builder
ARG FLAGS
# Disable all default features
RUN FLAGS+=" -DWITH_DEFAULTS=OFF" && \
# Enable the villas-* binaries from ./src again
FLAGS+=" -DWITH_SRC=ON" && \
# Enable the villas-* tools from ./tools again
FLAGS+=" -DWITH_TOOLS=ON" && \
# Enable libconfig configuration syntax
FLAGS+=" -DWITH_CONFIG=ON" && \
# Enable the nodes
FLAGS+=" -DWITH_NODE_TEST_RTT=ON" && \
FLAGS+=" -DWITH_NODE_WEBRTC=ON" && \
FLAGS+=" -DWITH_NODE_SIGNAL=ON" && \
# Enable hooks, in&out support
FLAGS+=" -DWITH_IN=ON" && \
FLAGS+=" -DWITH_HOOKS=ON" && \
FLAGS+=" -DWITH_OUT=ON"
COPY . /villas/
WORKDIR /villas/build
RUN cmake ${FLAGS} -S .. && \
make -j$(nproc) install && \
ldconfig
ENTRYPOINT ["villas"]
So far, i tried to reduce the number of dependencies and the layers. But i found out that the dependencies can not be pruned anymore, deleting any one of them will lead to failure when building the Dockerfile. And by reducing the layers did not help much.
So i tried to use 'Alpine Linux base image' to reduce the image size, and i tried it by adding 'FROM alpine:latest
' before 'COPY . /villas/
'. But it didn't work, i could not build the Dockerfile with it. So what is the right way in my case to reduce the size of image using 'Alpine Linux base image'?
The most important thing you can do with this setup is to introduce a multi-stage build. The image as you've shown it contains a complete C toolchain and development libraries, which are quite large. The size difference between a Fedora and Alpine image is miniscule compared to this (50-100 MB of base image, compared to 1 GB+ of toolchain and libraries).
The Dockerfile already starts with FROM image AS name
syntax to declare a named stage. You need to add a third stage at the end:
FROM ${DISTRO}:${FEDORA_VERSION}
# Install non-development versions of C shared libraries that will
# be used at runtime. See https://packages.fedoraproject.org/
# to find package names.
RUN dnf -y install \
openssl-libs \
libcurl \
...
# Copy the installed application into the final image.
COPY --from=builder /usr/local /usr/local
RUN ldconfig
# Set metadata for how to run the image.
# USER ...
# EXPOSE ...
CMD ["villas"]
This image will still be based on Fedora and not Alpine, but it will be substantially smaller than the image you're using now.
In principle it's possible to change that last FROM
line to FROM alpine
. You'll need to use Alpine's apk
package manager instead of Fedora's dnf
, and find dependencies on https://pkgs.alpinelinux.org/packages.
However, note that one of the things that makes Alpine-based images smaller is using an alternate C system library, musl libc instead of GNU libc. There are a number of very-low-level incompatibilities here. Many things will work with musl libc, but not all. If your application depends on a significant number of other shared libraries and also installs its own, I'd be worried about weird compatibility problems.
The easiest answer here often is to rewrite the entire build system to be Alpine- and not Fedora-based. A complete rewrite is beyond the scope of this answer. It's possible your application will run into build-time or link-time problems as well, but these should give clear pointers into your source code.
The multi-stage build approach will save you a huge amount of space in the final image. You may decide that saving a relatively small amount of space by switching base distributions isn't worth the effort of completely rebuilding and debugging the Dockerfile.