Примеры из org/base

Этот раздел показывает, какие паттерны уже используются в org/base.

distroless-static

distroless-static строится от scratch и задаёт самый маленький базовый rootfs:

binary_packages:
source_images:
  - base/distroless-builder
distroless:
  from: scratch
  rootfs:
    files:
      - /bin
      - /etc
      - /usr
      - /var
      # в оригинальном файле список файлов намного длиннее
  user: nonroot
  workdir: /home/nonroot

Главная идея: rootfs задаётся минимальным набором каталогов и системных файлов. Этот образ подходит для статически связанных программ или как основа для образов, которым не нужен glibc runtime.

distroless-base

distroless-base добавляет динамический runtime:

binary_packages:
  - glibc-core
  - glibc-pthread
  - glibc-timezones
  - libselinux
  - libssl3
  - tzdata
  - zlib
source_images:
  - base/distroless-builder
  - base/distroless-static
distroless:
  from: "{{ registry }}{{ branch }}/distroless-static:latest"
  rootfs:
    packages:
      - glibc-core
      - glibc-pthread
      - glibc-timezones
      - tzdata
      - zlib
    timezone: Europe/Moscow

Здесь появляется важный паттерн: binary_packages может быть шире, чем rootfs.packages. Часть пакетов нужна для отслеживания обновлений и builder-стадии, но в rootfs может попадать только выбранный набор файлов.

distroless-cc

distroless-cc добавляет C/C++ runtime-пакеты целиком:

В этом и следующем примере используется сокращение @binary_packages; его смысл описан в формате спецификаций.

binary_packages:
  - libgcc1
  - libgomp1
  - libstdc++6
source_images:
  - base/distroless-builder
  - base/distroless-base
distroless:
  from: "{{ registry }}{{ branch }}/distroless-base:latest"
  builder:
    reinstall_packages: "@binary_packages"
  rootfs:
    packages: "@binary_packages"

Это хороший шаблон для runtime-слоя, где нужно добавить несколько rpm-пакетов целиком.

distroless-python3

Python runtime строится поверх distroless-cc:

binary_packages:
  - ca-certificates
  - ca-trust
  - python3
  - python3-base
  - python3-modules-curses
  - python3-modules-sqlite3
  - libpython3
source_images:
  - base/distroless-builder
  - base/distroless-cc
distroless:
  from: "{{ registry }}{{ branch }}/distroless-cc:latest"
  builder:
    reinstall_packages: "@binary_packages"
  rootfs:
    full_files:
      - /usr/bin/python3
    library_files:
      - /usr/lib64/python3*/lib-dynload/*.so
    packages: "@binary_packages"
  env:
    LANG: C.UTF-8
    SSL_CERT_FILE: /etc/pki/tls/certs/ca-bundle.crt
  user: nonroot
  workdir: /home/nonroot
  entrypoint:
    - /usr/bin/python3

Здесь используются сразу три механизма rootfs:

  • full_files для /usr/bin/python3;
  • library_files для Python extension modules;
  • packages для файлов из runtime-пакетов, перечисленных в binary_packages.

Dockerfile дополнительно создаёт symlink /usr/bin/python -> python3, если его нет.

distroless-gotop

Простой пример динамического бинарника:

binary_packages:
  - gotop
source_images:
  - base/distroless-builder
  - base/distroless-base
distroless:
  from: "{{ registry }}{{ branch }}/distroless-base:latest"
  builder:
    reinstall_packages:
      - gotop
  rootfs:
    full_files:
      - /usr/bin/gotop
  entrypoint:
    - /usr/bin/gotop

Для похожих утилит это один из лучших стартовых шаблонов.

distroless-devel

distroless-devel не является минимальным runtime. Это отладочный образ:

distroless:
  from: "{{ registry }}{{ branch }}/distroless-base:latest"
  rootfs:
    full_files:
      - /bin/bash
      - /usr/bin/curl
      - /usr/bin/gdb
    files:
      - /etc/alternatives/links/*
      - /usr/bin/vim
    library_files:
      - /usr/bin/vim
      - /usr/bin/ss
    packages:
      - coreutils
      - findutils
      - glibc-utils
      - iproute2
  cmd:
    - /bin/bash

Используйте этот образ как пример, когда нужен shell, диагностика и инструменты. Не копируйте его как базу для production runtime без необходимости.

distroless-busybox

distroless-busybox отличается от стандартных distroless-образов. В нём есть секция distroless, но Dockerfile написан вручную:

FROM {{ registry }}{{ branch }}/{{ alt_image }}:latest AS prepare

{{ install_packages("busybox") }}

RUN mkdir -p /rootfs/usr/bin && \
    cp -aL /usr/bin/busybox /rootfs/usr/bin/busybox && \
    /usr/bin/busybox --list | while read -r applet; do \
        [ "$applet" != busybox ] || continue; \
        ln -sf busybox "/rootfs/usr/bin/$applet"; \
    done

FROM {{ registry }}{{ branch }}/distroless-base:latest

COPY --from=prepare /rootfs /
CMD ["/usr/bin/sh"]

Такой подход допустим, если helper'ов DistrolessImage недостаточно. Но для новых образов сначала попробуйте стандартный шаблон с distroless_add().

Образы вне org/base на базе distroless

Не все образы, которые используют distroless runtime, обязаны создаваться через DistrolessImage. Например org/k8s-extra/kube-rbac-proxy может оставаться обычным AltImage, если в info.yaml нет секции distroless, но финальная стадия его Dockerfile наследуется от distroless-base:

FROM {{ registry }}{{ branch }}/{{ alt_image }}:latest AS prepare

{{ install_packages("kube-rbac-proxy") }}

RUN mkdir -p /rootfs/usr/bin && cp -aL /usr/bin/kube-rbac-proxy /rootfs/usr/bin/kube-rbac-proxy

FROM {{ registry }}{{ branch }}/distroless-base:latest

COPY --from=prepare /rootfs /
ENTRYPOINT ["/usr/bin/kube-rbac-proxy"]

В info.yaml это фиксируется через source_images:

target_package: kube-rbac-proxy
binary_packages:
  - kube-rbac-proxy
source_images:
  - alt
  - base/distroless-base

Такой способ подходит, если образу достаточно вручную скопировать несколько файлов из prepare-стадии. Если нужен автоматический сбор rootfs по rpm-пакетам, ldd, ENV, USER, WORKDIR, ENTRYPOINT и CMD из info.yaml, добавьте секцию distroless и используйте renderer DistrolessImage.