Search code examples
c++dockercmakemakefiledockerfile

How to optimize the build time of a c++ project inside a container


I have a following Docker file with c++ project that installs dependencies, copy cpp-project and builds it.

FROM amd64/debian:bullseye-slim as builder
LABEL description="Build container"

# Update and install build dependencies
RUN apt-get update && \
    apt-get -y install \
    build-essential \
    cmake \
    libxmlrpc-c++8-dev \
    libxmlrpc-c++8v5 \
    libxmlrpc-core-c3-dev \
    libxmlrpc-core-c3 \
    xmlrpc-api-utils \
    curl \
    libcurl4-openssl-dev \
    libsqlite3-dev \
    sqlite3 \
    libxml2-dev &&  \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# Copy source files
COPY cpp-project/ /usr/local/src/cpp-project/

# Specify the working directory
WORKDIR /usr/local/src/cpp-project/build

# Compile daemon
RUN cmake .. && make

FROM amd64/debian:bullseye-slim as runtime
LABEL description="Run container"

# Update apps on the base image
RUN apt-get update && \
    apt-get -y install \
    tini \
    libxmlrpc-c++8v5 \
    sqlite3 \
    libxml2 && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*
    
RUN mkdir /usr/local/daemon
# Daemon bin
COPY --from=builder /usr/local/src/cpp-project/build/my-daemon /usr/local/daemon/my-daemon

WORKDIR /usr/local/daemon

#ENTRYPOINT ["/sbin/tini", "-v", "--"]
ENTRYPOINT ["/usr/bin/tini", "-v", "--"]
CMD ["./my-daemon"]

EXPOSE 40302

This way of building the images takes time, because every time code changes it copies source file and run cmake and make. All the previous built libraries is gone in the next build and cmake/make will not take advantage of the previous build as it is a fresh docker and previous build directory is not present.

Is it possible to modify or some kind of volume mount so that the build directory is persisted and next cmake/build take advantage of previous build libraries? Just wanted to speed up my development process on my local machine.


Solution

  • Modern Dockerfiles allow you to specify that a persistent volume should be used for caching purposes. Replace your RUN cmake .. && make with:

    RUN --mount=type=cache,target=/usr/local/src/cpp-project/build,sharing=locked \
      cmake .. && cmake --build . && cp my-daemon /
    

    and in your second stage grab my-daemon from /my-daemon instead.

    The sharing=locked argument prevents multiple concurrent builds from interfering.