-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdocker-run.sh
More file actions
executable file
·286 lines (250 loc) · 7.9 KB
/
docker-run.sh
File metadata and controls
executable file
·286 lines (250 loc) · 7.9 KB
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
#!/bin/sh
# ========================
# 国际化设置
# ========================
if [ -z "$LANGUAGE" ]; then
# 语言选择功能
echo "请选择语言 / Please select language:"
echo "1) 中文"
echo "2) English"
# 根据选择设置LANGUAGE环境变量
while true; do
read -p "> (1/2): " lang_choice
case $lang_choice in
1)
export LANGUAGE="zh"
break
;;
2)
export LANGUAGE="en"
break
;;
*)
echo "无效选择 / Invalid choice"
;;
esac
done
else
case "$LANGUAGE" in
*zh*|*CN*)
export LANGUAGE="zh"
;;
*)
export LANGUAGE="en"
;;
esac
fi
# 加载语言文件
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
LANG_DIR="$SCRIPT_DIR/langs"
load_language() {
local lang_file="$LANG_DIR/${1}.sh"
if [ -f "$lang_file" ]; then
# shellcheck source=/dev/null
. "$lang_file"
echo "Loaded language file: $lang_file" >&2
else
echo "警告:未找到语言文件 $ang_file,使用英文默认值"
echo "Warning: Language file $lang_file not found, using English defaults"
. "$LANG_DIR/en.sh"
fi
}
# 创建语言目录(如果不存在)
mkdir -p "$LANG_DIR"
# 加载语言文件
load_language "$LANGUAGE"
# ========================
# 默认配置
# ========================
DEFAULT_DOCKER_NET="docker-net"
DEFAULT_GATEWAY_IP="172.18.0.1"
DEFAULT_NETWORK_ADDRESS="172.18.0.0/24"
DEFAULT_RESOLV="/etc/resolv.conf"
DEFAULT_CONTAINER_NAME="docker-dns"
DEFAULT_IMAGE_NAME="docker-dns:alpine"
DEFAULT_TZ="Asia/Shanghai"
POSIX_TZ=""
LOG_LEVEL="INFO"
GATEWAY_NAME="gateway"
# ========================
# 容器启动函数
# ========================
start_container() {
name="$1"
echo "$LANG_STARTING_CONTAINER ${1}..."
docker run -d \
-e "TZ=$POSIX_TZ" \
-e "LOG_LEVEL=$LOG_LEVEL" \
-e "GATEWAY_NAME=$GATEWAY_NAME" \
-e "CONTAINER_NAME=$CONTAINER_NAME" \
--network "$DOCKER_NET" \
--name "$name" \
-p 53:53/udp \
--restart unless-stopped \
"$LOCAL_IMAGE_NAME"
}
# ========================
# 获取主机系统时区名称
# ========================
get_system_timezone() {
if command -v timedatectl >/dev/null 2>&1; then
timedatectl show -p Timezone --value
elif [ -f /etc/timezone ]; then
cat /etc/timezone
elif [ -L /etc/localtime ]; then
readlink /etc/localtime | sed 's|/usr/share/zoneinfo/||'
else
echo "$DEFAULT_TZ"
fi
}
# ========================
# 转换为POSIX标准TZ格式
# ========================
to_posix_tz() {
TZ_NAME="$1"
if echo "$TZ_NAME" | grep -Eq '^[Uu][Tt][Cc][+-][0-9]{1,2}(:[0-9]{1,2})?$'; then
# 解析UTC±N或UTC±N:MM格式
SIGN=$(echo "$TZ_NAME" | grep -oE '[+-]' | head -n1)
HOUR=$(echo "$TZ_NAME" | grep -oE '[0-9]{1,2}' | head -n1)
MIN=$(echo "$TZ_NAME" | grep -oE ':[0-9]{1,2}' | cut -c2-)
else
# tzdata名称格式
OFFSET=$(TZ="$TZ_NAME" date +%z)
if [ "$OFFSET" = "+0000" ] && [ "$TZ_NAME" != "UTC" ]; then
echo "$LANG_WARN_UNKNOWN_TZ $TZ_NAME, $LANG_FALLBACK_UTC" >&2
SIGN="+"
HOUR="00"
MIN="00"
else
SIGN=$(echo "$OFFSET" | cut -c1)
HOUR=$(echo "$OFFSET" | cut -c2-3)
MIN=$(echo "$OFFSET" | cut -c4-5)
fi
fi
SIGN=$(echo "$SIGN" | tr '+-' '-+')
[ -z "$SIGN" ] && SIGN="+"
[ -z "$HOUR" ] && HOUR="00"
[ -z "$MIN" ] && MIN="00"
if [ "$HOUR" = "00" ] && [ "$MIN" = "00" ]; then
echo "UTC"
return
fi
echo "UTC$SIGN$HOUR:$MIN"
}
# 提示用户输入并处理默认值
read -p "$LANG_ENTER_DOCKER_NET ($LANG_DEFAULT: $DEFAULT_DOCKER_NET): " DOCKER_NET
DOCKER_NET=${DOCKER_NET:-$DEFAULT_DOCKER_NET}
read -p "$LANG_ENTER_GATEWAY_IP ($LANG_DEFAULT: $DEFAULT_GATEWAY_IP): " GATEWAY_IP
GATEWAY_IP=${GATEWAY_IP:-$DEFAULT_GATEWAY_IP}
read -p "$LANG_ENTER_NETWORK_ADDR ($LANG_DEFAULT: $DEFAULT_NETWORK_ADDRESS): " NETWORK_ADDRESS
NETWORK_ADDRESS=${NETWORK_ADDRESS:-$DEFAULT_NETWORK_ADDRESS}
read -p "$LANG_ENTER_RESOLV_PATH ($LANG_DEFAULT: $DEFAULT_RESOLV): " RESOLV
RESOLV=${RESOLV:-$DEFAULT_RESOLV}
read -p "$LANG_ENTER_CONTAINER_NAME ($LANG_DEFAULT: $DEFAULT_CONTAINER_NAME): " CONTAINER_NAME
CONTAINER_NAME=${CONTAINER_NAME:-$DEFAULT_CONTAINER_NAME}
read -p "$LANG_ENTER_IMAGE_NAME ($LANG_DEFAULT: $DEFAULT_IMAGE_NAME): " IMAGE_NAME
LOCAL_IMAGE_NAME=${LOCAL_IMAGE_NAME:-$DEFAULT_IMAGE_NAME}
DEFAULT_TZ=$(get_system_timezone)
read -p "$LANG_ENTER_TIMEZONE ($LANG_DEFAULT: $DEFAULT_TZ): " TZ
TZ=${TZ:-$DEFAULT_TZ}
POSIX_TZ=$(to_posix_tz "$TZ")
# 显示最终配置
echo "----------------------------------------"
echo "$LANG_CONFIGURED_PARAMS:"
echo "$LANG_DOCKER_NET: $DOCKER_NET"
echo "$LANG_GATEWAY_IP: $GATEWAY_IP"
echo "$LANG_NETWORK_ADDR: $NETWORK_ADDRESS"
echo "$LANG_RESOLV_PATH: $RESOLV"
echo "$LANG_CONTAINER_NAME: $CONTAINER_NAME"
echo "$LANG_IMAGE_NAME: $LOCAL_IMAGE_NAME"
echo "$LANG_STD_TIMEZONE: $TZ"
echo "$LANG_POSIX_TIMEZONE: $POSIX_TZ"
echo "----------------------------------------"
# 确认继续
while true; do
read -p "$LANG_CONFIRM_DEPLOY? (Y/N) " yn
case $yn in
[Yy]* ) break;;
[Nn]* ) exit;;
* ) ;;
esac
done
# ========================
# 检查Docker网络
# ========================
if ! docker network inspect "$DOCKER_NET" >/dev/null 2>&1; then
echo "$LANG_NETWORK_NOT_EXIST $DOCKER_NET, $LANG_CREATING..."
if docker network create "$DOCKER_NET" --subnet="$NETWORK_ADDRESS" --gateway="$GATEWAY_IP"; then
echo "$LANG_NETWORK_CREATED $DOCKER_NET"
else
echo "$LANG_NETWORK_CREATE_FAILED $DOCKER_NET"
exit 1
fi
else
echo "$LANG_NETWORK_EXISTS $DOCKER_NET"
fi
# ========================
# 修改resolv.conf
# 确保第一个DNS是127.0.0.1
# ========================
echo "$LANG_SETTING_DNS 127.0.0.1"
# 如果是符号链接,解析实际文件
TARGET=$(readlink -f "$RESOLV")
[ -z "$TARGET" ] && TARGET="$RESOLV"
first_dns=$(grep '^nameserver' "$TARGET" | head -n1 | awk '{print $2}')
if [ "$first_dns" = "127.0.0.1" ]; then
echo "$LANG_DNS_ALREADY_CONFIGURED"
else
TMPFILE=$(mktemp)
# 获取nameservers列表并排除127.0.0.1
orig_dns=$(grep '^nameserver' "$TARGET" | awk '{print $2}' | grep -v '^127\.0\.0\.1$')
{
echo "nameserver 127.0.0.1"
for dns in $orig_dns; do
echo "nameserver $dns"
done
} > "$TMPFILE"
# 追加非nameserver配置
grep -v '^nameserver' "$TARGET" >> "$TMPFILE"
# 覆盖原始文件
cat "$TMPFILE" > "$TARGET"
rm -f "$TMPFILE"
echo "$LANG_DNS_CONFIG_COMPLETED"
fi
# ========================
# 启动/处理容器
# ========================
if docker ps -a --format '{{.Names}}' | grep -q "^$CONTAINER_NAME$"; then
echo "$LANG_CONTAINER_EXISTS $CONTAINER_NAME, $LANG_SELECT_OPERATION:"
echo "1) $LANG_DELETE_REBUILD"
echo "2) $LANG_USE_NEW_NAME"
echo "3) $LANG_EXIT"
while true; do
read -r -p "$LANG_ENTER_CHOICE [1-3]: " choice
case "$choice" in
1)
echo "$LANG_DELETING_OLD_CONTAINER..."
docker rm -f "$CONTAINER_NAME"
start_container "$CONTAINER_NAME"
break
;;
2)
read -r -p "$LANG_ENTER_NEW_NAME: " newname
if [ -z "$newname" ]; then
echo "$LANG_NAME_CANNOT_BE_EMPTY, $LANG_EXITING"
exit 1
fi
start_container "$newname"
break
;;
3)
echo "$LANG_EXITED"
exit 0
;;
*) ;;
esac
done
else
start_container "$CONTAINER_NAME"
fi
echo "$LANG_CONTAINER_STARTED_SUCCESSFULLY"