Параметризация сборки Docker путем передачи имени файла JAR из командной строки

Я пытаюсь параметризовать окончательное имя файла JAR в сборке Docker. Мне нужен docker-maven-plugin, чтобы получить имя файла jar, переданное через параметр командной строки. Maven build не выдает никаких ошибок при построении образа.

Если я жестко закодирую имя файла jar в dockerfile, оно работает нормально.

Команда Maven для сборки Docker:

mvn -X -s settings.xml docker:build -DJAR_FILE_NAME=${filename}

Мой файл докера:

RUN curl -kfsSL https://example.com/UnlimitedJCEPolicyJDK8/US_export_policy.jar > US_export_policy.jar \
&& curl -kfsSL https://example.com//UnlimitedJCEPolicyJDK8/local_policy.jar > local_policy.jar \
    && mv local_policy.jar ${JAVA_HOME}/jre/lib/security \
    && mv US_export_policy.jar ${JAVA_HOME}/jre/lib/security \
    && rm -rf US_export_policy.jar local_policy.jar 

ENV JAVA_KEYSTORE ${JAVA_HOME}/jre/lib/security/cacerts
RUN curl -kfsSL https://example.com/mycert.cer > mycert.cer \
    && ${JAVA_HOME}/bin/keytool -v -importcert -file mycert.cer -keystore ${JAVA_KEYSTORE} -storepass dummy -alias dummy -noprompt \
    && rm mycert.cer

VOLUME /tmp
#ADD myservice-2.0.2-SNAPSHOT.jar app.jar   <-hard-coded name works fine

RUN echo "final jar file name"
RUN echo ${JAR_FILE_NAME}

ADD ${JAR_FILE_NAME} app.jar
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

Мой POM.xml

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.4.0</version>
    <configuration>
        <imageName>${docker.image.prefix}/myservice</imageName>
        <dockerDirectory>src/main/docker</dockerDirectory>
        <resources>
            <resource>
                <targetPath>${docker.resource.targetPath}</targetPath>
                <directory>${project.build.directory}</directory>
                <include>${project.build.finalName}.jar</include>
            </resource>
        </resources>
    </configuration>
</plugin>

Вывод из процесса сборки докера:

Step 6 : VOLUME /tmp
 ---> Using cache
 ---> xxxxxxxxx
Step 7 : RUN /bin/bash -c echo JAR_FILE_NAME1 in docker :$JAR_FILE_NAME
 ---> Using cache
 ---> xxxxxxxxx
Step 8 : RUN /bin/bash -c echo JAR_FILE_NAME2 in docker :${JAR_FILE_NAME}
 ---> Using cache
 ---> xxxxxxxxx
Step 9 : RUN echo $JAR_FILE_NAME
 ---> Using cache
 ---> xxxxxxxxx
Step 10 : RUN echo "final jar file name"
 ---> Using cache
 ---> xxxxxxxxx
Step 11 : RUN echo ${JAR_FILE_NAME}
 ---> Using cache
 ---> xxxxxxxxx
Step 12 : ADD ${JAR_FILE_NAME} app.jar
 ---> Using cache
 ---> xxxxxxxxx
Step 13 : RUN bash -c 'touch /app.jar'
 ---> Using cache
 ---> xxxxxxxxx
Step 14 : ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -jar /app.jar
 ---> Using cache
 ---> xxxxxxxxx
Successfully built xxxxxxxxx
[INFO] Built xxx/myservice

Вывод при вытягивании изображения:

I0603 13:48:32.849159 23106 exec.cpp:132] Version: 0.23.0
I0603 13:48:32.857393 23114 exec.cpp:206] Executor registered on slave 20170523-104056-1453378314-5050-11670-S48
Usage of loopback devices is strongly discouraged for production use. Either use `--storage-opt dm.thinpooldev` or use `--storage-opt dm.no_warn_on_loop_devices=true` to suppress this warning.
Error: Invalid or corrupt jarfile /app.jar

3 ответа

Решение

Я параметризовал выходной jar для использования в образе докера таким образом.

  1. В Dockerfile используется конкретное имя без какой-либо версии. Удалены ${JAR_FILE_NAME}, динамические параметры из Dockerfile.

ADD myservice.jar app.jar

  1. В POM.xml я заставил maven выводить артефакт без версии в имени файла jar, добавив элемент под тегом.

<finalName>${project.artifactId}</finalName>

Таким образом, для Dockerfile не требуется ручное обновление. Забыть обновить Dockerfile и затем получить сборку не удалось. Я позволил Maven управлять версиями, и эти версии используются в качестве конечных тегов изображений, и, таким образом, "воспроизводимые сборки" работают для меня.

Почему бы вам не использовать обычный docker build команда вместо того, чтобы пройти через Maven? Вы можете использовать базовое изображение Maven, что-то вроде maven:onbuild четное. Пример здесь может помочь.

У меня была такая же проблема: я не хочу жестко кодировать версию проекта в моем Dockerfile.

Сначала я подумал об удалении версии в имени файла jar (это можно сделать с помощью вашего инструмента сборки, я лично использую gradle). Тем не менее, я был очень недоволен этим, так как считаю, что версия в имени jar является хорошей практикой ( например , в этом вопросе есть интерактивная дискуссия ).

Итак, я придумал это решение: скопировать/добавить банку с помощью подстановочного знака :

      FROM eclipse-temurin:17-jre-alpine
WORKDIR /app/
COPY ./path/to/my/jar/*.jar /app/my-app.jar
ENTRYPOINT ["java", "-jar",  "/app/my-app.jar"]

Здесь мне удалось заставить мой инструмент сборки создавать только ту банку, которую я хочу, в своей папке. Дело в том, чтобы иметь способ использовать подстановочный знак, чтобы получить эту единственную банку без двусмысленности.

Другие вопросы по тегам