我的Dockerfile是:
FROM maven:3.3.9-jdk-8-alpine as build-env
COPY . /EscomledML
WORKDIR EscomledML
RUN mvn package
FROM openjdk:8-jdk-alpine
WORKDIR /EscomledML
ADD . /EscomledML
ADD ./lib EscomledML/lib
ADD ./config EscomledML/config
ADD ./config EscomledML/home/escomled/escomled_server/config
ADD ./MLScripts EscomledML/MLScripts
ADD target/escomled-machine-learning-0.0.1-SNAPSHOT-jar-with-dependencies.jar EscomledML/lib/escomled-machine-learning-0.0.1-SNAPSHOT-jar-with-dependencies.jar
EXPOSE 8085
RUN ["sh", "EscomledML/MLScripts/escomled_data_grid.sh"]
RUN ["sh", "EscomledML/MLScripts/escomled_dirwatcher.sh"]
RUN ["sh", "EscomledML/MLScripts/escomled_startmap.sh"]
RUN ["sh", "EscomledML/MLScripts/escomled_ml.sh"]
这些脚本基本上将依赖项jar添加到classpath并启动所需的类,例如。 “ java ${ARGS} -classpath "${CLASSPATH}" com.escomled.blackboard.main.DataGridServer
”。
运行docker-compose up --build
时,脚本没有任何输出。
docker ps -a
返回
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ce690dbba3ab escomled-ml "/bin/sh" 2 minutes ago Exited (0) 2 minutes ago desktop_escomled-ml_1
答案 0 :(得分:1)
如何防止Dockerfile中的脚本退出?
关于RUN
,您不能/应该。
这不是应该的工作方式。 RUN
用于构建图像的阶段。它应该完成任务,完成并继续下一个Dockerfile命令。
从文档中
RUN
指令将在当前图像顶部的新层中执行所有命令,并提交结果。生成的提交图像将用于Dockerfile
中的下一步。
启动容器时应运行的脚本可以通过ENTRYPOINT
和CMD
声明的组合来设置。
答案 1 :(得分:1)
对于以下dockerfile:
FROM ubuntu:18.04
RUN echo a
CMD ["bash","-c","echo b && echo c; while true; do sleep 5; echo sleep; done"];
运行以下命令:
docker build -t test1 . && docker run test1
您会注意到:
echo a
在构建时执行echo b
和echo c
和echo sleep
在运行时执行现在,您可以在文件中使用结构类似的COMMAND,它应该可以工作。
答案 2 :(得分:0)
如果我正确理解原始Dockerfile中的每一行RUN
都对应一个服务(这是您要在Docker容器停止之前运行的进程)。问题在于,Docker容器需要一个在前台运行,在容器启动时启动并在容器停止时停止的主进程。另外,当主进程退出时(例如,由于引发异常),容器将自动停止。
为了在单个容器中运行多个进程,您需要使用一个进程管理器,该进程管理器将由该容器启动,然后将启动您的服务,监视它们并在出现故障的情况下重新启动它们,或者启动一个包装器脚本您的服务并检查它们是否还活着。 Docker documentation建议使用supervisord
。
在您的情况下,包装器将类似于:
#!/bin/bash
# Start the first process
/EscomledML/MLScripts/escomled_data_grid.sh -D
status=$?
if [ $status -ne 0 ]; then
echo "Failed to start escomled_data_grid: $status"
exit $status
fi
# Start the second process
/EscomledML/MLScripts/escomled_dirwatcher.sh -D
status=$?
if [ $status -ne 0 ]; then
echo "Failed to start escomled_dirwatcher: $status"
exit $status
fi
# Start the third process
/EscomledML/MLScripts/escomled_startmap.sh -D
status=$?
if [ $status -ne 0 ]; then
echo "Failed to start escomled_startmap: $status"
exit $status
fi
# Start the fourth process
/EscomledML/MLScripts/escomled_ml.sh -D
status=$?
if [ $status -ne 0 ]; then
echo "Failed to start escomled_ml: $status"
exit $status
fi
# Naive check runs checks once a minute to see if either of the processes exited.
# This illustrates part of the heavy lifting you need to do if you want to run
# more than one service in a container. The container exits with an error
# if it detects that either of the processes has exited.
# Otherwise it loops forever, waking up every 60 seconds
while sleep 60; do
ps aux |grep escomled_data_grid |grep -q -v grep
PROCESS_1_STATUS=$?
ps aux |grep escomled_dirwatcher |grep -q -v grep
PROCESS_2_STATUS=$?
ps aux |grep escomled_startmap |grep -q -v grep
PROCESS_3_STATUS=$?
ps aux |grep escomled_ml |grep -q -v grep
PROCESS_4_STATUS=$?
# If the greps above find anything, they exit with 0 status
# If they are not both 0, then something is wrong
if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 -o $PROCESS_3_STATUS -ne 0 -o $PROCESS_4_STATUS -ne 0 ]; then
echo "One of the processes has already exited."
exit 1
fi
done
尽管很可能您需要在while循环中修改grep条件,以准确匹配脚本正在启动的任何进程。然后假设您将脚本命名为“ wrapper.sh”
您将以下行放入Dockerfile中: COPY wrapper.sh /EscomledML/MLScripts/wrapper.sh ENTRYPOINT [“ EscomledML / MLScripts / wrapper.sh”]
我个人建议使用supervisored
而不是包装脚本,但这取决于您。