Обновить

Best Practices по Dockerfile: от базового образа и кеша до SBOM, Cosign и CI/CD

Уровень сложностиСредний
Время на прочтение30 мин
Охват и читатели18K
Всего голосов 48: ↑48 и ↓0+55
Комментарии7

Комментарии 7

Для сборки образа в CI/CD так же можно использовать buildkit rootless, если по каким-то причинам podman/buildah не подходит.

Да, согласен. BuildKit без рут прав - хороший вариант для сборки образов в CI/CD, особенно если хочется уйти от привилегированного Docker-in-Docker, а podman/buildah по каким-то причинам не подходят.

Там есть конечно свои нюансы с раннером, кешем, правами, сторедж и сетью, но как отдельный рабочий вариант безопасной сборки образов без рут доступа, это вполне уместно. 

Спасибо за комментарий, он в какой-то мере даже дополнил статью.

Спасибо что подметили, сейчас же добавлю)

ADD можно оставить только для редкого случая, когда вам действительно нужна автоматическая распаковка локального tar-архива и вы контролируете этот архив.

Ну как так-то… ADD умеет делать это лучше, чем приведенный сниппет.

Сравниваем:

RUN set -eux; \
    curl -fsSLo /tmp/tool.tar.gz "https://example.com/tool-${TOOL_VERSION}.tar.gz"; \
    echo "${TOOL_SHA256}  /tmp/tool.tar.gz" | sha256sum -c -; \
    tar -xzf /tmp/tool.tar.gz -C /usr/local/bin; \
    rm -f /tmp/tool.tar.gz

Против

ADD --unpack=true \
    --checksum sha256:${TOOL_SHA256} \
    https://example.com/tool-${TOOL_VERSION}.tar.gz /usr/local/bin

При этом ADD лучше работает с кэшами, не требует наличия в образе curl, tar, shasum и даже шелла. И не запускает qemu для не-нативных архитектур.

Двльше, очень нужно рассказать всем и везде, что Dockerfile поддерживает heredoc. И это очень полезно в первую очередь для RUN. Сравниваем на том же самом сниппете:

RUN set -eux; \
    curl -fsSLo /tmp/tool.tar.gz "https://example.com/tool-${TOOL_VERSION}.tar.gz"; \
    echo "${TOOL_SHA256}  /tmp/tool.tar.gz" | sha256sum -c -; \
    tar -xzf /tmp/tool.tar.gz -C /usr/local/bin; \
    rm -f /tmp/tool.tar.gz

Против

RUN << EOF
set -eux

curl -fsSLo /tmp/tool.tar.gz "https://example.com/tool-${TOOL_VERSION}.tar.gz"
echo "${TOOL_SHA256} /tmp/tool.tar.gz" | sha256sum -c -
tar -xzf /tmp/tool.tar.gz -C /usr/local/bin
rm -f /tmp/tool.tar.gz

EOF

Чем сложнее операции по сборке, тем нужнее эта фича. А если уж там 5-10 опций --mount для всяких кэшей и прочего добавить, то вообще незаменимая штука.

К слову об архитектурах.

Я бы еще добавил в секцию о multi-stage рекомендацию настраивать кросс-компиляцию и исполнять билд-стадию нативно, вот так:

ARG BUILDPLATFORM

# Run build stage on host-native architecture
FROM --platform=${BUILDPLATFORM} ${BUILD_BASE} AS build
ARG TARGETARCH
ARG BUILDARCH

RUN --mount=... --mount=... --mount=... << EOF

if [[ "${BUILDARCH}" != "${TARGETARCH}" ]; then
  # setup cross-compilation
fi

# compile
make -j`nproc` all

# install
make -j`nproc` install DESTDIR=/dest

EOF

# For target architecture just copy files from build stage without executing anything.
FROM ${BASE}

COPY --from=build /dest /

Если этого не делать, то при сборке мультплатформенных образов нативная для хоста архитектура будет собираться нормально, а вот все остальные будут собираться в qemu и это очень медленно.

Ну и на сладкое нужно упомянуть docker buildx bake, он пока довольно сырой, но уже позволяет гораздо более удобным способом управлять более сложными конфигурациями, когда требуется несколько вариантов образа и/или несколько вызовов докера для получения нужного результата.

Буквально пару недель назад переделывал контейнер одного сервиса. Раньше, там был alpine, gcc, и несмотря на настроенный multi-stage, нормально сборку никто не настраивал и не оптимизировал.

Я перевел с gcc на llvm/clang/lld, добавил варианты образов с сантиайзерами, внедрил кросс-компиляцию и 11 стадий сборки, за счет чего полностью избавился от сборки внутри qemu. Разобрался с кэшами и еще кучей всего. В результате, теперь сервис собирается за пять минут вместо полутора часов, при том, что сборка теперь делает в несколько раз больше полезных артефактов.

После вашего комментария специально копнул глубже, перепроверил актуальные возможности Dockerfile/BuildKit и подкорректировал статью: переписал блок про ADD, добавил пояснение про heredoc и отдельно отметил multi-platform сборки с нативной build-стадией и кросс-компиляцией. Спасибо — это как раз тот случай, когда комментарий не просто уточняет деталь, а реально усиливает материал.

Какая сокровищница! Спасибо!

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации