关于Dockerfile镜像制作完整实例
作者:天黑请闭眼
本文以实际应用发版为例,详细表述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/null
2、构件镜像
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脚本控制
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。