DockerProxy_Install.sh 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708
  1. #!/usr/bin/env bash
  2. #===============================================================================
  3. #
  4. # FILE: DockerProxy_Install.sh
  5. #
  6. # USAGE: ./DockerProxy_Install.sh
  7. #
  8. # DESCRIPTION: 自建Docker镜像加速服务,基于官方 registry 一键部署Docker、K8s、Quay、Ghcr镜像加速\管理服务.支持部署到Render.
  9. #
  10. # ORGANIZATION: DingQz dqzboy.com 浅时光博客
  11. #===============================================================================
  12. echo
  13. cat << EOF
  14. ██████╗ ██████╗ ██████╗██╗ ██╗███████╗██████╗ ██████╗ ██████╗ ██████╗ ██╗ ██╗██╗ ██╗
  15. ██╔══██╗██╔═══██╗██╔════╝██║ ██╔╝██╔════╝██╔══██╗ ██╔══██╗██╔══██╗██╔═══██╗╚██╗██╔╝╚██╗ ██╔╝
  16. ██║ ██║██║ ██║██║ █████╔╝ █████╗ ██████╔╝ ██████╔╝██████╔╝██║ ██║ ╚███╔╝ ╚████╔╝
  17. ██║ ██║██║ ██║██║ ██╔═██╗ ██╔══╝ ██╔══██╗ ██╔═══╝ ██╔══██╗██║ ██║ ██╔██╗ ╚██╔╝
  18. ██████╔╝╚██████╔╝╚██████╗██║ ██╗███████╗██║ ██║ ██║ ██║ ██║╚██████╔╝██╔╝ ██╗ ██║
  19. ╚═════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝
  20. 博客: dqzboy.com 浅时光博客
  21. 项目地址: https://github.com/dqzboy/Docker-Proxy
  22. EOF
  23. echo "----------------------------------------------------------------------------------------------------------"
  24. echo -e "\033[32m机场推荐\033[0m(\033[34m按量不限时,解锁ChatGPT\033[0m):\033[34;4mhttps://mojie.mx/#/register?code=CG6h8Irm\033[0m"
  25. echo "----------------------------------------------------------------------------------------------------------"
  26. echo
  27. echo
  28. GREEN="\033[0;32m"
  29. RED="\033[31m"
  30. YELLOW="\033[33m"
  31. RESET="\033[0m"
  32. INFO="[${GREEN}INFO${RESET}]"
  33. ERROR="[${RED}ERROR${RESET}]"
  34. WARN="[${YELLOW}WARN${RESET}]"
  35. function INFO() {
  36. echo -e "${INFO} ${1}"
  37. }
  38. function ERROR() {
  39. echo -e "${ERROR} ${1}"
  40. }
  41. function WARN() {
  42. echo -e "${WARN} ${1}"
  43. }
  44. PROXY_DIR="/data/registry-proxy"
  45. mkdir -p ${PROXY_DIR}
  46. cd "${PROXY_DIR}"
  47. GITRAW="https://raw.githubusercontent.com/dqzboy/Docker-Proxy/main"
  48. IMAGE_NAME="registry"
  49. UI_IMAGE_NAME="dqzboy/docker-registry-ui"
  50. DOCKER_COMPOSE_FILE="docker-compose.yaml"
  51. attempts=0
  52. maxAttempts=3
  53. function CHECK_OS() {
  54. INFO "======================= 检查环境 ======================="
  55. OSVER=$(cat /etc/os-release | grep -o '[0-9]' | head -n 1)
  56. if [ -f /etc/os-release ]; then
  57. . /etc/os-release
  58. else
  59. echo "无法确定发行版"
  60. exit 1
  61. fi
  62. case "$ID" in
  63. "centos")
  64. repo_type="centos"
  65. ;;
  66. "debian")
  67. repo_type="debian"
  68. ;;
  69. "rhel")
  70. repo_type="rhel"
  71. ;;
  72. "ubuntu")
  73. repo_type="ubuntu"
  74. ;;
  75. "opencloudos")
  76. repo_type="centos"
  77. ;;
  78. "rocky")
  79. repo_type="centos"
  80. ;;
  81. *)
  82. WARN "此脚本目前不支持您的系统: $ID"
  83. exit 1
  84. ;;
  85. esac
  86. INFO "System release:: $NAME"
  87. INFO "System version: $VERSION"
  88. INFO "System ID: $ID"
  89. INFO "System ID Like: $ID_LIKE"
  90. }
  91. function CHECK_PACKAGE_MANAGER() {
  92. if command -v dnf &> /dev/null; then
  93. package_manager="dnf"
  94. elif command -v yum &> /dev/null; then
  95. package_manager="yum"
  96. elif command -v apt-get &> /dev/null; then
  97. package_manager="apt-get"
  98. elif command -v apt &> /dev/null; then
  99. package_manager="apt"
  100. else
  101. ERROR "不受支持的软件包管理器."
  102. exit 1
  103. fi
  104. }
  105. function CHECK_PKG_MANAGER() {
  106. if command -v rpm &> /dev/null; then
  107. pkg_manager="rpm"
  108. elif command -v dpkg &> /dev/null; then
  109. pkg_manager="dpkg"
  110. elif command -v apt &> /dev/null; then
  111. pkg_manager="apt"
  112. else
  113. ERROR "无法确定包管理系统."
  114. exit 1
  115. fi
  116. }
  117. function CHECKMEM() {
  118. memory_usage=$(free | awk '/^Mem:/ {printf "%.2f", $3/$2 * 100}')
  119. memory_usage=${memory_usage%.*}
  120. if [[ $memory_usage -gt 90 ]]; then
  121. read -e -p "$(WARN '内存占用率高于 70%($memory_usage%). 是否继续安装?: ')" continu
  122. if [ "$continu" == "n" ] || [ "$continu" == "N" ]; then
  123. exit 1
  124. fi
  125. else
  126. INFO "内存资源充足。请继续.($memory_usage%)"
  127. fi
  128. }
  129. function CHECKFIRE() {
  130. systemctl stop firewalld &> /dev/null
  131. systemctl disable firewalld &> /dev/null
  132. systemctl stop iptables &> /dev/null
  133. systemctl disable iptables &> /dev/null
  134. ufw disable &> /dev/null
  135. INFO "防火墙已被禁用."
  136. if [[ "$repo_type" == "centos" || "$repo_type" == "rhel" ]]; then
  137. if sestatus | grep "SELinux status" | grep -q "enabled"; then
  138. WARN "SELinux 已启用。禁用 SELinux..."
  139. setenforce 0
  140. sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
  141. INFO "SELinux 已被禁用."
  142. else
  143. INFO "SELinux 已被禁用."
  144. fi
  145. fi
  146. }
  147. function CHECKBBR() {
  148. kernel_version=$(uname -r | awk -F "-" '{print $1}')
  149. read -e -p "$(WARN '是否开启BBR,优化网络带宽提高网络性能? [y/n]: ')" choice_bbr
  150. case $choice_bbr in
  151. y | Y)
  152. version_compare=$(echo "${kernel_version} 4.9" | awk '{if ($1 >= $2) print "yes"; else print "no"}')
  153. if [ "$version_compare" != "yes" ]; then
  154. WARN "你的内核版本小于4.9,无法启动BBR,需要你手动升级内核"
  155. exit 0
  156. fi
  157. sysctl net.ipv4.tcp_available_congestion_control | grep -q "bbr"
  158. if [ $? -eq 0 ]; then
  159. INFO "你的服务器已经启动BBR"
  160. else
  161. INFO "开启BBR中..."
  162. modprobe tcp_bbr
  163. if [ $? -eq 0 ]; then
  164. INFO "BBR模块添加成功."
  165. else
  166. ERROR "BBR模块添加失败,请执行 sysctl -p 检查."
  167. exit 1
  168. fi
  169. if [ ! -d /etc/modules-load.d/ ]; then
  170. mkdir -p /etc/modules-load.d/
  171. fi
  172. if [ ! -f /etc/modules-load.d/tcp_bbr.conf ]; then
  173. touch /etc/modules-load.d/tcp_bbr.conf
  174. fi
  175. if ! grep -q "tcp_bbr" /etc/modules-load.d/tcp_bbr.conf ; then
  176. echo 'tcp_bbr' >> /etc/modules-load.d/tcp_bbr.conf
  177. fi
  178. for setting in "net.core.default_qdisc=fq" "net.ipv4.tcp_congestion_control=bbr"; do
  179. if ! grep -q "$setting" /etc/sysctl.conf; then
  180. echo "$setting" >> /etc/sysctl.conf
  181. fi
  182. done
  183. sysctl -p &> /dev/null
  184. if [ $? -ne 0 ]; then
  185. ERROR "应用sysctl设置过程中发生了一个错误,请执行 sysctl -p 检查."
  186. exit 2
  187. fi
  188. lsmod | grep tcp_bbr
  189. if [ $? -eq 0 ]; then
  190. INFO "BBR已经成功开启。"
  191. else
  192. ERROR "BBR开启失败,请执行 sysctl -p 检查."
  193. exit 3
  194. fi
  195. WARN "如果BBR开启后未生效,请执行 reboot 重启服务器使其BBR模块生效"
  196. fi
  197. ;;
  198. n | N)
  199. INFO "不开启BBR"
  200. ;;
  201. *)
  202. ERROR "输入错误!请输入 y 或 n"
  203. ;;
  204. esac
  205. }
  206. function INSTALL_PACKAGE(){
  207. INFO "======================= 安装依赖 ======================="
  208. INFO "检查依赖安装情况,请稍等 ..."
  209. TIMEOUT=300
  210. PACKAGES_APT=(
  211. lsof jq wget apache2-utils tar
  212. )
  213. PACKAGES_YUM=(
  214. epel-release lsof jq wget yum-utils httpd-tools tar
  215. )
  216. if [ "$package_manager" = "dnf" ] || [ "$package_manager" = "yum" ]; then
  217. for package in "${PACKAGES_YUM[@]}"; do
  218. if $pkg_manager -q "$package" &>/dev/null; then
  219. INFO "已经安装 $package ..."
  220. else
  221. INFO "正在安装 $package ..."
  222. start_time=$(date +%s)
  223. $package_manager -y install "$package" --skip-broken > /dev/null 2>&1 &
  224. install_pid=$!
  225. while [[ $(($(date +%s) - $start_time)) -lt $TIMEOUT ]] && kill -0 $install_pid &>/dev/null; do
  226. sleep 1
  227. done
  228. if kill -0 $install_pid &>/dev/null; then
  229. WARN "$package 的安装时间超过 $TIMEOUT 秒。是否继续? (y/n)"
  230. read -r continue_install
  231. if [ "$continue_install" != "y" ]; then
  232. ERROR "$package 的安装超时。退出脚本。"
  233. exit 1
  234. else
  235. continue
  236. fi
  237. fi
  238. wait $install_pid
  239. if [ $? -ne 0 ]; then
  240. ERROR "$package 安装失败。请检查系统安装源,然后再次运行此脚本!请尝试手动执行安装:$package_manager -y install $package"
  241. exit 1
  242. fi
  243. fi
  244. done
  245. elif [ "$package_manager" = "apt-get" ] || [ "$package_manager" = "apt" ];then
  246. dpkg --configure -a &>/dev/null
  247. $package_manager update &>/dev/null
  248. for package in "${PACKAGES_APT[@]}"; do
  249. if $pkg_manager -s "$package" &>/dev/null; then
  250. INFO "已经安装 $package ..."
  251. else
  252. INFO "正在安装 $package ..."
  253. $package_manager install -y $package > /dev/null 2>&1
  254. if [ $? -ne 0 ]; then
  255. ERROR "安装 $package 失败,请检查系统安装源之后再次运行此脚本!请尝试手动执行安装:$package_manager -y install $package"
  256. exit 1
  257. fi
  258. fi
  259. done
  260. else
  261. WARN "无法确定包管理系统."
  262. exit 1
  263. fi
  264. }
  265. function INSTALL_CADDY() {
  266. INFO "====================== 安装Caddy ======================"
  267. start_caddy() {
  268. systemctl enable caddy.service &>/dev/null
  269. systemctl restart caddy.service
  270. status=$(systemctl is-active caddy)
  271. if [ "$status" = "active" ]; then
  272. INFO "Caddy 服务运行正常,请继续..."
  273. else
  274. ERROR "Caddy 服务未运行,会导致服务无法正常安装运行,请检查后再次执行脚本!"
  275. ERROR "-----------服务启动失败,请查看错误日志 ↓↓↓-----------"
  276. journalctl -u caddy.service --no-pager
  277. ERROR "-----------服务启动失败,请查看错误日志 ↑↑↑-----------"
  278. exit 1
  279. fi
  280. }
  281. check_caddy() {
  282. if pgrep "caddy" > /dev/null; then
  283. INFO "Caddy 已在运行."
  284. else
  285. WARN "Caddy 未运行。尝试启动 Caddy..."
  286. start_attempts=3
  287. for ((i=1; i<=$start_attempts; i++)); do
  288. start_caddy
  289. if pgrep "caddy" > /dev/null; then
  290. INFO "Caddy 已成功启动."
  291. break
  292. else
  293. if [ $i -eq $start_attempts ]; then
  294. ERROR "Caddy 在尝试 $start_attempts 后无法启动。请检查配置"
  295. exit 1
  296. else
  297. WARN "在 $i 时间内启动 Caddy 失败。重试..."
  298. fi
  299. fi
  300. done
  301. fi
  302. }
  303. if [ "$package_manager" = "dnf" ]; then
  304. if which caddy &>/dev/null; then
  305. INFO "Caddy 已经安装."
  306. else
  307. INFO "正在安装Caddy程序,请稍候..."
  308. $package_manager -y install 'dnf-command(copr)' &>/dev/null
  309. $package_manager -y copr enable @caddy/caddy &>/dev/null
  310. while [ $attempts -lt $maxAttempts ]; do
  311. $package_manager -y install caddy &>/dev/null
  312. if [ $? -ne 0 ]; then
  313. ((attempts++))
  314. WARN "正在尝试安装Caddy >>> (Attempt: $attempts)"
  315. if [ $attempts -eq $maxAttempts ]; then
  316. ERROR "Caddy installation failed. Please try installing manually."
  317. echo "命令: $package_manager -y install 'dnf-command(copr)' && $package_manager -y copr enable @caddy/caddy && $package_manager -y install caddy"
  318. exit 1
  319. fi
  320. else
  321. INFO "已安装 Caddy."
  322. break
  323. fi
  324. done
  325. fi
  326. check_caddy
  327. elif [ "$package_manager" = "yum" ]; then
  328. if which caddy &>/dev/null; then
  329. INFO "Caddy 已经安装."
  330. else
  331. INFO "正在安装Caddy程序,请稍候..."
  332. $package_manager -y install yum-plugin-copr &>/dev/null
  333. $package_manager -y copr enable @caddy/caddy &>/dev/null
  334. while [ $attempts -lt $maxAttempts ]; do
  335. $package_manager -y install caddy &>/dev/null
  336. if [ $? -ne 0 ]; then
  337. ((attempts++))
  338. WARN "正在尝试安装Caddy >>> (Attempt: $attempts)"
  339. if [ $attempts -eq $maxAttempts ]; then
  340. ERROR "Caddy installation failed. Please try installing manually."
  341. echo "命令: $package_manager -y install 'dnf-command(copr)' && $package_manager -y copr enable @caddy/caddy && $package_manager -y install caddy"
  342. exit 1
  343. fi
  344. else
  345. INFO "已安装 Caddy."
  346. break
  347. fi
  348. done
  349. fi
  350. check_caddy
  351. elif [ "$package_manager" = "apt" ] || [ "$package_manager" = "apt-get" ];then
  352. dpkg --configure -a &>/dev/null
  353. $package_manager update &>/dev/null
  354. if $pkg_manager -s "caddy" &>/dev/null; then
  355. INFO "Caddy 已安装,跳过..."
  356. else
  357. INFO "安装 Caddy 请稍等 ..."
  358. $package_manager install -y debian-keyring debian-archive-keyring apt-transport-https &>/dev/null
  359. curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg &>/dev/null
  360. curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list &>/dev/null
  361. $package_manager update &>/dev/null
  362. $package_manager install -y caddy &>/dev/null
  363. if [ $? -ne 0 ]; then
  364. ERROR "安装 Caddy 失败,请检查系统安装源之后再次运行此脚本!请尝试手动执行安装:$package_manager -y install caddy"
  365. exit 1
  366. fi
  367. fi
  368. check_caddy
  369. else
  370. WARN "无法确定包管理系统."
  371. exit 1
  372. fi
  373. INFO "====================== 配置Caddy ======================"
  374. while true; do
  375. INFO ">>> 域名解析主机记录(即域名前缀):ui、hub、gcr、ghcr、k8sgcr、k8s、quay、mcr、elastic <<<"
  376. WARN ">>> 只需选择你部署的服务进行解析即可,无需将上面提示中所有的主机记录进行解析 <<<"
  377. read -e -p "$(WARN '是否配置Caddy,实现自动HTTPS? 执行前需提前在DNS服务商选择部署的服务进行解析主机记录[y/n]: ')" caddy_conf
  378. case "$caddy_conf" in
  379. y|Y )
  380. read -e -p "$(INFO '请输入你的域名[例: baidu.com],不可为空: ')" caddy_domain
  381. read -e -p "$(INFO '请输入要配置的主机记录,用逗号分隔[例: hub,mcr]: ')" selected_records
  382. IFS=',' read -r -a records_array <<< "$selected_records"
  383. declare -A record_templates
  384. record_templates[ui]="ui.$caddy_domain {
  385. reverse_proxy localhost:50000 {
  386. header_up Host {host}
  387. header_up Origin {scheme}://{host}
  388. header_up X-Forwarded-For {remote_addr}
  389. header_up X-Forwarded-Proto {scheme}
  390. header_up X-Forwarded-Ssl on
  391. header_up X-Forwarded-Port {server_port}
  392. header_up X-Forwarded-Host {host}
  393. }
  394. }"
  395. record_templates[hub]="hub.$caddy_domain {
  396. reverse_proxy localhost:51000 {
  397. header_up Host {host}
  398. header_up X-Real-IP {remote_addr}
  399. header_up X-Forwarded-For {remote_addr}
  400. header_up X-Nginx-Proxy true
  401. }
  402. }"
  403. record_templates[ghcr]="ghcr.$caddy_domain {
  404. reverse_proxy localhost:52000 {
  405. header_up Host {host}
  406. header_up X-Real-IP {remote_addr}
  407. header_up X-Forwarded-For {remote_addr}
  408. header_up X-Nginx-Proxy true
  409. }
  410. }"
  411. record_templates[gcr]="gcr.$caddy_domain {
  412. reverse_proxy localhost:53000 {
  413. header_up Host {host}
  414. header_up X-Real-IP {remote_addr}
  415. header_up X-Forwarded-For {remote_addr}
  416. header_up X-Nginx-Proxy true
  417. }
  418. }"
  419. record_templates[k8sgcr]="k8sgcr.$caddy_domain {
  420. reverse_proxy localhost:54000 {
  421. header_up Host {host}
  422. header_up X-Real-IP {remote_addr}
  423. header_up X-Forwarded-For {remote_addr}
  424. header_up X-Nginx-Proxy true
  425. }
  426. }"
  427. record_templates[k8s]="k8s.$caddy_domain {
  428. reverse_proxy localhost:55000 {
  429. header_up Host {host}
  430. header_up X-Real-IP {remote_addr}
  431. header_up X-Forwarded-For {remote_addr}
  432. header_up X-Nginx-Proxy true
  433. }
  434. }"
  435. record_templates[quay]="quay.$caddy_domain {
  436. reverse_proxy localhost:56000 {
  437. header_up Host {host}
  438. header_up X-Real-IP {remote_addr}
  439. header_up X-Forwarded-For {remote_addr}
  440. header_up X-Nginx-Proxy true
  441. }
  442. }"
  443. record_templates[mcr]="mcr.$caddy_domain {
  444. reverse_proxy localhost:57000 {
  445. header_up Host {host}
  446. header_up X-Real-IP {remote_addr}
  447. header_up X-Forwarded-For {remote_addr}
  448. header_up X-Nginx-Proxy true
  449. }
  450. }"
  451. record_templates[elastic]="elastic.$caddy_domain {
  452. reverse_proxy localhost:58000 {
  453. header_up Host {host}
  454. header_up X-Real-IP {remote_addr}
  455. header_up X-Forwarded-For {remote_addr}
  456. header_up X-Nginx-Proxy true
  457. }
  458. }"
  459. > /etc/caddy/Caddyfile
  460. for record in "${records_array[@]}"; do
  461. if [[ -n "${record_templates[$record]}" ]]; then
  462. echo "${record_templates[$record]}" >> /etc/caddy/Caddyfile
  463. fi
  464. done
  465. start_attempts=3
  466. for ((i=1; i<=$start_attempts; i++)); do
  467. start_caddy
  468. if pgrep "caddy" > /dev/null; then
  469. INFO "重新载入配置成功. Caddy服务启动完成"
  470. break
  471. else
  472. if [ $i -eq $start_attempts ]; then
  473. ERROR "Caddy 在尝试 $start_attempts 后无法启动。请检查配置"
  474. exit 1
  475. else
  476. WARN "第 $i 次启动 Caddy 失败。重试..."
  477. fi
  478. fi
  479. done
  480. break;;
  481. n|N )
  482. WARN "退出配置 Caddy 操作。"
  483. break;;
  484. * )
  485. INFO "请输入 'y' 表示是,或者 'n' 表示否。";;
  486. esac
  487. done
  488. }
  489. function INSTALL_NGINX() {
  490. INFO "====================== 安装Nginx ======================"
  491. start_nginx() {
  492. systemctl enable nginx &>/dev/null
  493. systemctl restart nginx
  494. status=$(systemctl is-active nginx)
  495. if [ "$status" = "active" ]; then
  496. INFO "Nginx 服务运行正常,请继续..."
  497. else
  498. ERROR "Nginx 服务未运行,会导致服务无法正常安装运行,请检查后再次执行脚本!"
  499. ERROR "-----------服务启动失败,请查看错误日志 ↓↓↓-----------"
  500. journalctl -u nginx.service --no-pager
  501. ERROR "-----------服务启动失败,请查看错误日志 ↑↑↑-----------"
  502. exit 1
  503. fi
  504. }
  505. check_nginx() {
  506. if pgrep "nginx" > /dev/null; then
  507. INFO "Nginx 已在运行."
  508. else
  509. WARN "Nginx 未运行。尝试启动 Nginx..."
  510. start_attempts=3
  511. for ((i=1; i<=$start_attempts; i++)); do
  512. start_nginx
  513. if pgrep "nginx" > /dev/null; then
  514. INFO "Nginx 已成功启动."
  515. break
  516. else
  517. if [ $i -eq $start_attempts ]; then
  518. ERROR "Nginx 在尝试 $start_attempts 次后无法启动。请检查配置"
  519. exit 1
  520. else
  521. WARN "第 $i 次启动 Nginx 失败。重试..."
  522. fi
  523. fi
  524. done
  525. fi
  526. }
  527. if [ "$package_manager" = "dnf" ] || [ "$package_manager" = "yum" ]; then
  528. if which nginx &>/dev/null; then
  529. INFO "Nginx 已经安装."
  530. else
  531. INFO "正在安装Nginx程序,请稍候..."
  532. NGINX="nginx-1.24.0-1.el${OSVER}.ngx.x86_64.rpm"
  533. rm -f ${NGINX}
  534. wget http://nginx.org/packages/centos/${OSVER}/x86_64/RPMS/${NGINX} &>/dev/null
  535. while [ $attempts -lt $maxAttempts ]; do
  536. $package_manager -y install ${NGINX} &>/dev/null
  537. if [ $? -ne 0 ]; then
  538. ((attempts++))
  539. WARN "正在尝试安装Nginx >>> (Attempt: $attempts)"
  540. if [ $attempts -eq $maxAttempts ]; then
  541. ERROR "Nginx installation failed. Please try installing manually."
  542. rm -f ${NGINX}
  543. echo "命令: wget http://nginx.org/packages/centos/${OSVER}/x86_64/RPMS/${NGINX} && $package_manager -y install ${NGINX}"
  544. exit 1
  545. fi
  546. else
  547. INFO "已安装 Nginx."
  548. rm -f ${NGINX}
  549. break
  550. fi
  551. done
  552. fi
  553. check_nginx
  554. elif [ "$package_manager" = "apt-get" ] || [ "$package_manager" = "apt" ];then
  555. dpkg --configure -a &>/dev/null
  556. $package_manager update &>/dev/null
  557. if $pkg_manager -s "nginx" &>/dev/null; then
  558. INFO "nginx 已安装,跳过..."
  559. else
  560. INFO "安装 nginx 请稍等 ..."
  561. $package_manager install -y nginx > /dev/null 2>&1
  562. if [ $? -ne 0 ]; then
  563. ERROR "安装 nginx 失败,请检查系统安装源之后再次运行此脚本!请尝试手动执行安装:$package_manager -y install nginx"
  564. exit 1
  565. fi
  566. fi
  567. check_nginx
  568. else
  569. WARN "无法确定包管理系统."
  570. exit 1
  571. fi
  572. INFO "====================== 配置Nginx ======================"
  573. while true; do
  574. WARN "自行安装的 Nginx 请勿执行此操作,以防覆盖原有配置"
  575. INFO ">>> 域名解析主机记录(即域名前缀):ui、hub、gcr、ghcr、k8sgcr、k8s、quay、mcr、elastic <<<"
  576. WARN ">>> 只需选择你部署的服务进行解析即可,无需将上面提示中所有的主机记录进行解析 <<<"
  577. read -e -p "$(WARN '是否配置 Nginx ?配置完成后需在DNS服务商对部署的服务进行解析主机记录[y/n]: ')" nginx_conf
  578. case "$nginx_conf" in
  579. y|Y )
  580. read -e -p "$(INFO '请输入你的域名[例: baidu.com],不可为空: ')" nginx_domain
  581. read -e -p "$(INFO '请输入要配置的主机记录,用逗号分隔[例: hub,mcr]: ')" selected_records
  582. IFS=',' read -r -a records_array <<< "$selected_records"
  583. declare -A record_templates
  584. record_templates[ui]="server {
  585. listen 80;
  586. #listen 443 ssl;
  587. server_name ui.$nginx_domain;
  588. #ssl_certificate /path/to/your_domain_name.crt;
  589. #ssl_certificate_key /path/to/your_domain_name.key;
  590. #ssl_session_timeout 1d;
  591. #ssl_session_cache shared:SSL:50m;
  592. #ssl_session_tickets off;
  593. #ssl_protocols TLSv1.2 TLSv1.3;
  594. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  595. #ssl_prefer_server_ciphers on;
  596. #ssl_buffer_size 8k;
  597. proxy_connect_timeout 600;
  598. proxy_send_timeout 600;
  599. proxy_read_timeout 600;
  600. send_timeout 600;
  601. location / {
  602. proxy_pass http://localhost:50000;
  603. proxy_set_header Host \$host;
  604. proxy_set_header Origin \$scheme://\$host;
  605. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  606. proxy_set_header X-Forwarded-Proto \$scheme;
  607. proxy_set_header X-Forwarded-Ssl on;
  608. proxy_set_header X-Forwarded-Port \$server_port;
  609. proxy_set_header X-Forwarded-Host \$host;
  610. }
  611. }"
  612. record_templates[hub]="server {
  613. listen 80;
  614. #listen 443 ssl;
  615. server_name hub.$nginx_domain;
  616. #ssl_certificate /path/to/your_domain_name.crt;
  617. #ssl_certificate_key /path/to/your_domain_name.key;
  618. #ssl_session_timeout 1d;
  619. #ssl_session_cache shared:SSL:50m;
  620. #ssl_session_tickets off;
  621. #ssl_protocols TLSv1.2 TLSv1.3;
  622. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  623. #ssl_prefer_server_ciphers on;
  624. #ssl_buffer_size 8k;
  625. proxy_connect_timeout 600;
  626. proxy_send_timeout 600;
  627. proxy_read_timeout 600;
  628. send_timeout 600;
  629. location / {
  630. proxy_pass http://localhost:51000;
  631. proxy_set_header Host \$host;
  632. proxy_set_header X-Real-IP \$remote_addr;
  633. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  634. proxy_set_header X-Nginx-Proxy true;
  635. proxy_buffering off;
  636. proxy_redirect off;
  637. }
  638. }"
  639. record_templates[ghcr]="server {
  640. listen 80;
  641. #listen 443 ssl;
  642. server_name ghcr.$nginx_domain;
  643. #ssl_certificate /path/to/your_domain_name.crt;
  644. #ssl_certificate_key /path/to/your_domain_name.key;
  645. #ssl_session_timeout 1d;
  646. #ssl_session_cache shared:SSL:50m;
  647. #ssl_session_tickets off;
  648. #ssl_protocols TLSv1.2 TLSv1.3;
  649. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  650. #ssl_prefer_server_ciphers on;
  651. #ssl_buffer_size 8k;
  652. proxy_connect_timeout 600;
  653. proxy_send_timeout 600;
  654. proxy_read_timeout 600;
  655. send_timeout 600;
  656. location / {
  657. proxy_pass http://localhost:52000;
  658. proxy_set_header Host \$host;
  659. proxy_set_header X-Real-IP \$remote_addr;
  660. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  661. proxy_set_header X-Nginx-Proxy true;
  662. proxy_buffering off;
  663. proxy_redirect off;
  664. }
  665. }"
  666. record_templates[gcr]="server {
  667. listen 80;
  668. #listen 443 ssl;
  669. server_name gcr.$nginx_domain;
  670. #ssl_certificate /path/to/your_domain_name.crt;
  671. #ssl_certificate_key /path/to/your_domain_name.key;
  672. #ssl_session_timeout 1d;
  673. #ssl_session_cache shared:SSL:50m;
  674. #ssl_session_tickets off;
  675. #ssl_protocols TLSv1.2 TLSv1.3;
  676. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  677. #ssl_prefer_server_ciphers on;
  678. #ssl_buffer_size 8k;
  679. proxy_connect_timeout 600;
  680. proxy_send_timeout 600;
  681. proxy_read_timeout 600;
  682. send_timeout 600;
  683. location / {
  684. proxy_pass http://localhost:53000;
  685. proxy_set_header Host \$host;
  686. proxy_set_header X-Real-IP \$remote_addr;
  687. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  688. proxy_set_header X-Nginx-Proxy true;
  689. proxy_buffering off;
  690. proxy_redirect off;
  691. }
  692. }"
  693. record_templates[k8sgcr]="server {
  694. listen 80;
  695. #listen 443 ssl;
  696. server_name k8sgcr.$nginx_domain;
  697. #ssl_certificate /path/to/your_domain_name.crt;
  698. #ssl_certificate_key /path/to/your_domain_name.key;
  699. #ssl_session_timeout 1d;
  700. #ssl_session_cache shared:SSL:50m;
  701. #ssl_session_tickets off;
  702. #ssl_protocols TLSv1.2 TLSv1.3;
  703. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  704. #ssl_prefer_server_ciphers on;
  705. #ssl_buffer_size 8k;
  706. proxy_connect_timeout 600;
  707. proxy_send_timeout 600;
  708. proxy_read_timeout 600;
  709. send_timeout 600;
  710. location / {
  711. proxy_pass http://localhost:54000;
  712. proxy_set_header Host \$host;
  713. proxy_set_header X-Real-IP \$remote_addr;
  714. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  715. proxy_set_header X-Nginx-Proxy true;
  716. proxy_buffering off;
  717. proxy_redirect off;
  718. }
  719. }"
  720. record_templates[k8s]="server {
  721. listen 80;
  722. #listen 443 ssl;
  723. server_name k8s.$nginx_domain;
  724. #ssl_certificate /path/to/your_domain_name.crt;
  725. #ssl_certificate_key /path/to/your_domain_name.key;
  726. #ssl_session_timeout 1d;
  727. #ssl_session_cache shared:SSL:50m;
  728. #ssl_session_tickets off;
  729. #ssl_protocols TLSv1.2 TLSv1.3;
  730. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  731. #ssl_prefer_server_ciphers on;
  732. #ssl_buffer_size 8k;
  733. proxy_connect_timeout 600;
  734. proxy_send_timeout 600;
  735. proxy_read_timeout 600;
  736. send_timeout 600;
  737. location / {
  738. proxy_pass http://localhost:55000;
  739. proxy_set_header Host \$host;
  740. proxy_set_header X-Real-IP \$remote_addr;
  741. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  742. proxy_set_header X-Nginx-Proxy true;
  743. proxy_buffering off;
  744. proxy_redirect off;
  745. }
  746. }"
  747. record_templates[quay]="server {
  748. listen 80;
  749. #listen 443 ssl;
  750. server_name quay.$nginx_domain;
  751. #ssl_certificate /path/to/your_domain_name.crt;
  752. #ssl_certificate_key /path/to/your_domain_name.key;
  753. #ssl_session_timeout 1d;
  754. #ssl_session_cache shared:SSL:50m;
  755. #ssl_session_tickets off;
  756. #ssl_protocols TLSv1.2 TLSv1.3;
  757. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  758. #ssl_prefer_server_ciphers on;
  759. #ssl_buffer_size 8k;
  760. proxy_connect_timeout 600;
  761. proxy_send_timeout 600;
  762. proxy_read_timeout 600;
  763. send_timeout 600;
  764. location / {
  765. proxy_pass http://localhost:56000;
  766. proxy_set_header Host \$host;
  767. proxy_set_header X-Real-IP \$remote_addr;
  768. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  769. proxy_set_header X-Nginx-Proxy true;
  770. proxy_buffering off;
  771. proxy_redirect off;
  772. }
  773. }"
  774. record_templates[mcr]="server {
  775. listen 80;
  776. #listen 443 ssl;
  777. server_name mcr.$nginx_domain;
  778. #ssl_certificate /path/to/your_domain_name.crt;
  779. #ssl_certificate_key /path/to/your_domain_name.key;
  780. #ssl_session_timeout 1d;
  781. #ssl_session_cache shared:SSL:50m;
  782. #ssl_session_tickets off;
  783. #ssl_protocols TLSv1.2 TLSv1.3;
  784. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  785. #ssl_prefer_server_ciphers on;
  786. #ssl_buffer_size 8k;
  787. proxy_connect_timeout 600;
  788. proxy_send_timeout 600;
  789. proxy_read_timeout 600;
  790. send_timeout 600;
  791. location / {
  792. proxy_pass http://localhost:57000;
  793. proxy_set_header Host \$host;
  794. proxy_set_header X-Real-IP \$remote_addr;
  795. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  796. proxy_set_header X-Nginx-Proxy true;
  797. proxy_buffering off;
  798. proxy_redirect off;
  799. }
  800. }"
  801. record_templates[elastic]="server {
  802. listen 80;
  803. #listen 443 ssl;
  804. server_name elastic.$nginx_domain;
  805. #ssl_certificate /path/to/your_domain_name.crt;
  806. #ssl_certificate_key /path/to/your_domain_name.key;
  807. #ssl_session_timeout 1d;
  808. #ssl_session_cache shared:SSL:50m;
  809. #ssl_session_tickets off;
  810. #ssl_protocols TLSv1.2 TLSv1.3;
  811. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  812. #ssl_prefer_server_ciphers on;
  813. #ssl_buffer_size 8k;
  814. proxy_connect_timeout 600;
  815. proxy_send_timeout 600;
  816. proxy_read_timeout 600;
  817. send_timeout 600;
  818. location / {
  819. proxy_pass http://localhost:58000;
  820. proxy_set_header Host \$host;
  821. proxy_set_header X-Real-IP \$remote_addr;
  822. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  823. proxy_set_header X-Nginx-Proxy true;
  824. proxy_buffering off;
  825. proxy_redirect off;
  826. }
  827. }"
  828. > /etc/nginx/conf.d/docker-proxy.conf
  829. for record in "${records_array[@]}"; do
  830. if [[ -n "${record_templates[$record]}" ]]; then
  831. echo "${record_templates[$record]}" >> /etc/nginx/conf.d/docker-proxy.conf
  832. fi
  833. done
  834. start_attempts=3
  835. for ((i=1; i<=$start_attempts; i++)); do
  836. start_nginx
  837. if pgrep "nginx" > /dev/null; then
  838. INFO "重新载入配置成功. Nginx服务启动完成"
  839. break
  840. else
  841. if [ $i -eq $start_attempts ]; then
  842. ERROR "Nginx 在尝试 $start_attempts 后无法启动。请检查配置"
  843. exit 1
  844. else
  845. WARN "第 $i 次启动 Nginx 失败。重试..."
  846. fi
  847. fi
  848. done
  849. break;;
  850. n|N )
  851. WARN "退出配置 Nginx 操作。"
  852. break;;
  853. * )
  854. INFO "请输入 'y' 表示是,或者 'n' 表示否。";;
  855. esac
  856. done
  857. }
  858. function CHECK_DOCKER() {
  859. status=$(systemctl is-active docker)
  860. if [ "$status" = "active" ]; then
  861. INFO "Docker 服务运行正常,请继续..."
  862. else
  863. ERROR "Docker 服务未运行,会导致服务无法正常安装运行,请检查后再次执行脚本!"
  864. ERROR "-----------服务启动失败,请查看错误日志 ↓↓↓-----------"
  865. journalctl -u docker.service --no-pager
  866. ERROR "-----------服务启动失败,请查看错误日志 ↑↑↑-----------"
  867. exit 1
  868. fi
  869. }
  870. function INSTALL_DOCKER() {
  871. repo_file="docker-ce.repo"
  872. url="https://download.docker.com/linux/$repo_type"
  873. MAX_ATTEMPTS=3
  874. attempt=0
  875. success=false
  876. if [ "$repo_type" = "centos" ] || [ "$repo_type" = "rhel" ]; then
  877. if ! command -v docker &> /dev/null;then
  878. while [[ $attempt -lt $MAX_ATTEMPTS ]]; do
  879. attempt=$((attempt + 1))
  880. WARN "Docker 未安装,正在进行安装..."
  881. yum-config-manager --add-repo $url/$repo_file &>/dev/null
  882. $package_manager -y install docker-ce &>/dev/null
  883. if [ $? -eq 0 ]; then
  884. success=true
  885. break
  886. fi
  887. ERROR "Docker 安装失败,正在尝试重新下载 (尝试次数: $attempt)"
  888. done
  889. if $success; then
  890. INFO "Docker 安装成功,版本为:$(docker --version)"
  891. systemctl restart docker &>/dev/null
  892. CHECK_DOCKER
  893. systemctl enable docker &>/dev/null
  894. else
  895. ERROR "Docker 安装失败,请尝试手动安装"
  896. exit 1
  897. fi
  898. else
  899. INFO "Docker 已安装,安装版本为:$(docker --version)"
  900. systemctl restart docker | grep -E "ERROR|ELIFECYCLE|WARN"
  901. fi
  902. elif [ "$repo_type" == "ubuntu" ]; then
  903. if ! command -v docker &> /dev/null;then
  904. while [[ $attempt -lt $MAX_ATTEMPTS ]]; do
  905. attempt=$((attempt + 1))
  906. WARN "Docker 未安装,正在进行安装..."
  907. curl -fsSL $url/gpg | sudo apt-key add - &>/dev/null
  908. add-apt-repository "deb [arch=amd64] $url $(lsb_release -cs) stable" <<< $'\n' &>/dev/null
  909. $package_manager -y install docker-ce docker-ce-cli containerd.io &>/dev/null
  910. if [ $? -eq 0 ]; then
  911. success=true
  912. break
  913. fi
  914. ERROR "Docker 安装失败,正在尝试重新下载 (尝试次数: $attempt)"
  915. done
  916. if $success; then
  917. INFO "Docker 安装成功,版本为:$(docker --version)"
  918. systemctl restart docker &>/dev/null
  919. CHECK_DOCKER
  920. systemctl enable docker &>/dev/null
  921. else
  922. ERROR "Docker 安装失败,请尝试手动安装"
  923. exit 1
  924. fi
  925. else
  926. INFO "Docker 已安装,安装版本为:$(docker --version)"
  927. systemctl restart docker | grep -E "ERROR|ELIFECYCLE|WARN"
  928. fi
  929. elif [ "$repo_type" == "debian" ]; then
  930. if ! command -v docker &> /dev/null;then
  931. while [[ $attempt -lt $MAX_ATTEMPTS ]]; do
  932. attempt=$((attempt + 1))
  933. WARN "Docker 未安装,正在进行安装..."
  934. curl -fsSL $url/gpg | sudo apt-key add - &>/dev/null
  935. add-apt-repository "deb [arch=amd64] $url $(lsb_release -cs) stable" <<< $'\n' &>/dev/null
  936. $package_manager -y install docker-ce docker-ce-cli containerd.io &>/dev/null
  937. if [ $? -eq 0 ]; then
  938. success=true
  939. break
  940. fi
  941. ERROR "Docker 安装失败,正在尝试重新下载 (尝试次数: $attempt)"
  942. done
  943. if $success; then
  944. INFO "Docker 安装成功,版本为:$(docker --version)"
  945. systemctl restart docker &>/dev/null
  946. CHECK_DOCKER
  947. systemctl enable docker &>/dev/null
  948. else
  949. ERROR "Docker 安装失败,请尝试手动安装"
  950. exit 1
  951. fi
  952. else
  953. INFO "Docker 已安装,安装版本为:$(docker --version)"
  954. systemctl restart docker &>/dev/null
  955. CHECK_DOCKER
  956. fi
  957. else
  958. ERROR "不支持的操作系统."
  959. exit 1
  960. fi
  961. }
  962. function INSTALL_COMPOSE() {
  963. INFO "================== 安装Docker Compose =================="
  964. TAG=`curl -s https://api.github.com/repos/docker/compose/releases/latest | jq -r '.tag_name'`
  965. url="https://github.com/docker/compose/releases/download/$TAG/docker-compose-$(uname -s)-$(uname -m)"
  966. MAX_ATTEMPTS=3
  967. attempt=0
  968. success=false
  969. save_path="/usr/local/bin"
  970. chmod +x $save_path/docker-compose &>/dev/null
  971. if ! command -v docker-compose &> /dev/null || [ -z "$(docker-compose --version)" ]; then
  972. WARN "Docker Compose 未安装或安装不完整,正在进行安装..."
  973. while [ $attempt -lt $MAX_ATTEMPTS ]; do
  974. attempt=$((attempt + 1))
  975. wget --continue -q $url -O $save_path/docker-compose
  976. if [ $? -eq 0 ]; then
  977. chmod +x $save_path/docker-compose
  978. version_check=$(docker-compose --version)
  979. if [ -n "$version_check" ]; then
  980. success=true
  981. chmod +x $save_path/docker-compose
  982. break
  983. else
  984. WARN "Docker Compose 下载的文件不完整,正在尝试重新下载 (尝试次数: $attempt)"
  985. rm -f $save_path/docker-compose
  986. fi
  987. fi
  988. ERROR "Docker Compose 下载失败,正在尝试重新下载 (尝试次数: $attempt)"
  989. done
  990. if $success; then
  991. INFO "Docker Compose 安装成功,版本为:$(docker-compose --version)"
  992. else
  993. ERROR "Docker Compose 下载失败,请尝试手动安装docker-compose"
  994. exit 1
  995. fi
  996. else
  997. chmod +x $save_path/docker-compose
  998. INFO "Docker Compose 安装成功,版本为:$(docker-compose --version)"
  999. fi
  1000. }
  1001. function INSTALL_DOCKER_CN() {
  1002. MAX_ATTEMPTS=3
  1003. attempt=0
  1004. success=false
  1005. cpu_arch=$(uname -m)
  1006. save_path="/opt/docker_tgz"
  1007. mkdir -p $save_path
  1008. docker_ver="docker-26.1.4.tgz"
  1009. case $cpu_arch in
  1010. "arm64")
  1011. url="https://gitlab.com/dqzboy/docker/-/raw/main/stable/aarch64/$docker_ver"
  1012. ;;
  1013. "aarch64")
  1014. url="https://gitlab.com/dqzboy/docker/-/raw/main/stable/aarch64/$docker_ver"
  1015. ;;
  1016. "x86_64")
  1017. url="https://gitlab.com/dqzboy/docker/-/raw/main/stable/x86_64/$docker_ver"
  1018. ;;
  1019. *)
  1020. ERROR "不支持的CPU架构: $cpu_arch"
  1021. exit 1
  1022. ;;
  1023. esac
  1024. if ! command -v docker &> /dev/null; then
  1025. while [ $attempt -lt $MAX_ATTEMPTS ]; do
  1026. attempt=$((attempt + 1))
  1027. WARN "Docker 未安装,正在进行安装..."
  1028. wget -P "$save_path" "$url" &>/dev/null
  1029. if [ $? -eq 0 ]; then
  1030. success=true
  1031. break
  1032. fi
  1033. ERROR "Docker 安装失败,正在尝试重新下载 (尝试次数: $attempt)"
  1034. done
  1035. if $success; then
  1036. tar -xzf $save_path/$docker_ver -C $save_path
  1037. \cp $save_path/docker/* /usr/bin/ &>/dev/null
  1038. rm -rf $save_path
  1039. INFO "Docker 安装成功,版本为:$(docker --version)"
  1040. cat > /usr/lib/systemd/system/docker.service <<EOF
  1041. [Unit]
  1042. Description=Docker Application Container Engine
  1043. Documentation=https://docs.docker.com
  1044. After=network-online.target firewalld.service
  1045. Wants=network-online.target
  1046. [Service]
  1047. Type=notify
  1048. ExecStart=/usr/bin/dockerd
  1049. ExecReload=/bin/kill -s HUP
  1050. LimitNOFILE=infinity
  1051. LimitNPROC=infinity
  1052. LimitCORE=infinity
  1053. TimeoutStartSec=0
  1054. Delegate=yes
  1055. KillMode=process
  1056. Restart=on-failure
  1057. StartLimitBurst=3
  1058. StartLimitInterval=60s
  1059. [Install]
  1060. WantedBy=multi-user.target
  1061. EOF
  1062. systemctl daemon-reload
  1063. systemctl restart docker &>/dev/null
  1064. CHECK_DOCKER
  1065. systemctl enable docker &>/dev/null
  1066. else
  1067. ERROR "Docker 安装失败,请尝试手动安装"
  1068. exit 1
  1069. fi
  1070. else
  1071. INFO "Docker 已安装,安装版本为:$(docker --version)"
  1072. systemctl restart docker &>/dev/null
  1073. CHECK_DOCKER
  1074. fi
  1075. }
  1076. function INSTALL_COMPOSE_CN() {
  1077. INFO "================== 安装Docker Compose =================="
  1078. MAX_ATTEMPTS=3
  1079. attempt=0
  1080. cpu_arch=$(uname -m)
  1081. success=false
  1082. save_path="/usr/local/bin"
  1083. case $cpu_arch in
  1084. "arm64")
  1085. url="https://gitlab.com/dqzboy/docker/-/raw/main/stable/aarch64/docker-compose-linux-aarch64"
  1086. ;;
  1087. "aarch64")
  1088. url="https://gitlab.com/dqzboy/docker/-/raw/main/stable/aarch64/docker-compose-linux-aarch64"
  1089. ;;
  1090. "x86_64")
  1091. url="https://gitlab.com/dqzboy/docker/-/raw/main/stable/x86_64/docker-compose-linux-x86_64"
  1092. ;;
  1093. *)
  1094. ERROR "不支持的CPU架构: $cpu_arch"
  1095. exit 1
  1096. ;;
  1097. esac
  1098. chmod +x $save_path/docker-compose &>/dev/null
  1099. if ! command -v docker-compose &> /dev/null || [ -z "$(docker-compose --version)" ]; then
  1100. WARN "Docker Compose 未安装或安装不完整,正在进行安装..."
  1101. while [ $attempt -lt $MAX_ATTEMPTS ]; do
  1102. attempt=$((attempt + 1))
  1103. wget --continue -q $url -O $save_path/docker-compose
  1104. if [ $? -eq 0 ]; then
  1105. chmod +x $save_path/docker-compose
  1106. version_check=$(docker-compose --version)
  1107. if [ -n "$version_check" ]; then
  1108. success=true
  1109. chmod +x $save_path/docker-compose
  1110. break
  1111. else
  1112. WARN "Docker Compose 下载的文件不完整,正在尝试重新下载 (尝试次数: $attempt)"
  1113. rm -f $save_path/docker-compose
  1114. fi
  1115. fi
  1116. ERROR "Docker Compose 下载失败,正在尝试重新下载 (尝试次数: $attempt)"
  1117. done
  1118. if $success; then
  1119. INFO "Docker Compose 安装成功,版本为:$(docker-compose --version)"
  1120. else
  1121. ERROR "Docker Compose 下载失败,请尝试手动安装docker-compose"
  1122. exit 1
  1123. fi
  1124. else
  1125. chmod +x $save_path/docker-compose
  1126. INFO "Docker Compose 安装成功,版本为:$(docker-compose --version)"
  1127. fi
  1128. }
  1129. function append_auth_config() {
  1130. local file=$1
  1131. local auth_config="
  1132. auth:
  1133. htpasswd:
  1134. realm: basic-realm
  1135. path: /auth/htpasswd"
  1136. echo -e "$auth_config" | sudo tee -a "$file" > /dev/null
  1137. sed -ri "s@#- ./htpasswd:/auth/htpasswd@- ./htpasswd:/auth/htpasswd@g" ${PROXY_DIR}/docker-compose.yaml &>/dev/null
  1138. }
  1139. function update_docker_registry_url() {
  1140. local container_name=$1
  1141. sed -ri "s@- DOCKER_REGISTRY_URL=http://reg-docker-hub:5000@- DOCKER_REGISTRY_URL=http://${container_name}:5000@g" ${PROXY_DIR}/docker-compose.yaml
  1142. }
  1143. function DOWN_CONFIG() {
  1144. files=(
  1145. "dockerhub reg-docker-hub ${GITRAW}/config/registry-hub.yml"
  1146. "gcr reg-gcr ${GITRAW}/config/registry-gcr.yml"
  1147. "ghcr reg-ghcr ${GITRAW}/config/registry-ghcr.yml"
  1148. "quay reg-quay ${GITRAW}/config/registry-quay.yml"
  1149. "k8sgcr reg-k8s-gcr ${GITRAW}/config/registry-k8sgcr.yml"
  1150. "k8s reg-k8s ${GITRAW}/config/registry-k8s.yml"
  1151. "mcr reg-mcr ${GITRAW}/config/registry-mcr.yml"
  1152. "elastic reg-elastic ${GITRAW}/config/registry-elastic.yml"
  1153. )
  1154. selected_names=()
  1155. selected_files=()
  1156. selected_containers=()
  1157. echo -e "${YELLOW}-------------------------------------------------${RESET}"
  1158. echo -e "${GREEN}1) ${RESET}docker hub"
  1159. echo -e "${GREEN}2) ${RESET}gcr"
  1160. echo -e "${GREEN}3) ${RESET}ghcr"
  1161. echo -e "${GREEN}4) ${RESET}quay"
  1162. echo -e "${GREEN}5) ${RESET}k8s-gcr"
  1163. echo -e "${GREEN}6) ${RESET}k8s"
  1164. echo -e "${GREEN}7) ${RESET}mcr"
  1165. echo -e "${GREEN}8) ${RESET}elastic"
  1166. echo -e "${GREEN}9) ${RESET}all"
  1167. echo -e "${GREEN}0) ${RESET}exit"
  1168. echo -e "${YELLOW}-------------------------------------------------${RESET}"
  1169. read -e -p "$(INFO '输入序号下载对应配置文件,空格分隔多个选项. all下载所有: ')" choices_reg
  1170. if [[ "$choices_reg" == "9" ]]; then
  1171. for file in "${files[@]}"; do
  1172. file_name=$(echo "$file" | cut -d' ' -f1)
  1173. container_name=$(echo "$file" | cut -d' ' -f2)
  1174. file_url=$(echo "$file" | cut -d' ' -f3-)
  1175. selected_names+=("$file_name")
  1176. selected_containers+=("$container_name")
  1177. selected_files+=("$file_url")
  1178. wget -NP ${PROXY_DIR}/ $file_url &>/dev/null
  1179. done
  1180. selected_all=true
  1181. elif [[ "$choices_reg" == "0" ]]; then
  1182. WARN "退出下载配置! 首次安装如果没有配置无法启动服务,只能启动UI服务"
  1183. return
  1184. else
  1185. for choice in ${choices_reg}; do
  1186. if [[ $choice =~ ^[0-9]+$ ]] && ((choice > 0 && choice <= ${#files[@]})); then
  1187. file_name=$(echo "${files[$((choice - 1))]}" | cut -d' ' -f1)
  1188. container_name=$(echo "${files[$((choice - 1))]}" | cut -d' ' -f2)
  1189. file_url=$(echo "${files[$((choice - 1))]}" | cut -d' ' -f3-)
  1190. selected_names+=("$file_name")
  1191. selected_containers+=("$container_name")
  1192. selected_files+=("$file_url")
  1193. wget -NP ${PROXY_DIR}/ $file_url &>/dev/null
  1194. else
  1195. ERROR "无效的选择: $choice"
  1196. exit 1
  1197. fi
  1198. done
  1199. selected_all=false
  1200. if [[ "$user_choice" != "4" ]]; then
  1201. first_selected_container=${selected_containers[0]}
  1202. update_docker_registry_url "$first_selected_container"
  1203. fi
  1204. fi
  1205. read -e -p "$(echo -e ${INFO} ${GREEN}"是否需要配置镜像仓库访问账号和密码? (y/n): "${RESET})" config_auth
  1206. if [[ "$config_auth" == "y" ]]; then
  1207. while true; do
  1208. read -e -p "$(echo -e ${INFO} ${GREEN}"请输入账号名称: "${RESET})" username
  1209. if [[ -z "$username" ]]; then
  1210. ERROR "用户名不能为空。请重新输入"
  1211. else
  1212. break
  1213. fi
  1214. done
  1215. while true; do
  1216. read -e -p "$(echo -e ${INFO} ${GREEN}"请输入账号密码: "${RESET})" password
  1217. if [[ -z "$password" ]]; then
  1218. ERROR "密码不能为空。请重新输入"
  1219. else
  1220. break
  1221. fi
  1222. done
  1223. htpasswd -Bbn "$username" "$password" > ${PROXY_DIR}/htpasswd
  1224. for file_url in "${selected_files[@]}"; do
  1225. yml_name=$(basename "$file_url")
  1226. append_auth_config "${PROXY_DIR}/${yml_name}"
  1227. done
  1228. fi
  1229. }
  1230. function PROXY_HTTP() {
  1231. read -e -p "$(echo -e ${INFO} ${GREEN}"是否添加代理? (y/n): "${RESET})" modify_config
  1232. case $modify_config in
  1233. [Yy]* )
  1234. read -e -p "$(INFO "输入代理地址 (e.g. host:port): ")" url
  1235. while [[ -z "$url" ]]; do
  1236. WARN "代理地址不能为空,请重新输入。"
  1237. read -e -p "$(INFO "输入代理地址 (e.g. host:port): ")" url
  1238. done
  1239. sed -i "s@#environment:@environment:@g" ${PROXY_DIR}/docker-compose.yaml
  1240. sed -i "s@#- http=http://host:port@- http_proxy=http://${url}@g" ${PROXY_DIR}/docker-compose.yaml
  1241. sed -i "s@#- https=http://host:port@- https_proxy=http://${url}@g" ${PROXY_DIR}/docker-compose.yaml
  1242. INFO "你配置代理地址为: http://${url}."
  1243. ;;
  1244. [Nn]* )
  1245. WARN "跳过代理配置"
  1246. ;;
  1247. * )
  1248. ERROR "无效的输入。跳过配置修改"
  1249. ;;
  1250. esac
  1251. }
  1252. function ADD_PROXY() {
  1253. mkdir -p /etc/systemd/system/docker.service.d
  1254. if [ ! -f /etc/systemd/system/docker.service.d/http-proxy.conf ]; then
  1255. cat > /etc/systemd/system/docker.service.d/http-proxy.conf <<EOF
  1256. [Service]
  1257. Environment="HTTP_PROXY=http://$url"
  1258. Environment="HTTPS_PROXY=http://$url"
  1259. EOF
  1260. systemctl daemon-reload
  1261. systemctl restart docker &>/dev/null
  1262. CHECK_DOCKER
  1263. else
  1264. if ! grep -q "HTTP_PROXY=http://$url" /etc/systemd/system/docker.service.d/http-proxy.conf || ! grep -q "HTTPS_PROXY=http://$url" /etc/systemd/system/docker.service.d/http-proxy.conf; then
  1265. cat >> /etc/systemd/system/docker.service.d/http-proxy.conf <<EOF
  1266. [Service]
  1267. Environment="HTTP_PROXY=http://$url"
  1268. Environment="HTTPS_PROXY=http://$url"
  1269. EOF
  1270. systemctl daemon-reload
  1271. systemctl restart docker &>/dev/null
  1272. CHECK_DOCKER
  1273. else
  1274. INFO "======================================================= "
  1275. fi
  1276. fi
  1277. }
  1278. function START_CONTAINER() {
  1279. if [ "$modify_config" = "y" ] || [ "$modify_config" = "Y" ]; then
  1280. ADD_PROXY
  1281. else
  1282. INFO "拉取服务镜像并启动服务中,请稍等..."
  1283. fi
  1284. if [ "$selected_all" = true ]; then
  1285. docker-compose up -d --force-recreate
  1286. else
  1287. docker-compose up -d "${selected_names[@]}" registry-ui
  1288. fi
  1289. }
  1290. function RESTART_CONTAINER() {
  1291. if [ "$selected_all" = true ]; then
  1292. docker-compose restart
  1293. else
  1294. docker-compose restart "${selected_names[@]}"
  1295. fi
  1296. }
  1297. function INSTALL_DOCKER_PROXY() {
  1298. INFO "======================= 开始安装 ======================="
  1299. wget -P ${PROXY_DIR}/ ${GITRAW}/docker-compose.yaml &>/dev/null
  1300. DOWN_CONFIG
  1301. PROXY_HTTP
  1302. START_CONTAINER
  1303. }
  1304. function STOP_REMOVE_CONTAINER() {
  1305. if [[ -f "${PROXY_DIR}/${DOCKER_COMPOSE_FILE}" ]]; then
  1306. INFO "停止和移除所有容器"
  1307. docker-compose -f "${PROXY_DIR}/${DOCKER_COMPOSE_FILE}" down --remove-orphans
  1308. else
  1309. WARN "容器未运行,无需删除"
  1310. exit 1
  1311. fi
  1312. }
  1313. function UPDATE_CONFIG() {
  1314. while true; do
  1315. read -e -p "$(WARN '是否更新配置,更新前请确保您已备份现有配置,此操作不可逆? [y/n]: ')" update_conf
  1316. case "$update_conf" in
  1317. y|Y )
  1318. DOWN_CONFIG
  1319. RESTART_CONTAINER
  1320. break;;
  1321. n|N )
  1322. WARN "退出配置更新操作。"
  1323. break;;
  1324. * )
  1325. INFO "请输入 'y' 表示是,或者 'n' 表示否。";;
  1326. esac
  1327. done
  1328. }
  1329. function REMOVE_NONE_TAG() {
  1330. docker images | grep "^${IMAGE_NAME}.*<none>" | awk '{print $3}' | xargs -r docker rmi
  1331. images=$(docker images ${IMAGE_NAME} --format '{{.Repository}}:{{.Tag}}')
  1332. latest=$(echo "$images" | sort -V | tail -n1)
  1333. for image in $images
  1334. do
  1335. if [ "$image" != "$latest" ];then
  1336. docker rmi $image
  1337. fi
  1338. done
  1339. }
  1340. function PACKAGE() {
  1341. while true; do
  1342. read -e -p "$(INFO '是否执行软件包安装? [y/n]: ')" choice_package
  1343. case "$choice_package" in
  1344. y|Y )
  1345. INSTALL_PACKAGE
  1346. break;;
  1347. n|N )
  1348. WARN "跳过软件包安装步骤。"
  1349. break;;
  1350. * )
  1351. INFO "请输入 'y' 表示是,或者 'n' 表示否。";;
  1352. esac
  1353. done
  1354. }
  1355. function INSTALL_WEB() {
  1356. while true; do
  1357. read -e -p "$(INFO "是否安装WEB服务?(用来通过域名方式访问加速服务) [y/n]: ")" choice_service
  1358. if [[ "$choice_service" =~ ^[YyNn]$ ]]; then
  1359. if [[ "$choice_service" == "Y" || "$choice_service" == "y" ]]; then
  1360. while true; do
  1361. read -e -p "$(INFO "选择安装的WEB服务。安装Caddy可自动开启HTTPS [Nginx/Caddy]: ")" web_service
  1362. if [[ "$web_service" =~ ^(nginx|Nginx|caddy|Caddy)$ ]]; then
  1363. if [[ "$web_service" == "nginx" || "$web_service" == "Nginx" ]]; then
  1364. INSTALL_NGINX
  1365. break
  1366. elif [[ "$web_service" == "caddy" || "$web_service" == "Caddy" ]]; then
  1367. INSTALL_CADDY
  1368. break
  1369. fi
  1370. else
  1371. WARN "请输入'nginx' 或者 'caddy'"
  1372. fi
  1373. done
  1374. break
  1375. else
  1376. WARN "跳过WEB服务的安装。"
  1377. break
  1378. fi
  1379. else
  1380. INFO "请输入 'y' 表示是,或者 'n' 表示否。"
  1381. fi
  1382. done
  1383. }
  1384. function UPDATE_SERVICE() {
  1385. services=(
  1386. "dockerhub"
  1387. "gcr"
  1388. "ghcr"
  1389. "quay"
  1390. "k8sgcr"
  1391. "k8s"
  1392. )
  1393. selected_services=()
  1394. WARN "更新服务请在docker compose文件存储目录下执行脚本.默认存储路径: ${PROXY_DIR}"
  1395. echo -e "${YELLOW}-------------------------------------------------${RESET}"
  1396. echo -e "${GREEN}1) ${RESET}docker hub"
  1397. echo -e "${GREEN}2) ${RESET}gcr"
  1398. echo -e "${GREEN}3) ${RESET}ghcr"
  1399. echo -e "${GREEN}4) ${RESET}quay"
  1400. echo -e "${GREEN}5) ${RESET}k8s-gcr"
  1401. echo -e "${GREEN}6) ${RESET}k8s"
  1402. echo -e "${GREEN}7) ${RESET}mcr"
  1403. echo -e "${GREEN}8) ${RESET}elastic"
  1404. echo -e "${GREEN}9) ${RESET}all"
  1405. echo -e "${GREEN}0) ${RESET}exit"
  1406. echo -e "${YELLOW}-------------------------------------------------${RESET}"
  1407. read -e -p "$(INFO '输入序号选择对应服务,空格分隔多个选项. all选择所有: ')" choices_service
  1408. if [[ "$choices_service" == "9" ]]; then
  1409. for service_name in "${services[@]}"; do
  1410. if docker-compose ps --services | grep -q "^${service_name}$"; then
  1411. selected_services+=("$service_name")
  1412. else
  1413. WARN "服务 ${service_name}未运行,跳过更新。"
  1414. fi
  1415. done
  1416. INFO "更新的服务: ${selected_services[*]}"
  1417. elif [[ "$choices_service" == "0" ]]; then
  1418. WARN "退出更新服务!"
  1419. exit 1
  1420. else
  1421. for choice in ${choices_service}; do
  1422. if [[ $choice =~ ^[0-9]+$ ]] && ((choice >0 && choice <= ${#services[@]})); then
  1423. service_name="${services[$((choice -1))]}"
  1424. if docker-compose ps --services | grep -q "^${service_name}$"; then
  1425. selected_services+=("$service_name")
  1426. INFO "更新的服务: ${selected_services[*]}"
  1427. else
  1428. WARN "服务 ${service_name} 未运行,跳过更新。"
  1429. fi
  1430. else
  1431. ERROR "无效的选择: $choice"
  1432. exit 3
  1433. fi
  1434. done
  1435. fi
  1436. }
  1437. function PROMPT(){
  1438. PUBLIC_IP=$(curl -s https://ifconfig.me)
  1439. ALL_IPS=$(hostname -I)
  1440. INTERNAL_IP=$(echo "$ALL_IPS" | awk '$1!="127.0.0.1" && $1!="::1" && $1!="docker0" {print $1}')
  1441. echo
  1442. INFO "=================感谢您的耐心等待,安装已经完成=================="
  1443. INFO
  1444. INFO "请用浏览器访问 UI 面板: "
  1445. INFO "公网访问地址: http://$PUBLIC_IP:50000"
  1446. INFO "内网访问地址: http://$INTERNAL_IP:50000"
  1447. INFO
  1448. INFO "服务安装路径: ${PROXY_DIR}"
  1449. INFO
  1450. INFO "作者博客: https://dqzboy.com"
  1451. INFO "技术交流: https://t.me/dqzboyblog"
  1452. INFO "代码仓库: https://github.com/dqzboy/Docker-Proxy"
  1453. INFO
  1454. INFO "如果使用的是云服务器,且配置了域名与证书,请至安全组开放80、443端口;否则开放对应服务的监听端口"
  1455. INFO
  1456. INFO "================================================================"
  1457. }
  1458. function main() {
  1459. INFO "====================== 请选择操作 ======================"
  1460. echo "1) 新装服务"
  1461. echo "2) 重启服务"
  1462. echo "3) 更新服务"
  1463. echo "4) 更新配置"
  1464. echo "5) 卸载服务"
  1465. read -e -p "$(INFO '输入对应数字并按 Enter 键: ')" user_choice
  1466. case $user_choice in
  1467. 1)
  1468. CHECK_OS
  1469. CHECK_PACKAGE_MANAGER
  1470. CHECK_PKG_MANAGER
  1471. CHECKMEM
  1472. CHECKFIRE
  1473. CHECKBBR
  1474. PACKAGE
  1475. INSTALL_WEB
  1476. while true; do
  1477. INFO "====================== 安装Docker ======================"
  1478. read -e -p "$(INFO '安装环境确认.[国外输1;大陆输2]: ')" deploy_docker
  1479. case "$deploy_docker" in
  1480. 1 )
  1481. INSTALL_DOCKER
  1482. INSTALL_COMPOSE
  1483. break;;
  1484. 2 )
  1485. INSTALL_DOCKER_CN
  1486. INSTALL_COMPOSE_CN
  1487. break;;
  1488. * )
  1489. INFO "请输入 '1' 表示国外,或者 '2' 表示大陆。";;
  1490. esac
  1491. done
  1492. INSTALL_DOCKER_PROXY
  1493. PROMPT
  1494. ;;
  1495. 2)
  1496. INFO "======================= 重启服务 ======================="
  1497. docker-compose restart
  1498. INFO "======================= 重启完成 ======================="
  1499. ;;
  1500. 3)
  1501. INFO "======================= 更新服务 ======================="
  1502. UPDATE_SERVICE
  1503. if [ ${#selected_services[@]} -eq 0 ]; then
  1504. WARN "没有需要更新的服务。"
  1505. else
  1506. docker-compose pull ${selected_services[*]}
  1507. docker-compose up -d --force-recreate ${selected_services[*]}
  1508. fi
  1509. INFO "======================= 更新完成 ======================="
  1510. ;;
  1511. 4)
  1512. INFO "======================= 更新配置 ======================="
  1513. UPDATE_CONFIG
  1514. INFO "======================= 更新完成 ======================="
  1515. ;;
  1516. 5)
  1517. INFO "======================= 卸载服务 ======================="
  1518. WARN "注意: 卸载服务会一同将项目本地的镜像缓存删除,请执行卸载之前确定是否需要备份本地的镜像缓存文件"
  1519. while true; do
  1520. read -e -p "$(INFO '本人已知晓后果,确认卸载服务? [y/n]: ')" uninstall
  1521. case "$uninstall" in
  1522. y|Y )
  1523. STOP_REMOVE_CONTAINER
  1524. REMOVE_NONE_TAG
  1525. docker rmi --force $(docker images -q ${IMAGE_NAME}) &>/dev/null
  1526. docker rmi --force $(docker images -q ${UI_IMAGE_NAME}) &>/dev/null
  1527. rm -rf ${PROXY_DIR} &>/dev/null
  1528. INFO "服务已经卸载,感谢你的使用!"
  1529. INFO "========================================================"
  1530. break;;
  1531. n|N )
  1532. WARN "退出卸载服务."
  1533. break;;
  1534. * )
  1535. INFO "请输入 'y' 表示是,或者 'n' 表示否。";;
  1536. esac
  1537. done
  1538. ;;
  1539. *)
  1540. WARN "输入了无效的选择。请重新运行脚本并选择1-4的选项。"
  1541. ;;
  1542. esac
  1543. }
  1544. main