# 016基础镜像重构之Java21Runtime镜像
构建时间,不包括下载环境包的时间
# 构建工具选型(来自章节d008)
# 里程碑
- 20250902
- 镜像名:kenaito-runtime:jdk21
- 镜像大小:1.11GB
- 构建耗时:111.2s
- 20250903(多阶段构建)
- 镜像名:kenaito-runtime:jdk21
- 镜像大小:742.06MB
- 构建耗时:70.0s
- 20250904(多阶段构建,仅保留jre)
- 镜像名:kenaito-runtime:jre21
- 镜像大小:409MB
- 构建耗时:67.8s
# 20250902
# 下载环境
if [ ! -f "Alibaba_Dragonwell_Standard_21.0.7.0.7.6_x64_linux.tar.gz" ];then
curl -O https://dragonwell.oss-cn-shanghai.aliyuncs.com/21.0.7.0.7%2B6/Alibaba_Dragonwell_Standard_21.0.7.0.7.6_x64_linux.tar.gz
fi
if [ $? -ne 0 ]; then
echo "下载 Alibaba_Dragonwell_Standard_21.0.7.0.7.6_x64_linux.tar.gz 文件失败"
exit 1
fi
# 释放文件,优化大小
rm -rf build
mkdir build
tar -xvf Alibaba_Dragonwell_Standard_21.0.7.0.7.6_x64_linux.tar.gz
if [ $? -ne 0 ]; then
echo "初始化失败"
exit 1
fi
rm -f dragonwell-21.0.7.0.7+6-GA/lib/src.zip
mv dragonwell-21.0.7.0.7+6-GA build/jdk
cd build && pwd
# 压缩成品
tar -czvf jdk.tgz jdk
rm -rf jdk
# 应用控制脚本
cat > appctl.sh << 'EOF'
#!/bin/bash
JAR_NAME="$APP_NAME.jar"
stopApplication(){
# 查找应用进程
PID=$(ps -ef | grep "$JAR_NAME" | grep -v grep | grep -v 'restart.sh' | awk '{print $2}')
# 如果找到进程
if [ -n "$PID" ]; then
echo "找到进程 $JAR_NAME, PID: $PID"
# 发送 SIGTERM 信号 (kill -15)
echo "正在发送 SIGTERM 信号..."
kill -15 $PID
# 等待并检查进程是否终止
COUNT=0
# 最大重试次数
MAX_RETRIES=10
SLEEP_TIME=1
while [ $COUNT -lt $MAX_RETRIES ]; do
if ps -p $PID > /dev/null 2>&1; then
echo "进程仍在运行,等待中... ($((COUNT+1))/$MAX_RETRIES)"
sleep $SLEEP_TIME
COUNT=$((COUNT+1))
else
echo "进程已正常终止"
exit 0
fi
done
# 如果进程仍然存在,使用 kill -9
if ps -p $PID > /dev/null 2>&1; then
echo "进程仍未终止,发送 SIGKILL 信号..."
kill -9 $PID
sleep 1
# 确认进程是否被杀死
if ps -p $PID > /dev/null 2>&1; then
echo "错误: 无法终止进程 $PID"
exit 1
else
echo "进程已被强制终止"
fi
fi
else
echo "未找到 $JAR_NAME 进程"
fi
}
EOF
# 应用重启脚本
cat > restart.sh << 'EOF'
#!/bin/bash
source /home/admin/appctl.sh
if ls /home/admin/app/*.jar >/dev/null 2>&1; then
stopApplication
nohup java -jar $JAR_NAME > /home/admin/app/logs/console.log 2>&1 &
echo "开始启动新的进程..."
fi
sleep 365d
EOF
# Dockerfile
cat > Dockerfile << 'EOF'
FROM alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/alinux3:latest
LABEL MAINTAINER="tianjun@odboy.cn"
ENV TimeZone="Asia/Shanghai"
ENV JAVA_HOME="/home/admin/jdk"
ENV PATH="$PATH:${JAVA_HOME}/bin"
WORKDIR /home/admin
ADD jdk.tgz .
ADD appctl.sh .
ADD restart.sh .
RUN ln -snf /usr/share/zoneinfo/$TimeZone /etc/localtime && echo $TimeZone > /etc/timezone; \
sed -i 's/mirrors.cloud.aliyuncs.com/mirrors.aliyun.com/' /etc/yum.repos.d/*.repo; \
yum install procps -y; \
chmod +x /home/admin/jdk/bin/*; \
chmod +x /home/admin/*.sh;
EXPOSE 8000
ENTRYPOINT ["/home/admin/restart.sh"]
EOF
# 构建镜像(docker可换成buildah)
docker build --no-cache -f Dockerfile -t kenaito-runtime:jdk21 .
if [ $? -ne 0 ]; then
echo "构建镜像失败"
exit 1
fi
# 运行测试
docker run kenaito-runtime:jdk21
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
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
# 20250903
# 下载环境
if [ ! -f "Alibaba_Dragonwell_Standard_21.0.7.0.7.6_x64_linux.tar.gz" ];then
curl -O https://dragonwell.oss-cn-shanghai.aliyuncs.com/21.0.7.0.7%2B6/Alibaba_Dragonwell_Standard_21.0.7.0.7.6_x64_linux.tar.gz
fi
if [ $? -ne 0 ]; then
echo "下载 Alibaba_Dragonwell_Standard_21.0.7.0.7.6_x64_linux.tar.gz 文件失败"
exit 1
fi
# 释放文件,优化大小
rm -rf build
mkdir build
tar -xvf Alibaba_Dragonwell_Standard_21.0.7.0.7.6_x64_linux.tar.gz
if [ $? -ne 0 ]; then
echo "初始化失败"
exit 1
fi
rm -f dragonwell-21.0.7.0.7+6-GA/lib/src.zip
mv dragonwell-21.0.7.0.7+6-GA build/jdk
cd build && pwd
# 压缩成品
tar -czvf jdk.tgz jdk
rm -rf jdk
# 应用控制脚本
cat > appctl.sh << 'EOF'
#!/bin/bash
JAR_NAME="$APP_NAME.jar"
stopApplication(){
# 查找应用进程
PID=$(ps -ef | grep "$JAR_NAME" | grep -v grep | grep -v 'restart.sh' | awk '{print $2}')
# 如果找到进程
if [ -n "$PID" ]; then
echo "找到进程 $JAR_NAME, PID: $PID"
# 发送 SIGTERM 信号 (kill -15)
echo "正在发送 SIGTERM 信号..."
kill -15 $PID
# 等待并检查进程是否终止
COUNT=0
# 最大重试次数
MAX_RETRIES=10
SLEEP_TIME=1
while [ $COUNT -lt $MAX_RETRIES ]; do
if ps -p $PID > /dev/null 2>&1; then
echo "进程仍在运行,等待中... ($((COUNT+1))/$MAX_RETRIES)"
sleep $SLEEP_TIME
COUNT=$((COUNT+1))
else
echo "进程已正常终止"
exit 0
fi
done
# 如果进程仍然存在,使用 kill -9
if ps -p $PID > /dev/null 2>&1; then
echo "进程仍未终止,发送 SIGKILL 信号..."
kill -9 $PID
sleep 1
# 确认进程是否被杀死
if ps -p $PID > /dev/null 2>&1; then
echo "错误: 无法终止进程 $PID"
exit 1
else
echo "进程已被强制终止"
fi
fi
else
echo "未找到 $JAR_NAME 进程"
fi
}
EOF
# 应用重启脚本
cat > restart.sh << 'EOF'
#!/bin/bash
source /home/admin/appctl.sh
if ls /home/admin/app/*.jar >/dev/null 2>&1; then
stopApplication
nohup java -jar $JAR_NAME > /home/admin/app/logs/console.log 2>&1 &
echo "开始启动新的进程..."
fi
sleep 365d
EOF
# Dockerfile
cat > Dockerfile << 'EOF'
FROM alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/alinux3:latest AS installer
LABEL MAINTAINER="tianjun@odboy.cn"
ENV TimeZone="Asia/Shanghai"
RUN ln -snf /usr/share/zoneinfo/$TimeZone /etc/localtime && echo $TimeZone > /etc/timezone; \
sed -i 's/mirrors.cloud.aliyuncs.com/mirrors.aliyun.com/' /etc/yum.repos.d/*.repo; \
yum install procps -y;
FROM alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/alinux3:latest
LABEL MAINTAINER="tianjun@odboy.cn"
ENV TimeZone="Asia/Shanghai"
ENV JAVA_HOME="/home/admin/jdk"
ENV PATH="$PATH:${JAVA_HOME}/bin"
WORKDIR /home/admin
ADD jdk.tgz .
ADD appctl.sh .
ADD restart.sh .
RUN ln -snf /usr/share/zoneinfo/$TimeZone /etc/localtime && echo $TimeZone > /etc/timezone; \
sed -i 's/mirrors.cloud.aliyuncs.com/mirrors.aliyun.com/' /etc/yum.repos.d/*.repo; \
chmod +x /home/admin/jdk/bin/*; \
chmod +x /home/admin/*.sh;
COPY --from=installer /usr/bin/ps /usr/bin/ps
COPY --from=installer /usr/lib64/libprocps.so.7* /usr/lib64/
EXPOSE 8000
ENTRYPOINT ["/home/admin/restart.sh"]
EOF
# 构建镜像(docker可换成buildah)
docker build --no-cache -f Dockerfile -t kenaito-runtime:jdk21 .
if [ $? -ne 0 ]; then
echo "构建镜像失败"
exit 1
fi
# 运行测试
docker run kenaito-runtime:jdk21
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
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
# 20250904
# 下载环境
if [ ! -f "Alibaba_Dragonwell_Standard_21.0.7.0.7.6_x64_linux.tar.gz" ];then
curl -O https://dragonwell.oss-cn-shanghai.aliyuncs.com/21.0.7.0.7%2B6/Alibaba_Dragonwell_Standard_21.0.7.0.7.6_x64_linux.tar.gz
fi
if [ $? -ne 0 ]; then
echo "下载 Alibaba_Dragonwell_Standard_21.0.7.0.7.6_x64_linux.tar.gz 文件失败"
exit 1
fi
# 释放文件,优化大小
rm -rf build
mkdir build
tar -xvf Alibaba_Dragonwell_Standard_21.0.7.0.7.6_x64_linux.tar.gz
if [ $? -ne 0 ]; then
echo "初始化失败"
exit 1
fi
rm -f dragonwell-21.0.7.0.7+6-GA/lib/src.zip
mv dragonwell-21.0.7.0.7+6-GA build/jdk
cd build && pwd
# 压缩成品
tar -czvf jdk.tgz jdk
rm -rf jdk
# 应用控制脚本
cat > appctl.sh << 'EOF'
#!/bin/bash
JAR_NAME="$APP_NAME.jar"
stopApplication(){
# 查找应用进程
PID=$(ps -ef | grep "$JAR_NAME" | grep -v grep | grep -v 'restart.sh' | awk '{print $2}')
# 如果找到进程
if [ -n "$PID" ]; then
echo "找到进程 $JAR_NAME, PID: $PID"
# 发送 SIGTERM 信号 (kill -15)
echo "正在发送 SIGTERM 信号..."
kill -15 $PID
# 等待并检查进程是否终止
COUNT=0
# 最大重试次数
MAX_RETRIES=10
SLEEP_TIME=1
while [ $COUNT -lt $MAX_RETRIES ]; do
if ps -p $PID > /dev/null 2>&1; then
echo "进程仍在运行,等待中... ($((COUNT+1))/$MAX_RETRIES)"
sleep $SLEEP_TIME
COUNT=$((COUNT+1))
else
echo "进程已正常终止"
exit 0
fi
done
# 如果进程仍然存在,使用 kill -9
if ps -p $PID > /dev/null 2>&1; then
echo "进程仍未终止,发送 SIGKILL 信号..."
kill -9 $PID
sleep 1
# 确认进程是否被杀死
if ps -p $PID > /dev/null 2>&1; then
echo "错误: 无法终止进程 $PID"
exit 1
else
echo "进程已被强制终止"
fi
fi
else
echo "未找到 $JAR_NAME 进程"
fi
}
EOF
# 应用重启脚本
cat > restart.sh << 'EOF'
#!/bin/bash
source /home/admin/appctl.sh
if ls /home/admin/app/*.jar >/dev/null 2>&1; then
stopApplication
nohup java -jar $JAR_NAME > /home/admin/app/logs/console.log 2>&1 &
echo "开始启动新的进程..."
fi
sleep 365d
EOF
# Dockerfile
cat > Dockerfile << 'EOF'
FROM alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/alinux3:latest AS installer
LABEL MAINTAINER="tianjun@odboy.cn"
ENV TimeZone="Asia/Shanghai"
RUN ln -snf /usr/share/zoneinfo/$TimeZone /etc/localtime && echo $TimeZone > /etc/timezone; \
sed -i 's/mirrors.cloud.aliyuncs.com/mirrors.aliyun.com/' /etc/yum.repos.d/*.repo; \
yum install procps -y;
WORKDIR /home/admin
ADD jdk.tgz .
RUN cd jdk && \
rm -f jmods/._*.jmod && \
./bin/jlink --module-path jmods --add-modules java.desktop --output jre
FROM alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/alinux3:latest
LABEL MAINTAINER="tianjun@odboy.cn"
ENV TimeZone="Asia/Shanghai"
ENV JAVA_HOME="/home/admin/jre"
ENV PATH="$PATH:${JAVA_HOME}/bin"
WORKDIR /home/admin
ADD appctl.sh .
ADD restart.sh .
RUN ln -snf /usr/share/zoneinfo/$TimeZone /etc/localtime && echo $TimeZone > /etc/timezone; \
sed -i 's/mirrors.cloud.aliyuncs.com/mirrors.aliyun.com/' /etc/yum.repos.d/*.repo; \
chmod +x /home/admin/jre/bin/*; \
chmod +x /home/admin/*.sh;
COPY --from=installer /usr/bin/ps /usr/bin/ps
COPY --from=installer /usr/lib64/libprocps.so.7* /usr/lib64/
COPY --from=installer /home/admin/jdk/jre/ /home/admin/jre/
EXPOSE 8000
ENTRYPOINT ["/home/admin/restart.sh"]
EOF
# 构建镜像(docker可换成buildah)
docker build --no-cache -f Dockerfile -t kenaito-runtime:jre21 .
if [ $? -ne 0 ]; then
echo "构建镜像失败"
exit 1
fi
# 运行测试
docker run kenaito-runtime:jre21
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
128
129
130
131
132
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
128
129
130
131
132