Comments 12
Docker image это шаблон только для чтения с инструкциями по созданию контейнера.
Docker контейнер — это запускаемый экземпляр image.
Если проект большой, то можно в докере подмонтировать глобальный volume для промежуточных файлов сборки. Чтобы не пересобирать каждый раз с нуля.
При старте контейнер запускает только команду, которая указана в ENTRYPOINT или CMD, и останавливается при ее завершении.
Это неверно. Команда, которая выполняется при запуске контейнера получается, условно, путем склеивания ENTRYPOINT и CMD. Причем оба параметры могут переопределены при docker run
Чтобы этого избежать, можно при каждой сборке клонировать git-репозиторий внутрь контейнера, как, например, в файле:
Это худшая из идей. Нужно для начала определиться — для чего мы используем образ. Если для дистрибуции нашего софта, то git clone в докерфайле быть не должно. Как минимум из соображений того, что нам на приватные гит репозитории придется в докерфайле ещё как-то прописать ключи доступа. Ну, и, очевидно, что в образе хранить их не очень.
Второй момент, что если мы образ докера используем для фиксации версии сборочного тулинга, то это другая ситуация и исходники можно передавать как volume (опять же нет необходимости делать git clone внутри докерфайла)
Третий момент, который хочется подсветить — касается кэширования. Действительно, что докер пытается все кэшировать. И, соответственно, если в докерфайле написан "git clone", то докер может подумать, что изменений нет. Именно поэтому рекомендуется исходники инжектировать в образ через команду COPY, которая, как следует из названия, копирует файлы с машины разработчика внутрь образа. И в случае изменения любого файла в каталоге, передаваемом внутрь, докер увидит изменения. Либо есть ещё интересный воркераунд с передачей build-args и директивой ARG. Если внутрь образа подкидывать, например, текущую дату, то все после соответстввющей инструкции ARG будет инвалидировано и, как следствие, пересобрано. В принципе, это нормальная, описанная практика, хотя и выглядит как небольшой костыль
Ещё можно использовать docker multistage.
Команда, которая выполняется при запуске контейнера получается, условно, путем склеивания ENTRYPOINT и CMD.
Не совсем так, в документации написано, что, кроме склеивания, ENTRYPOINT
может полностью затирать CMD
— https://docs.docker.com/engine/reference/builder/#understand-how-cmd-and-entrypoint-interact.
Это важное замечание, и в статью добавлена информация о том, что ENTRYPOINT
и CMD
могут быть указаны вместе.
По поводу клонирования git-репозитория внутрь контейнера.
Такое поведение полезно, когда комиты попадают в мастер только через pull request (это позволяет выполнить, как минимум, сode review ). При таком подходе происходит разделение ролей — одни пишут код, другие выполняют сode review, а третьи выпускают версии (создают тег с новой версией в репозитрии и выполняют сборку релиза из добавленного тега). Клонирование репозитория с нужным тэгом внутрь контейнера, как минимум, упрощает сборку новой версии (не придется руками выполнять команду git checkout ...
). Так же, такое поведение исключает вероятность того, что папка с исходниками может содержать незакомиченный код, ветку разработки и пр.
Использование сборки с volume так же описана в статье.
Нужно для начала определиться — для чего мы используем образ.
В данной статье образ используется только для сборки. Если есть приватный репозиторий, то данные для аутентификации могут быть проброшены в контейнер, например через параметры -e, --env, --env-file
команды docker run
.
Третий момент, который хочется подсветить — касается кэширования.
Это полезное добавление. Я упустил из виду возможность использовать COPY
для копирования исходников внутрь контейнера.
Не совсем так, в документации написано, что, кроме склеивания, ENTRYPOINT может полностью затирать CMD —
Ну, там написано, что если меняете ENTRYPOINT, то CMD обнуляется.
Плюс есть немного магии с sh -c
А, в целом, это не противоречит написанному мной.
Так же, такое поведение исключает вероятность того, что папка с исходниками может содержать незакомиченный код, ветку разработки и пр.
Небольшая ремарка. У вас все равно должна быть система сборки и хранения кода. Например, гитлаб. И она гарантирует, что сборка не сможет быть произведена для кода, который не в репозитории. А разработчику МОЖЕТ быть нужно проверить код, который в его локальную копию репозитория ещё не попал. Это тонкости и, наверное, не предмет для спора. Но именно по совокупности — я за COPY исходников, а лучше — за подключение их в виде volume/bind-mount в сборочный контейнер (т.к. тот же гитлаб/jenkins etc. сами делают git clone в известное место известного коммита/ветки/тэга).
Если есть приватный репозиторий, то данные для аутентификации могут быть проброшены в контейнер, например через параметры -e, --env, --env-file команды docker run.
Принимается, но опять же — этой проблемы можно избежать, если исходники есть. Сюда же можно приплести гит-субмодули, если требуется сборка проекта из нескольких репозиториев (тогда создаётся убер-репозиторий, в который все остальные включены как субмодули с правильными версиями, и можно выкачать определенный срез-версию кодовой базы одним чохом, как говорится)
Можно взять за основу один из описанных вот тут — https://hub.docker.com/_/microsoft-windows-base-os-images
Пример Dockerfile с описанием windows-окружения есть вот тут — https://docs.microsoft.com/ru-ru/virtualization/windowscontainers/manage-docker/manage-windows-dockerfile
Инфраструктура сборки проекта с docker