Как кэшировать дир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 шт):
В вашем скрипте имеется только одна команда сборки. Вам нужно разделить её на две так, чтобы первая собирала библиотеки, а вторая - ваше приложение. То же самое относится к копированию файлов из хоста в контейнер. Сначала ваш скрипт должен скопировать файлы библиотек, потом их собрать, потом скопировать файлы вашего приложения, и наконец собрать его. Примерно так:
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, то эта команда и все последующие выполнятся полностью. Если же изменений не было, то будет использован кэш.