当前位置:首页 > 站长知识 > 服务器 > 正文内容

Dockerfile镜像制作教程

2024-12-02服务器37

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

目录结构介绍

起始目录

package目录

target目录

sh目录

init.sh脚本

作用:创建网络、启动镜像、挂载目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/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脚本

作用:启动容器

1
docker start online_ccs

stop.sh脚本

作用:停止容器

1
docker stop online_ccs

restart.sh脚本

作用:重启容器

1
docker restart online_ccs

config目录

把需要启动的应用程序配置到server.config,容器启动时,配合script.sh可以实现应用程序的动态启动

步骤

1、编写dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 使用官方的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脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/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脚本控制