Как я могу всегда получать мой последний образ докера, но при этом детерминировано записывать его состав для будущей воспроизводимости?

Я выполняю аналитическую работу в среде докеров «Лаборатория», которой я управляю. Я использую Travis для сборки, тегирования и публикации лабораторного образа в реестре контейнеров докеров (AWS ECR), а затем всегда извлекаю образ latest, когда запускаю контейнер для выполнения своей аналитической работы. Это гарантирует, что я всегда работаю в последней версии среды Lab. Примечание. Каждый раз, когда Travis публикует новый образ, он помечает его в ECR с помощью идентификатора фиксации сборки git и latest.

Для воспроизводимости моих аналитических результатов я хотел бы, чтобы мой код Python, работающий внутри контейнера, мог записывать в свои выходные данные идентификатор, указывающий точное используемое изображение докера. Это позволило бы мне повторно загрузить этот конкретный образ докера много месяцев/лет спустя из ECR и/или найти коммит git, из которого был создан образ докера, снова запустить код и (надеюсь!) получить те же результаты.

Каков наиболее стандартный способ достижения этого? Могу ли я сохранить дайджест изображения как переменную среды внутри контейнера?


person FOXintheBOX    schedule 01.05.2020    source источник


Ответы (3)


Вариантов, наверное, пару, но это зависит от того, как строится образ

Предполагая, что исходный код клонирован в CI, и из этого источника создается образ (поэтому вы не клонируете исходный код в файле Docker), вы можете использовать build-arg, чтобы «запечь» эту фиксацию в образе как переменная окружения;

В вашем Dockerfile определите аргумент сборки (ARG) и присвойте его значение переменной среды (ENV). Необходимо назначить его ENV, потому что аргументы сборки (по замыслу) не сохраняются в самом образе (доступны только во время сборки).

Например:

FROM busybox:latest
ARG GIT_COMMIT=HEAD
ENV GIT_COMMIT=${GIT_COMMIT}

Я устанавливаю значение по умолчанию, чтобы переменная содержала что-то «полезное», если Dockerfile собирается без передачи build-arg

Затем при сборке образа передайте git commit в качестве аргумента сборки.

git clone https://github.com/me/my-repo.git && cd my-repo

export GIT_COMMIT=$(git rev-parse --short --verify HEAD)

docker build -t lab:${GIT_COMMIT} --build-arg GIT_COMMIT=${GIT_COMMIT} .

При запуске образа GIT_COMMIT доступна как переменная среды.

Если вместо этого вы хотите передать ссылку во время runtime (при запуске образа), вы можете передать ссылку при запуске образа; например, чтобы передать дайджест образа, который вы запускаете;

docker pull lab:latest

export IMAGE_DIGEST=$(docker inspect --format '{{ (index .RepoDigests 0) }}' lab:latest)

docker run -it --rm -e IMAGE_DIGEST=${IMAGE_DIGEST} lab:latest
person thaJeztah    schedule 01.05.2020
comment
Спасибо! Это действительно полезно. Я сам попробовал ваше первое предложение, но мне не понравился тот факт, что это создает новый образ (и отправляет в ECR) при каждом нажатии git на репо, даже если файл докеры и контекст не изменились. Я думаю, что вариант времени выполнения, который вы предлагаете, может быть лучшим вариантом для меня. - person FOXintheBOX; 01.05.2020
comment
Генерируются ли аналитические результаты при запуске образа или при построении образа? И как публикуются результаты? Вместо того, чтобы выполнять анализ в docker run, рассматривали ли вы возможность поместить шаги в Dockerfile и выполнить их в docker build? (у меня, очевидно, не очень много контекста, так что просто мысли вслух) - person thaJeztah; 01.05.2020
comment
Они генерируются при запуске образа. Этот контейнер — моя аналитическая рабочая среда. Я запускаю его с интерактивной оболочкой, выполняю исследовательскую работу (наука о данных) на Python изнутри, генерирую некоторые результаты, которые сохраняю на смонтированном томе, затем закрываю контейнер, иду домой и готовлюсь к новому дню. . Затем я просыпаюсь ночью и понимаю, что не могу гарантировать воспроизведение этих результатов, потому что они не содержат информации о вычислительной среде, использованной для их создания. - person FOXintheBOX; 01.05.2020

Добавьте идентификатор фиксации к тегу изображения.

пример: имя изображения: dev-v1-bc4da47

где bc4da47 – идентификатор последнего коммита.

вы можете получить идентификатор последнего коммита

git rev-parse --short HEAD
person WSMathias9    schedule 01.05.2020
comment
Спасибо за предложение! Я уже делаю это, как упоминал в примечании. Однако это не означает, что я могу видеть этот идентификатор коммита, когда я docker pull lab:latest делаю его доступным внутри контейнера для записи с моими результатами. - person FOXintheBOX; 01.05.2020

Когда вы создаете образ, передайте аргумент сборки с хэшем git:

$ docker build --build-arg GIT_HASH=$(git rev-parse --short HEAD) -t yourimage .

И в вашем Dockerfile у вас должно быть:

ARG GIT_HASH

Я считаю, что теперь у вас должна быть переменная среды с хэшем git, доступным для кода, работающего внутри результирующего контейнера.

Длинная версия: https://pythonspeed.com/articles/identifying-images/

person Itamar Turner-Trauring    schedule 01.05.2020
comment
Спасибо за это. Я прочитал статью, на которую вы ссылаетесь, и это побудило меня попробовать добавить --label git-commit=git-commit (вместо использования --build-arg). Основным недостатком любого подхода (для меня) является то, что каждый раз, когда мой CI создает репозиторий (который содержит другой код, а не только образ докера), label или build-arg изменяется, даже если больше ничего не меняется, что приводит к созданию и публикации новые (иначе идентичные) изображения в ECR. - person FOXintheBOX; 04.05.2020