本文以实际应用发版为例,详细表述docker镜像的制作过程,其中包括如何实现动态控制应用程序的启动
目录结构介绍
起始目录

package目录

target目录

sh目录

init.sh脚本
作用:创建网络、启动镜像、挂载目录
#!/bin/bash
# 开始
echo "info: init start"
## ---------------------------------------------------------------------------------
# 容器名称
containername=online_ccs
# 网络名称
networkname=network_test001
# 映射端口(宿主机端口)
# ass-web服务端口
port1=8087
# ass-web服务socket端口
port2=9901
# ass-wechat服务端口
port3=8090
# ccs-web服务端口
port4=8089
# ccs-wechat服务端口
port5=8091
# weixin3rd服务端口
port6=9015
# 挂载根目录(宿主机目录)
dir=$(dirname "$pwd")
# docker服务启动时,自启容器
#rst=${1:-"always"}
# docker服务启动时,不启动容器
rst=${1:-"no"}
## ---------------------------------------------------------------------------------
# 镜像文件
imagefile="$dir"/images/img_online_ccs.tar.gz
# 镜像名称
imagename=online_ccs:1.4.1.20241113_release
# 工作目录(容器目录)
workdir=/app
###创建网络的作用,文章后边会补充
# 检查docker的网络名称是否存在network_test001,不存在则创建
res=$(docker network ls --format '{{.name}}' | grep $networkname)
if [ ! "$res" == "$networkname" ]; then
echo "info: create network [$networkname]"
res=$(docker network create --subnet=172.21.0.0/16 $networkname)
if [ ! -n "$res" ]; then
echo "error: create network [$networkname] fail"
exit 1
fi
fi
# 检查docker镜像是否存在
if [ ! -f "$imagefile" ]; then
echo "error: $imagefile file not found"
exit 1
fi
# 导入docker镜像
echo "info: import image [$imagefile]"
res=$(docker load -i "$imagefile")
echo "$res"
# 运行docker镜像
###-v的都是挂载的目录,这里主要挂载的是前后端的配置文件、日志文件,实现公共读写的功能
echo "info: the image [$imagefile] is running"
res=$(docker run --name $containername --restart=$rst --network=$networkname --ip=172.21.0.6 \
-p $port1:8087 \
-p $port2:9901 \
-p $port3:8090 \
-p $port4:8089 \
-p $port5:8091 \
-p $port6:9015 \
-v $dir/config:$workdir/config \
-v $dir/java/fs_web_ass/appid.properties:$workdir/tomcat8-ass-cloud-web-8087/webapps/fs_web_ass/web-inf/classes/appid.properties \
-v $dir/java/fs_web_ass/application.properties:$workdir/tomcat8-ass-cloud-web-8087/webapps/fs_web_ass/web-inf/classes/application.properties \
-v $dir/java/fs_web_ass/asr.properties:$workdir/tomcat8-ass-cloud-web-8087/webapps/fs_web_ass/web-inf/classes/asr.properties \
-v $dir/java/fs_web_ass/config.properties:$workdir/tomcat8-ass-cloud-web-8087/webapps/fs_web_ass/web-inf/classes/config.properties \
-v $dir/java/fs_web_ass/logback-spring.xml:$workdir/tomcat8-ass-cloud-web-8087/webapps/fs_web_ass/web-inf/classes/logback-spring.xml \
-v $dir/java/fs_web_ass/mybatis-config.xml:$workdir/tomcat8-ass-cloud-web-8087/webapps/fs_web_ass/web-inf/classes/mybatis-config.xml \
-v $dir/java/fs_web_ass/rocketmq.properties:$workdir/tomcat8-ass-cloud-web-8087/webapps/fs_web_ass/web-inf/classes/rocketmq.properties \
-v $dir/java/fs_web_ass/shardingdatasource.properties:$workdir/tomcat8-ass-cloud-web-8087/webapps/fs_web_ass/web-inf/classes/shardingdatasource.properties \
-v $dir/java/fs_web_ass/spring.properties:$workdir/tomcat8-ass-cloud-web-8087/webapps/fs_web_ass/web-inf/classes/spring.properties \
-v $dir/java/fs_wechat_ass/appid.properties:$workdir/tomcat8-ass-cloud-wechat-8090/webapps/fs_wechat_ass/web-inf/classes/appid.properties \
-v $dir/java/fs_wechat_ass/application.properties:$workdir/tomcat8-ass-cloud-wechat-8090/webapps/fs_wechat_ass/web-inf/classes/application.properties \
-v $dir/java/fs_wechat_ass/asr.properties:$workdir/tomcat8-ass-cloud-wechat-8090/webapps/fs_wechat_ass/web-inf/classes/asr.properties \
-v $dir/java/fs_wechat_ass/config.properties:$workdir/tomcat8-ass-cloud-wechat-8090/webapps/fs_wechat_ass/web-inf/classes/config.properties \
-v $dir/java/fs_wechat_ass/logback-spring.xml:$workdir/tomcat8-ass-cloud-wechat-8090/webapps/fs_wechat_ass/web-inf/classes/logback-spring.xml \
-v $dir/java/fs_wechat_ass/mybatis-config.xml:$workdir/tomcat8-ass-cloud-wechat-8090/webapps/fs_wechat_ass/web-inf/classes/mybatis-config.xml \
-v $dir/java/fs_wechat_ass/rocketmq.properties:$workdir/tomcat8-ass-cloud-wechat-8090/webapps/fs_wechat_ass/web-inf/classes/rocketmq.properties \
-v $dir/java/fs_wechat_ass/shardingdatasource.properties:$workdir/tomcat8-ass-cloud-wechat-8090/webapps/fs_wechat_ass/web-inf/classes/shardingdatasource.properties \
-v $dir/java/fs_wechat_ass/spring.properties:$workdir/tomcat8-ass-cloud-wechat-8090/webapps/fs_wechat_ass/web-inf/classes/spring.properties \
-v $dir/java/fs_web_ccs/appid.properties:$workdir/tomcat8-ccs-cloud-web-8089/webapps/fs_web_ccs/web-inf/classes/appid.properties \
-v $dir/java/fs_web_ccs/application.properties:$workdir/tomcat8-ccs-cloud-web-8089/webapps/fs_web_ccs/web-inf/classes/application.properties \
-v $dir/java/fs_web_ccs/config.properties:$workdir/tomcat8-ccs-cloud-web-8089/webapps/fs_web_ccs/web-inf/classes/config.properties \
-v $dir/java/fs_web_ccs/logback.xml:$workdir/tomcat8-ccs-cloud-web-8089/webapps/fs_web_ccs/web-inf/classes/logback.xml \
-v $dir/java/fs_web_ccs/mybatis-config.xml:$workdir/tomcat8-ccs-cloud-web-8089/webapps/fs_web_ccs/web-inf/classes/mybatis-config.xml \
-v $dir/java/fs_web_ccs/nacos.properties:$workdir/tomcat8-ccs-cloud-web-8089/webapps/fs_web_ccs/web-inf/classes/nacos.properties \
-v $dir/java/fs_web_ccs/rocketmq.properties:$workdir/tomcat8-ccs-cloud-web-8089/webapps/fs_web_ccs/web-inf/classes/rocketmq.properties \
-v $dir/java/fs_web_ccs/shardingdatasource.properties:$workdir/tomcat8-ccs-cloud-web-8089/webapps/fs_web_ccs/web-inf/classes/shardingdatasource.properties \
-v $dir/java/fs_web_ccs/snowflake.yml:$workdir/tomcat8-ccs-cloud-web-8089/webapps/fs_web_ccs/web-inf/classes/snowflake.yml \
-v $dir/java/fs_web_ccs/spring.properties:$workdir/tomcat8-ccs-cloud-web-8089/webapps/fs_web_ccs/web-inf/classes/spring.properties \
-v $dir/java/fs_wechat_ccs/appid.properties:$workdir/tomcat8-ccs-cloud-wechat-8091/webapps/fs_wechat_ccs/web-inf/classes/appid.properties \
-v $dir/java/fs_wechat_ccs/application.properties:$workdir/tomcat8-ccs-cloud-wechat-8091/webapps/fs_wechat_ccs/web-inf/classes/application.properties \
-v $dir/java/fs_wechat_ccs/config.properties:$workdir/tomcat8-ccs-cloud-wechat-8091/webapps/fs_wechat_ccs/web-inf/classes/config.properties \
-v $dir/java/fs_wechat_ccs/logback.xml:$workdir/tomcat8-ccs-cloud-wechat-8091/webapps/fs_wechat_ccs/web-inf/classes/logback.xml \
-v $dir/java/fs_wechat_ccs/mybatis-config.xml:$workdir/tomcat8-ccs-cloud-wechat-8091/webapps/fs_wechat_ccs/web-inf/classes/mybatis-config.xml \
-v $dir/java/fs_wechat_ccs/nacos.properties:$workdir/tomcat8-ccs-cloud-wechat-8091/webapps/fs_wechat_ccs/web-inf/classes/nacos.properties \
-v $dir/java/fs_wechat_ccs/rocketmq.properties:$workdir/tomcat8-ccs-cloud-wechat-8091/webapps/fs_wechat_ccs/web-inf/classes/rocketmq.properties \
-v $dir/java/fs_wechat_ccs/shardingdatasource.properties:$workdir/tomcat8-ccs-cloud-wechat-8091/webapps/fs_wechat_ccs/web-inf/classes/shardingdatasource.properties \
-v $dir/java/fs_wechat_ccs/snowflake.yml:$workdir/tomcat8-ccs-cloud-wechat-8091/webapps/fs_wechat_ccs/web-inf/classes/snowflake.yml \
-v $dir/java/fs_wechat_ccs/spring.properties:$workdir/tomcat8-ccs-cloud-wechat-8091/webapps/fs_wechat_ccs/web-inf/classes/spring.properties \
-v $dir/java/weixin3rd_boot_cloud/application.yml:$workdir/tomcat9_weixin3rd_9015/webapps/weixin3rd_boot_cloud/web-inf/classes/application.yml \
-v $dir/java/weixin3rd_boot_cloud/application-sharding.yml:$workdir/tomcat9_weixin3rd_9015/webapps/weixin3rd_boot_cloud/web-inf/classes/application-sharding.yml \
-v $dir/java/weixin3rd_boot_cloud/config.properties:$workdir/tomcat9_weixin3rd_9015/webapps/weixin3rd_boot_cloud/web-inf/classes/config.properties \
-v $dir/java/weixin3rd_boot_cloud/logback.xml:$workdir/tomcat9_weixin3rd_9015/webapps/weixin3rd_boot_cloud/web-inf/classes/logback.xml \
-v $dir/html/fs_web_ccs/config.js:$workdir/html/fs_web_ccs/static/config.js \
-v $dir/html/fs_web_ccs/images:$workdir/html/fs_web_ccs/static/images \
-v $dir/logs/tomcat8-ass-cloud-web-8087:$workdir/tomcat8-ass-cloud-web-8087/logs \
-v $dir/logs/tomcat8-ass-cloud-wechat-8090:$workdir/tomcat8-ass-cloud-wechat-8090/logs \
-v $dir/logs/tomcat8-ccs-cloud-web-8089:$workdir/tomcat8-ccs-cloud-web-8089/logs \
-v $dir/logs/tomcat8-ccs-cloud-wechat-8091:$workdir/tomcat8-ccs-cloud-wechat-8091/logs \
-v $dir/logs/tomcat9_weixin3rd_9015:$workdir/tomcat9_weixin3rd_9015/logs \
-d $imagename)
echo "$res"
# 结束
echo "info: init finish"
start.sh脚本
作用:启动容器
docker start online_ccs
stop.sh脚本
作用:停止容器
docker stop online_ccs
restart.sh脚本
作用:重启容器
docker restart online_ccs
config目录


把需要启动的应用程序配置到server.config,容器启动时,配合script.sh可以实现应用程序的动态启动
步骤
1、编写dockerfile
# 使用官方的openjdk镜像作为基础镜像 from centos:7.9_jdk as build # 配置环境变量 env lang en_us.utf8 env language en_us.utf8 env lc_all en_us.utf8 env tz=asia/shanghai # 设置工作目录 workdir /app # 将本地的tomcat应用程序的文件复制到容器内(这里不会把package目录也复制进去) copy ./package . # 给tomcat设置权限 run chmod +x ./*/bin/*.sh \ && rm -rf ./*/logs/* # 二阶段构建,以减小镜像体积 from centos:7.9_jdk # 配置环境变量 env lang en_us.utf8 env language en_us.utf8 env lc_all en_us.utf8 env tz=asia/shanghai # 设置工作目录 workdir /app copy --from=build /app . # 设置时区 run ln -snf /usr/share/zoneinfo/$tz /etc/localtime && echo $tz > /etc/timezone # 挂载点 volume ["/app/config"] # 当docker容器启动时执行script.sh脚本 cmd ["/app/script.sh", "/app/config/server.config", "/app"]
注:script.sh脚本已经在centos:7.9_jdk镜像里边了,该镜像是私有镜像,因此,实际使用的时候,需要把script.sh复制到容器的app目录下(在package目录补上script.sh脚本)
script.sh脚本
#!/bin/bash
# 检查文件是否存在
if [ ! -f "$1" ]; then
echo "$(date +"%y-%m-%d %h:%m:%s") error: $1 file not found."
exit 1
fi
# 逐行读取文件内容
while ifs= read -r line || [[ -n "$line" ]]
do
# 去除前面的空格
line="${line#"${line%%[![:space:]]*}"}"
# 去除后面的空格
line="${line%"${line##*[![:space:]]}"}"
# 跳过空行、或者以#开头
if [[ ! -z "$line" ]] && [[ ! "$line" == \#* ]]; then
echo "$(date +"%y-%m-%d %h:%m:%s") exec: $2/$line/bin/startup.sh run"
# 执行命令 (catalina.sh run方式启动,catalina.out不会输出)
sh -c "cd $2/$line/bin && ./startup.sh"
fi
done < "$1"
# 结束
echo "$(date +"%y-%m-%d %h:%m:%s") all commands executed."
# 目的维持容器运行
tail -f /dev/null2、构件镜像
docker build . -t 镜像名称:标签

3、保存镜像到本地服务器
docker save 镜像名称:标签 -o 文件名称

4、复制镜像文件到指定目录
并执行init.sh脚本

注:init.sh脚本只在第一次运行的时候执行,后续启动与关闭通过start.sh、stop.sh、restart.sh脚本控制
5、查看挂载的日志目录
查看tomcat日志,看程序是否正常启动

里边确实有tomcat启动的日志,这里忘记截图了
6、访问测试
这里只访问镜像中其中一个tomcat的接口

7、容器配置ip的作用
docker容器的ip地址在容器网络中扮演着至关重要的角色,主要体现在以下几个方面:
- 网络通信:每个docker容器都有一个唯一的内部ip地址,这个ip地址是docker内部网络中的地址,用于容器之间的通信。容器可以通过这个内部ip地址与其他容器进行通信,就像在同一个局域网中一样。
- 网络配置:在docker中设置静态ip可以确保容器始终具有相同的ip地址,从而稳定地进行网络通信。这有助于提高网络通信的稳定性和可靠性,并且使得管理和监控变得更加容易。
- 负载均衡:虚拟ip(vip)可以使容器以简化的方式进行通信,而不需要直接使用宿主机的ip地址。在负载均衡场景中,外部请求通过虚拟ip被路由到不同的容器,从而实现了请求的分散处理。
- 隔离与安全:docker网络启用虚拟ip后,可以将不同的网络隔离开,增强安全性。这意味着容器只与同一网络中的其他容器通信,从而提高了容器的安全性。
- 动态ip管理:docker会自动处理容器ip的分配和回收,开发者无需关心容器的ip地址变化,这简化了容器的部署和管理过程。
总的来说,docker容器的ip地址在网络通信、负载均衡、隔离与安全以及动态ip管理等方面都发挥着重要作用,确保了容器的稳定运行和高效管理。
总结
如果以本例的目录结构为模板,构件新的镜像,只需要调整的文件如下
1、将需要打包的文件放到package(记得补上script.sh脚本)
2、调整init.sh脚本
3、如果觉得target目录结构太复杂,完全可以省去,将镜像打包成功就算结束,容器的启动与创建直接通过sh脚本控制
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论