How to have two JARs start automatically on “docker run container”

狂风中的少年 提交于 2020-01-02 04:04:50

问题


I want two seperate JAR files to be executed automatically once a docker container is called via run command, so when I type docker run mycontainer they are both called. So far, I have a dockerfile that looks like this:

# base image is java:8 (ubuntu)
FROM java:8

# add files to image 
ADD first.jar .
ADD second.jar .

# start on run
CMD ["/usr/lib/jvm/java-8-openjdk-amd64/bin/java", "-jar", "first.jar"]
CMD ["/usr/lib/jvm/java-8-openjdk-amd64/bin/java", "-jar", "second.jar"]

This, however, only starts second.jar.

Now, both jars are servers in a loop, so I guess once one is started it just blocks the terminal. If I run the container using run -it mycontainer bash and call them manually, too, the first one will do its outputs and I can't start the other one.

Is there a way to open different terminals and switch between them to have each JAR run in its own context? Preferably already in the dockerfile.

I know next to nothing about ubuntu but I found the xterm command that opens a new terminal, however this won't work after calling a JAR. What I'm looking for are instructions for inside the dockerfile that for example open a new terminal, execute first.jar, alt-tab into the old terminal and execute second.jar there, or at least achieve the same.

Thanks!


回答1:


The second CMD instruction replaces the first, so you need to use a single instruction for both commands.

Easy (not so good) Approach

You could add a bash script that executes both commands and blocks on the second one:

# start.sh
/usr/lib/jvm/java-8-openjdk-amd64/bin/java -jar first.jar &
/usr/lib/jvm/java-8-openjdk-amd64/bin/java -jar second.jar

Then change your Dockerfile to this:

# base image is java:8 (ubuntu)
FROM java:8

# add files to image 
ADD first.jar .
ADD second.jar .
ADD start.sh .

# start on run
CMD ["bash", "start.sh"]

When using docker stop it might not shut down properly, see: https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/

Better Approach

To solve this, you could use Phusion: https://hub.docker.com/r/phusion/baseimage/
It has an init-system that is much easier to use than e.g. supervisord.

Here is a good starting point: https://github.com/phusion/baseimage-docker#getting_started

Instructions for using phusion

Sadly there is not official openjdk-8-jdk available for Ubuntu 14.04 LTS. You could try with an inofficial ppa, which is used in the following explanation.

In your case you would need to bash scripts (which act like "services"):

# start-first.sh (the file has to start with the following line!):
#!/bin/bash
usr/lib/jvm/java-8-openjdk-amd64/bin/java -jar /root/first.jar

# start-second.sh
#!/bin/bash
usr/lib/jvm/java-8-openjdk-amd64/bin/java -jar /root/second.jar

And your Dockerfile would look like this:

# base image is phusion
FROM phusion/baseimage:latest

# Use init service of phusion
CMD ["/sbin/my_init"]

# Install unofficial openjdk-8
RUN add-apt-repository ppa:openjdk-r/ppa && apt-get update && apt-get dist-upgrade -y && apt-get install -y openjdk-8-jdk

ADD first.jar /root/first.jar
ADD second.jar /root/second.jar

# Add first service
RUN mkdir /etc/service/first
ADD start-first.sh /etc/service/first/run
RUN chmod +x /etc/service/first/run

# Add second service
RUN mkdir /etc/service/second
ADD start-second.sh /etc/service/second/run
RUN chmod +x /etc/service/second/run

# Clean up
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

This should install two services which will be run on startup and shut down properly when using docker stop.




回答2:


A Docker container has only a single process when it is started.

You can still create several processes afterward.:

  • One simple way is to create a second process inside a bash script.
  • You can also use Supervisor : https://docs.docker.com/articles/using_supervisord/



回答3:


You have a few options. A lot of the answers have mentioned using supervisor for this, which is a fine solution. Here are some others:

Create a short script that just kicks off both jars. Add that to your CMD. For example, the script, which we'll call run_jars.sh could look like:

/usr/lib/jvm/java-8-openjdk-amd64/bin/java -jar first.jar;
/usr/lib/jvm/java-8-openjdk-amd64/bin/java -jar second.jar;

Then your CMD would be CMD sh run_jars.sh

Another alternative is just running two separate containers-- one for first.jar and the other for second.jar. You can run each one through docker run, for example:

docker run my_repo/my_image:some_tag /usr/lib/jvm/java-8-openjdk-amd64/bin/java -jar second.jar




回答4:


If you want to start two different processes inside one docker container (not recommanded behaviour) you can use something like supervisord



来源:https://stackoverflow.com/questions/33283916/how-to-have-two-jars-start-automatically-on-docker-run-container

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!