Как кэшировать дирeкторию в Docker?

Я использую cmake и пытаюсь написать Dockerfile для сборки образа с скомпилированным проектом. Пока мой Dockerfile выглядит так:

FROM ubuntu:latest AS builder

RUN apt-get update && apt-get install -y \
    gcc g++ cmake git \
    libjsoncpp-dev uuid-dev zlib1g-dev openssl libssl-dev \
    postgresql-server-dev-all \
    libpq-dev

WORKDIR /app

COPY . /app

RUN mkdir -p /app/build && \
    cd /app/build && \
    cmake /app/src && \
    make -j$(nproc) && \
    test -f /app/build/auth


FROM ubuntu:latest AS runtime

WORKDIR /app

COPY --from=builder /app/build/auth /app
COPY --from=builder /app/src/config.json /app
COPY --from=builder /app/src/ec384-*.pem /app

RUN apt-get update && apt-get install -y \
    libssl3 zlib1g libjsoncpp25 uuid-runtime \
    postgresql-client libpq5

RUN mkdir /app/uploads && \
    chmod -R 777 /app/uploads

EXPOSE 5555

USER nobody

ENTRYPOINT ["/app/auth"]

Я столкнулся с проблемой. При каждой сборке образа компилируется не только мой код, но и библиотеки, что значительно увеличивает время компиляции. Как я понял, эту проблему можно решить, если директория /app/build в контейнере не будет от сборки к сборке образа изменяться. Вопрос, как это сделать или другим способом решить проблему с повторной сборкой библиотек?


Ответы (1 шт):

Автор решения: maestro

В вашем скрипте имеется только одна команда сборки. Вам нужно разделить её на две так, чтобы первая собирала библиотеки, а вторая - ваше приложение. То же самое относится к копированию файлов из хоста в контейнер. Сначала ваш скрипт должен скопировать файлы библиотек, потом их собрать, потом скопировать файлы вашего приложения, и наконец собрать его. Примерно так:

COPY lib_dir /working/lib_dir/src
RUN mkdir -p /working/lib_dir/build && \
    cd /working/lib_dir/build && \
    cmake /working/lib_dir/src && \
    make -j$(nproc)

COPY app /working/app/src
RUN mkdir -p /working/app/build && \
    cd /working/app/build && \
    cmake /working/app/src && \
    make -j$(nproc)

Каждая отдельная команда в Dockerfile создаёт кэшируемый слой файловой системы. Кэш применяется при построении образов, если не было изменений в текущей команде и в командах, которые должны выполняться до неё. Так, например, если изменилась команда COPY lib_dir... или файлы, хранящиеся в lib_dir, то эта команда и все последующие выполнятся полностью. Если же изменений не было, то будет использован кэш.

→ Ссылка