#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
команду, если вам нужно запустить другой.