docker是一个非常方便的部署工具,一般来说我们会把每个jar包打成一个docker镜像,如果jar包非常多,就会非常占资源,所以就直接一个容器多个jar运行,做个笔记以防忘记,内容多为copy而来。

首先需要一个Dockerfile文件

# 环境
FROM java:8
# 作者信息
MAINTAINER wyler "467135974@qq.com"
# 将本地文件tmp挂载到容器
VOLUME /tmp
#拷贝
COPY run.sh /run.sh
COPY gateway-0.0.1-SNAPSHOT.jar /gateway-0.0.1-SNAPSHOT.jar
COPY admin-client-0.0.1-SNAPSHOT.jar /admin-client-0.0.1-SNAPSHOT.jar
COPY device-client-0.0.1-SNAPSHOT.jar /device-client-0.0.1-SNAPSHOT.jar
COPY admin-server-0.0.1-SNAPSHOT.jar /admin-server-0.0.1-SNAPSHOT.jar
COPY device-server-0.0.1-SNAPSHOT.jar /device-server-0.0.1-SNAPSHOT.jar
# RUN命令
RUN chmod 777 /run.sh 
# 执行命令
ENTRYPOINT ["/run.sh"]

然后还有一个run.sh文件

 #!/bin/bash
start1(){
    echo "starting gateway....."
    nohup java -jar /gateway-0.0.1-SNAPSHOT.jar > gateway.log &
}
start2(){
    echo "starting admin-client....."
    nohup java -jar /admin-client-0.0.1-SNAPSHOT.jar > adminclient.log &

start3(){
    echo "starting device-client....."
    nohup java -jar /device-client-0.0.1-SNAPSHOT.jar > deviceclient.log &
}
start4(){
    echo "starting admin-server....."
    nohup java -jar /admin-server-0.0.1-SNAPSHOT.jar > adminserver.log &
}
start5(){
    echo "starting device-server....."
    nohup java -jar /device-server-0.0.1-SNAPSHOT.jar > deviceserve.log &
}
#定义一个方法pid_health_check $1是这个方法的参数,其他地方调用此方法传入进来
pid_health_check(){
    #定义一个linux的命令字符串 $1是这个方法的参数类似于(ps -ef|grep tomcat 的命令),其他地方调用此方法传入进来
    #这个命令解释: 搜索linux中的进程 并且过滤掉-带grep的那条 
    process_cnt=`ps -ef | grep $1 | grep -v grep | wc -l`
    #表示执行上面定义的process_cnt命令
    echo $process_cnt
    #返回值-上面命令查询出来的日志的条数
    return $?
}
##在脚本最后一行添加tail -f /dev/null,这个命令永远完成不了,所以该脚本一直不会执行完,所以该容器永远不会退出
##tail -f /dev/null
##我这里写的死循环就不用上面的那个查看日志的命令了
start1
start2
start3
start4
start5
 
while [[ 1 -gt 0 ]]
do
    echo "check healthy of gateway...."
    process_cnt=$(pid_health_check gateway-0.0.1-SNAPSHOT)
    ##if语句 (ps -ef|grep relations-analysis)查询结果小于1表示此服务已经停了
    if [[ $process_cnt -lt 1 ]]
    then
        start1
    fi
    echo "check healthy of admin-client...."
    process_cnt=$(pid_health_check admin-client-0.0.1-SNAPSHOT)
    if [[ $process_cnt -lt 1 ]]
    then
        start2
    fi
    echo "check healthy of device-client...."
    process_cnt=$(pid_health_check device-client-0.0.1-SNAPSHOT)
    if [[ $process_cnt -lt 1 ]]
    then
        start3
    fi
    echo "check healthy of admin-server...."
    process_cnt=$(pid_health_check admin-server-0.0.1-SNAPSHOT)
    if [[ $process_cnt -lt 1 ]]
    then
        start4
    fi
    echo "check healthy of device-server...."
    process_cnt=$(pid_health_check device-server-0.0.1-SNAPSHOT)
    if [[ $process_cnt -lt 1 ]]
    then
        start5
    fi
    ##睡眠1
    sleep 1m
done
 

 自己有多少个jar就写多少个start方法,run.sh里的  /admin-client-0.0.1-SNAPSHOT.jar 是与Dockerfile里 /admin-client-0.0.1-SNAPSHOT.jar 是对应的。

 

运行docker命令打包镜像

docker build -t cloud .

注意后面的 . 不能省略

运行打包成功后的镜像容器

docker run -d --name cloud --restart=always -p 8799:8799 cloud

--restart=always 表示一直运行  -p 表示映射的端口,可以映射多个,这里我是把我的网关服务端口映射出来,毕竟我只需要这个端口来作为访问入口。 

还有个容易出现的小问题,可能运行容器时会失败,可以通过  docker logs cloud 查看日志报错

可能会看到如下错误:

standard_init_linux.go:178: exec user process caused "no such file or directory"
standard_init_linux.go:178: exec user process caused "no such file or directory"
standard_init_linux.go:178: exec user process caused "no such file or directory"

原因是镜像的entrypoint设置的启动脚本格式是dos,在linux系统上用vi修改成unix格式即可

# vi filename(run.sh)
# :set ff  回车后看到当前文件的fileformat格式
# :set ff=unix 回车后输入:wq保存文件,重新build镜像即可。

 

添加日志分割版本

安装cronolog

yum install cronolog

 

查看cronolog

which cronolog

run.sh

#!/bin/bash
start1(){
    echo "starting gateway....."
    nohup java -jar /gateway-0.0.1-SNAPSHOT.jar | /usr/sbin/cronolog /logs/gateway/gateway-%Y-%m-%d.log &
}
start2(){
    echo "starting admin-client....."
    nohup java -jar /admin-client-0.0.1-SNAPSHOT.jar | /usr/sbin/cronolog /logs/adminclient/adminclient-%Y-%m-%d.log &

start3(){
    echo "starting device-client....."
    nohup java -jar /device-client-0.0.1-SNAPSHOT.jar | /usr/sbin/cronolog /logs/deviceclient/deviceclient-%Y-%m-%d.log &
}
start4(){
    echo "starting admin-server....."
    nohup java -jar /admin-server-0.0.1-SNAPSHOT.jar | /usr/sbin/cronolog /logs/adminserver/adminserver-%Y-%m-%d.log &
}
start5(){
    echo "starting device-server....."
    nohup java -jar /device-server-0.0.1-SNAPSHOT.jar | /usr/sbin/cronolog /logs/deviceserver/deviceserver-%Y-%m-%d.log &
}
#定义一个方法pid_health_check $1是这个方法的参数,其他地方调用此方法传入进来
pid_health_check(){
    #定义一个linux的命令字符串 $1是这个方法的参数类似于(ps -ef|grep tomcat 的命令),其他地方调用此方法传入进来
    #这个命令解释: 搜索linux中的进程 并且过滤掉-带grep的那条 
    process_cnt=`ps -ef | grep $1 | grep -v grep | wc -l`
    #表示执行上面定义的process_cnt命令
    echo $process_cnt
    #返回值-上面命令查询出来的日志的条数
    return $?
}
##在脚本最后一行添加tail -f /dev/null,这个命令永远完成不了,所以该脚本一直不会执行完,所以该容器永远不会退出
##tail -f /dev/null
##我这里写的死循环就不用上面的那个查看日志的命令了
start1
start2
start3
start4
start5
 
while [[ 1 -gt 0 ]]
do
    echo "check healthy of gateway...."
    process_cnt=$(pid_health_check gateway-0.0.1-SNAPSHOT)
    ##if语句 (ps -ef|grep relations-analysis)查询结果小于1表示此服务已经停了
    if [[ $process_cnt -lt 1 ]]
    then
        start1
    fi
    echo "check healthy of admin-client...."
    process_cnt=$(pid_health_check admin-client-0.0.1-SNAPSHOT)
    if [[ $process_cnt -lt 1 ]]
    then
        start2
    fi
    echo "check healthy of device-client...."
    process_cnt=$(pid_health_check device-client-0.0.1-SNAPSHOT)
    if [[ $process_cnt -lt 1 ]]
    then
        start3
    fi
    echo "check healthy of admin-server...."
    process_cnt=$(pid_health_check admin-server-0.0.1-SNAPSHOT)
    if [[ $process_cnt -lt 1 ]]
    then
        start4
    fi
    echo "check healthy of device-server...."
    process_cnt=$(pid_health_check device-server-0.0.1-SNAPSHOT)
    if [[ $process_cnt -lt 1 ]]
    then
        start5
    fi
    ##睡眠1
    sleep 1m
done
 

/usr/sbin/cronolog 是通过查看命令获取具体位置

/logs/gateway/gateway-%Y-%m-%d.log 是具体生成的日志

打包  docker build -t cloud .

运行

docker run -d --name cloud --restart=always -p 8799:8799 \
-v /root/logs/gateway:/logs/gateway \
-v /root/logs/adminclient:/logs/adminclient \
-v /root/logs/deviceclient:/logs/deviceclient \
-v /root/logs/adminserver:/logs/adminserver \
-v /root/logs/deviceserver:/logs/deviceserver \
-v /usr/sbin/cronolog:/usr/sbin/cronolog \
cloud

-v 代表挂载,将本地目录与容器内目录挂载 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐