Запуск java с помощью аргументов в Docker

#java #docker

#Ява #докер

Вопрос:

Допустим, у нас есть следующий файл Dockerfile для создания образа java и компиляции двух сценариев.

 FROM openjdk:latest COPY src JavaDocker WORKDIR JavaDocker RUN mkdir -p bin RUN javac -d bin ./com/myapp/HelloWorld1.java RUN javac -d bin ./com/myapp/HelloWorld2.java WORKDIR bin ENTRYPOINT java  

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

Я использую команду: docker run myapp-image "com.myapp.Server"

И я получаю:

 Usage: java [options] lt;mainclassgt; [args...]  (to execute a class)  or java [options] -jar lt;jarfilegt; [args...]  (to execute a jar file)  or java [options] -m lt;modulegt;[/lt;mainclassgt;] [args...]  java [options] --module lt;modulegt;[/lt;mainclassgt;] [args...]  (to execute the main class in a module)  or java [options] lt;sourcefilegt; [args]  (to execute a single source-file program)   Arguments following the main class, source file, -jar lt;jarfilegt;,  -m or --module lt;modulegt;/lt;mainclassgt; are passed as the arguments to  main class.  

Ответ №1:

Я бы предложил создать отдельное изображение для каждого приложения; это может помочь уточнить, что должно делать изображение. Я также обычно рекомендую использовать CMD over ENTRYPOINT .

Таким образом, файл Dockerfile, который запускает только первое приложение, может выглядеть так:

 FROM openjdk:latest  # Prefer an absolute path for clarity. WORKDIR /JavaDocker  # Set up the Java class path. RUN mkdir bin ENV CLASSPATH=/JavaDocker/bin  # Use a relative path as the target, to avoid repeating it. # (If you change the source code, repeating `docker build` will # skip everything before here.) COPY src .  # Compile the application. RUN javac -d bin ./com/myapp/HelloWorld1.java  # Set the main container command. CMD ["java", "com.myapp.HelloWorld1"]  

Что делать, если у вас есть изображение, содержащее несколько приложений? Если вы используете CMD здесь, очень легко предоставить альтернативную команду при запуске образа:

 docker run myapp-image   java com.myapp.HelloWorld2  # Wait, what's actually in this image? docker run --rm myapp-image   ls -l bin/com/myapp  

Обычно я рекомендую зарезервировать ENTRYPOINT сценарий-оболочку, который выполняет некоторую настройку в первый раз, а затем запускается exec "$@" для выполнения обычного CMD . Существует альтернативный способ ввода полной команды ENTRYPOINT и использования CMD для предоставления ее аргументов. В обоих этих случаях ENTRYPOINT должен быть синтаксис JSON-массива, а не синтаксис оболочки.

 ENTRYPOINT ["java", "com.myapp.HelloWorld1"] # lt;-- JSON-array syntax CMD ["-argument", "to-program-1"]  
 docker run myapp-image   -argument=different -options  

но труднее заставить этот образ делать что-то другое

 docker run   --entrypoint ls  # lt;-- first word of the command is before the image name  myapp-image   -l bin/com/myapp # lt;-- and the rest after  docker run   --entrypoint java   myapp-image   com.myapp.HelloWorld2  

Ваш исходный файл Dockerfile, вероятно, будет работать, если вы измените ENTRYPOINT строку с синтаксиса оболочки на синтаксис массива JSON; использование синтаксиса оболочки приведет к CMD игнорированию части (включая команду, переданную после docker run image-name ). Возможно, вам будет проще сделать один полный вызов приложения по умолчанию и включить java команду, если вам нужно запустить другой.