Что я хочу сделать, это создать образ докеров для моего Java-приложения, но для большинства скомпилированных языков должны быть верны следующие соображения.
Проблема
На моем сервере сборки я хочу создать образ докеры для моего приложения в качестве поставляемого. Для этого мне нужно скомпилировать приложение с помощью некоторого инструмента сборки (обычно Gradle, Maven или Ant), а затем добавить созданный файл JAR в образ докеры. Поскольку я хочу, чтобы изображение докера просто выполняло JAR файл, я, конечно же, начну с базового образа с уже установленной Java.
Существует три способа сделать это:
Пусть инструмент сборки управляет процессом
В этом случае мой инструмент построения управляет всем процессом. Поэтому он готовит JAR файл, и после создания JAR он вызывает Docker для создания изображения. Это работает, поскольку JAR создается заранее, и Docker может не обращать внимания на процесс сборки, необходимый для создания JAR.
Но мой Dockerfile больше не является автономным. Это зависит от шагов, которые могут произойти за пределами Docker. В моем Dockerfile у меня будет оператор COPY
или ADD
, который должен скопировать JAR файл на изображение. Это утверждение не будет выполнено, если баннер не будет создан заранее. Так что просто выполнение Dockerfile может не работать. Это становится проблемой, если вы хотите интегрироваться с сервисами, которые только что создаются с использованием текущего файла Docker, например, функции автоматической сборки на DockerHub.
пусть Docker управляет сборкой
В этом случае все необходимые шаги для создания изображения добавляются в файл Docker, поэтому изображение можно создать, просто выполнив сборку Docker.
Основная проблема с этим подходом заключается в том, что нельзя добавлять команды Dockerfile, которые должны выполняться за пределами создаваемого образа докера. Это означает, что я должен добавить свой исходный код и свои инструменты сборки к образцу докеров и создать свой JAR файл внутри изображения. Это приведет к тому, что мое изображение будет больше, чем должно быть из-за всех добавленных файлов, которые будут лишними во время выполнения. Это также добавит дополнительные слои к моему изображению.
Edit:
Как заметил @adrian-mouat, если бы я добавил источники, создав приложение и удалив исходные файлы в одном заявлении RUN, я мог бы избежать добавления ненужных файлов и слоев в образ Docker. Это означало бы создание какой-то безумной цепной команды.
две отдельные сборки
В этом случае мы разделим нашу сборку на две части: сначала мы создаем файл JAR с помощью нашего инструмента сборки и загружаем его в репозиторий (репозиторий Maven или Ivy). Затем мы запускаем отдельную сборку Docker, которая просто добавляет JAR файл из репозитория.
Заключение
На мой взгляд, лучший способ - позволить инструменту сборки управлять процессом. Это приведет к чистому снимку докера и, поскольку изображение - это то, что мы хотим доставить, имеет большое значение. Во избежание наличия потенциально не работающего файла Docker, лежащего вокруг него, необходимо создать часть сборки. Поэтому никто не случайно использовал его, чтобы начать разбитую сборку.
Но это не позволит мне интегрироваться с DockerHub.
Вопрос
Есть ли другой способ, который мне не хватает?