DockerProxy_Install.sh 112 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326
  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[32mVPS 推荐\033[0m(\033[34mRackNerd 高性价比便宜VPS\033[0m):\033[34;4mhttps://my.racknerd.com/aff.php?aff=12151\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. BLUE="\033[0;34m"
  33. MAGENTA="\033[0;35m"
  34. CYAN="\033[0;36m"
  35. WHITE="\033[1;37m"
  36. BLACK="\033[0;30m"
  37. PINK="\033[0;95m"
  38. LIGHT_GREEN="\033[1;32m"
  39. LIGHT_RED="\033[1;31m"
  40. LIGHT_YELLOW="\033[1;33m"
  41. LIGHT_BLUE="\033[1;34m"
  42. LIGHT_MAGENTA="\033[1;35m"
  43. LIGHT_CYAN="\033[1;36m"
  44. LIGHT_PINK="\033[1;95m"
  45. BRIGHT_CYAN="\033[96m"
  46. BOLD="\033[1m"
  47. UNDERLINE="\033[4m"
  48. BLINK="\033[5m"
  49. REVERSE="\033[7m"
  50. INFO="[${GREEN}INFO${RESET}]"
  51. ERROR="[${RED}ERROR${RESET}]"
  52. WARN="[${YELLOW}WARN${RESET}]"
  53. function INFO() {
  54. echo -e "${INFO} ${1}"
  55. }
  56. function ERROR() {
  57. echo -e "${ERROR} ${1}"
  58. }
  59. function WARN() {
  60. echo -e "${WARN} ${1}"
  61. }
  62. function PROMPT_Y_N() {
  63. echo -e "[${LIGHT_GREEN}y${RESET}/${LIGHT_BLUE}n${RESET}]: "
  64. }
  65. PROMPT_YES_NO=$(PROMPT_Y_N)
  66. function SEPARATOR() {
  67. echo -e "${INFO}${BOLD}${LIGHT_BLUE}======================== ${1} ========================${RESET}"
  68. }
  69. # 检查是否以root权限运行
  70. if [[ $EUID -ne 0 ]]; then
  71. ERROR "此脚本必须以root权限运行!"
  72. exit 1
  73. fi
  74. PROXY_DIR="/data/registry-proxy"
  75. mkdir -p ${PROXY_DIR}
  76. cd "${PROXY_DIR}"
  77. GITRAW="https://raw.githubusercontent.com/dqzboy/Docker-Proxy/main"
  78. CNGITRAW="https://gitee.com/boydqz/Docker-Proxy/raw/main"
  79. # docker registry
  80. IMAGE_NAME="dqzboy/registry"
  81. UI_IMAGE_NAME="dqzboy/docker-registry-ui"
  82. DOCKER_COMPOSE_FILE="docker-compose.yaml"
  83. # HubCMD-UI
  84. CMDUI_IMAGE_NAME="dqzboy/hubcmd-ui"
  85. CMDUI_COMPOSE_FILE="${GITRAW}/hubcmdui/${DOCKER_COMPOSE_FILE}"
  86. # Registry Domain prefix
  87. REGISTRY_SLD="ui、hub、gcr、ghcr、k8sgcr、k8s、quay、mcr、elastic、nvcr"
  88. RECORDS=("ui" "hub" "gcr" "ghcr" "k8sgcr" "k8s" "quay" "mcr" "elastic" "nvcr")
  89. attempts=0
  90. maxAttempts=3
  91. # registry services
  92. function REGISTRY_MENU() {
  93. echo -e "${YELLOW}-------------------------------------------------${RESET}"
  94. echo -e "${GREEN}1)${RESET} ${BOLD}docker hub${RESET}"
  95. echo -e "${GREEN}2)${RESET} ${BOLD}gcr${RESET}"
  96. echo -e "${GREEN}3)${RESET} ${BOLD}ghcr${RESET}"
  97. echo -e "${GREEN}4)${RESET} ${BOLD}quay${RESET}"
  98. echo -e "${GREEN}5)${RESET} ${BOLD}k8s-gcr${RESET}"
  99. echo -e "${GREEN}6)${RESET} ${BOLD}k8s${RESET}"
  100. echo -e "${GREEN}7)${RESET} ${BOLD}mcr${RESET}"
  101. echo -e "${GREEN}8)${RESET} ${BOLD}elastic${RESET}"
  102. echo -e "${GREEN}9)${RESET} ${BOLD}nvcr${RESET}"
  103. echo -e "${GREEN}10)${RESET} ${BOLD}all${RESET}"
  104. echo -e "${GREEN}0)${RESET} ${BOLD}exit${RESET}"
  105. echo -e "${YELLOW}-------------------------------------------------${RESET}"
  106. }
  107. function REGISTRY_SER_MENU() {
  108. echo -e "${YELLOW}-------------------------------------------------${RESET}"
  109. echo -e "${GREEN}1)${RESET} ${BOLD}docker hub${RESET}"
  110. echo -e "${GREEN}2)${RESET} ${BOLD}gcr${RESET}"
  111. echo -e "${GREEN}3)${RESET} ${BOLD}ghcr${RESET}"
  112. echo -e "${GREEN}4)${RESET} ${BOLD}quay${RESET}"
  113. echo -e "${GREEN}5)${RESET} ${BOLD}k8s-gcr${RESET}"
  114. echo -e "${GREEN}6)${RESET} ${BOLD}k8s${RESET}"
  115. echo -e "${GREEN}7)${RESET} ${BOLD}mcr${RESET}"
  116. echo -e "${GREEN}8)${RESET} ${BOLD}elastic${RESET}"
  117. echo -e "${GREEN}9)${RESET} ${BOLD}nvcr${RESET}"
  118. echo -e "${GREEN}0)${RESET} ${BOLD}exit${RESET}"
  119. echo -e "${YELLOW}-------------------------------------------------${RESET}"
  120. }
  121. # 定义Docker容器服务名称
  122. CONTAINER_SERVICES() {
  123. services=(
  124. "dockerhub"
  125. "gcr"
  126. "ghcr"
  127. "quay"
  128. "k8sgcr"
  129. "k8s"
  130. "mcr"
  131. "elastic"
  132. "nvcr"
  133. )
  134. }
  135. REGISTRY_FILES() {
  136. files=(
  137. "dockerhub registry-hub.yml"
  138. "gcr registry-gcr.yml"
  139. "ghcr registry-ghcr.yml"
  140. "quay registry-quay.yml"
  141. "k8sgcr registry-k8sgcr.yml"
  142. "k8s registry-k8s.yml"
  143. "mcr registry-mcr.yml"
  144. "elastic registry-elastic.yml"
  145. "nvcr registry-nvcr.yml"
  146. )
  147. }
  148. function CHECK_OS() {
  149. SEPARATOR "检查环境"
  150. OSVER=$(cat /etc/os-release | grep -o '[0-9]' | head -n 1)
  151. if [ -f /etc/os-release ]; then
  152. . /etc/os-release
  153. else
  154. echo "无法确定发行版"
  155. exit 1
  156. fi
  157. case "$ID" in
  158. "centos")
  159. repo_type="centos"
  160. ;;
  161. "debian")
  162. repo_type="debian"
  163. ;;
  164. "rhel")
  165. repo_type="rhel"
  166. ;;
  167. "ubuntu")
  168. repo_type="ubuntu"
  169. ;;
  170. "opencloudos")
  171. repo_type="centos"
  172. ;;
  173. "rocky")
  174. repo_type="centos"
  175. ;;
  176. *)
  177. WARN "此脚本目前不支持您的系统: $ID"
  178. exit 1
  179. ;;
  180. esac
  181. INFO "System release:: $NAME"
  182. INFO "System version: $VERSION"
  183. INFO "System ID: $ID"
  184. INFO "System ID Like: $ID_LIKE"
  185. }
  186. function CHECK_PACKAGE_MANAGER() {
  187. if command -v dnf &> /dev/null; then
  188. package_manager="dnf"
  189. elif command -v yum &> /dev/null; then
  190. package_manager="yum"
  191. elif command -v apt-get &> /dev/null; then
  192. package_manager="apt-get"
  193. elif command -v apt &> /dev/null; then
  194. package_manager="apt"
  195. else
  196. ERROR "不受支持的软件包管理器."
  197. exit 1
  198. fi
  199. }
  200. function CHECK_PKG_MANAGER() {
  201. if command -v rpm &> /dev/null; then
  202. pkg_manager="rpm"
  203. elif command -v dpkg &> /dev/null; then
  204. pkg_manager="dpkg"
  205. elif command -v apt &> /dev/null; then
  206. pkg_manager="apt"
  207. else
  208. ERROR "无法确定包管理系统."
  209. exit 1
  210. fi
  211. }
  212. function CHECK_COMPOSE_CMD() {
  213. if command -v docker &> /dev/null && docker compose version &> /dev/null; then
  214. DOCKER_COMPOSE_CMD="docker compose"
  215. elif command -v docker-compose &> /dev/null; then
  216. DOCKER_COMPOSE_CMD="docker-compose"
  217. else
  218. WARN "未检查到Docker Compose客户端工具,请通过脚本安装部署!"
  219. fi
  220. }
  221. function CHECKMEM() {
  222. memory_usage=$(free | awk '/^Mem:/ {printf "%.2f", $3/$2 * 100}')
  223. memory_usage=${memory_usage%.*}
  224. if [[ $memory_usage -gt 90 ]]; then
  225. read -e -p "$(WARN "内存占用率${LIGHT_RED}高于 70%($memory_usage%)${RESET} 是否继续安装? ${PROMPT_YES_NO}")" continu
  226. if [ "$continu" == "n" ] || [ "$continu" == "N" ]; then
  227. exit 1
  228. fi
  229. else
  230. INFO "内存资源充足.请继续 ${LIGHT_GREEN}($memory_usage%)${RESET}"
  231. fi
  232. }
  233. function CHECKFIRE() {
  234. systemctl stop firewalld &> /dev/null
  235. systemctl disable firewalld &> /dev/null
  236. systemctl stop iptables &> /dev/null
  237. systemctl disable iptables &> /dev/null
  238. ufw disable &> /dev/null
  239. INFO "防火墙已被禁用."
  240. if [[ "$repo_type" == "centos" || "$repo_type" == "rhel" ]]; then
  241. if sestatus | grep "SELinux status" | grep -q "enabled"; then
  242. WARN "SELinux 已启用。禁用 SELinux..."
  243. setenforce 0
  244. sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
  245. INFO "SELinux 已被禁用."
  246. else
  247. INFO "SELinux 已被禁用."
  248. fi
  249. fi
  250. }
  251. function CHECKBBR() {
  252. kernel_version=$(uname -r | awk -F "-" '{print $1}')
  253. read -e -p "$(WARN "是否开启${BRIGHT_CYAN}BBR${RESET},优化网络带宽提高网络性能? ${PROMPT_YES_NO}")" choice_bbr
  254. case $choice_bbr in
  255. y | Y)
  256. version_compare=$(echo "${kernel_version} 4.9" | awk '{if ($1 >= $2) print "yes"; else print "no"}')
  257. if [ "$version_compare" != "yes" ]; then
  258. WARN "你的内核版本小于4.9,无法启动BBR,需要你手动升级内核"
  259. exit 0
  260. fi
  261. sysctl net.ipv4.tcp_available_congestion_control | grep -q "bbr"
  262. if [ $? -eq 0 ]; then
  263. INFO "你的服务器已经启动 ${BRIGHT_CYAN}BBR${RESET}"
  264. else
  265. INFO "开启BBR中..."
  266. modprobe tcp_bbr
  267. if [ $? -eq 0 ]; then
  268. INFO "${BRIGHT_CYAN}BBR${RESET} 模块${LIGHT_GREEN}添加成功${RESET}"
  269. else
  270. ERROR "${BRIGHT_CYAN}BBR${RESET} 模块${LIGHT_RED}添加失败${RESET},请执行 ${LIGHT_CYAN}sysctl -p${RESET} 检查."
  271. exit 1
  272. fi
  273. if [ ! -d /etc/modules-load.d/ ]; then
  274. mkdir -p /etc/modules-load.d/
  275. fi
  276. if [ ! -f /etc/modules-load.d/tcp_bbr.conf ]; then
  277. touch /etc/modules-load.d/tcp_bbr.conf
  278. fi
  279. if ! grep -q "tcp_bbr" /etc/modules-load.d/tcp_bbr.conf ; then
  280. echo 'tcp_bbr' >> /etc/modules-load.d/tcp_bbr.conf
  281. fi
  282. for setting in "net.core.default_qdisc=fq" "net.ipv4.tcp_congestion_control=bbr"; do
  283. if ! grep -q "$setting" /etc/sysctl.conf; then
  284. echo "$setting" >> /etc/sysctl.conf
  285. fi
  286. done
  287. sysctl -p &> /dev/null
  288. if [ $? -ne 0 ]; then
  289. ERROR "应用sysctl设置过程中发生了一个错误,请执行 ${LIGHT_CYAN}sysctl -p${RESET} 检查."
  290. exit 2
  291. fi
  292. lsmod | grep tcp_bbr &> /dev/null
  293. if [ $? -eq 0 ]; then
  294. INFO "${BRIGHT_CYAN}BBR${RESET} 已经${LIGHT_GREEN}成功开启${RESET}"
  295. else
  296. ERROR "${BRIGHT_CYAN}BBR${RESET} 开启${LIGHT_RED}失败${RESET},请执行 ${LIGHT_CYAN}sysctl -p${RESET} 检查."
  297. exit 3
  298. fi
  299. WARN "如果 ${BRIGHT_CYAN}BBR${RESET} 开启后${LIGHT_YELLOW}未生效${RESET},请执行 ${LIGHT_BLUE}reboot${RESET} 重启服务器使其BBR模块生效"
  300. fi
  301. ;;
  302. n | N)
  303. INFO "不开启BBR"
  304. ;;
  305. *)
  306. WARN "输入了无效的选择。请重新输入${LIGHT_GREEN}y${RESET} 或 ${LIGHT_YELLOW}n${RESET}"
  307. CHECKBBR
  308. ;;
  309. esac
  310. }
  311. function INSTALL_PACKAGE(){
  312. SEPARATOR "安装依赖"
  313. INFO "检查依赖安装情况,请稍等 ..."
  314. TIMEOUT=300
  315. PACKAGES_APT=(
  316. lsof jq wget apache2-utils tar
  317. )
  318. PACKAGES_YUM=(
  319. epel-release lsof jq wget yum-utils httpd-tools tar
  320. )
  321. if [ "$package_manager" = "dnf" ] || [ "$package_manager" = "yum" ]; then
  322. for package in "${PACKAGES_YUM[@]}"; do
  323. if $pkg_manager -q "$package" &>/dev/null; then
  324. INFO "${LIGHT_GREEN}已经安装${RESET} $package ..."
  325. else
  326. INFO "${LIGHT_CYAN}正在安装${RESET} $package ..."
  327. start_time=$(date +%s)
  328. $package_manager -y install "$package" --skip-broken > /dev/null 2>&1 &
  329. install_pid=$!
  330. while [[ $(($(date +%s) - $start_time)) -lt $TIMEOUT ]] && kill -0 $install_pid &>/dev/null; do
  331. sleep 1
  332. done
  333. if kill -0 $install_pid &>/dev/null; then
  334. read -e -p "$(WARN "$package 的安装时间超过 ${LIGHT_YELLOW}$TIMEOUT 秒${RESET}。是否继续? ${PROMPT_YES_NO}")" continue_install
  335. if [ "$continue_install" != "y" ]; then
  336. ERROR "$package 的安装超时。退出脚本。"
  337. exit 1
  338. else
  339. continue
  340. fi
  341. fi
  342. wait $install_pid
  343. if [ $? -ne 0 ]; then
  344. ERROR "$package 安装失败。请检查系统安装源,然后再次运行此脚本!请尝试手动执行安装: ${LIGHT_BLUE}$package_manager -y install $package${RESET}"
  345. exit 1
  346. fi
  347. fi
  348. done
  349. elif [ "$package_manager" = "apt-get" ] || [ "$package_manager" = "apt" ];then
  350. dpkg --configure -a &>/dev/null
  351. $package_manager update &>/dev/null
  352. for package in "${PACKAGES_APT[@]}"; do
  353. if $pkg_manager -s "$package" &>/dev/null; then
  354. INFO "已经安装 $package ..."
  355. else
  356. INFO "正在安装 $package ..."
  357. $package_manager install -y $package > /dev/null 2>&1
  358. if [ $? -ne 0 ]; then
  359. ERROR "安装 $package 失败,请检查系统安装源之后再次运行此脚本!请尝试手动执行安装: ${LIGHT_BLUE}$package_manager -y install $package${RESET}"
  360. exit 1
  361. fi
  362. fi
  363. done
  364. else
  365. ERROR "无法确定包管理系统,脚本无法继续执行,请检查!"
  366. exit 1
  367. fi
  368. }
  369. function INSTALL_CADDY() {
  370. SEPARATOR "安装Caddy"
  371. start_caddy() {
  372. systemctl enable caddy.service &>/dev/null
  373. systemctl restart caddy.service
  374. status=$(systemctl is-active caddy)
  375. if [ "$status" = "active" ]; then
  376. INFO "Caddy 服务运行正常,请继续..."
  377. else
  378. ERROR "Caddy 服务未运行,请查看日志报错,定位问题后再次执行脚本!"
  379. ERROR "-----------服务启动失败,请查看错误日志 ↓↓↓-----------"
  380. journalctl -u caddy.service --no-pager
  381. ERROR "-----------服务启动失败,请查看错误日志 ↑↑↑-----------"
  382. exit 1
  383. fi
  384. }
  385. check_caddy() {
  386. if pgrep "caddy" > /dev/null; then
  387. INFO "Caddy 已在运行."
  388. else
  389. WARN "Caddy 未运行。尝试启动 Caddy..."
  390. start_attempts=3
  391. for ((i=1; i<=$start_attempts; i++)); do
  392. start_caddy
  393. if pgrep "caddy" > /dev/null; then
  394. INFO "Caddy 已成功启动."
  395. break
  396. else
  397. if [ $i -eq $start_attempts ]; then
  398. ERROR "Caddy 在尝试 $start_attempts 后无法启动。请检查配置"
  399. exit 1
  400. else
  401. WARN "在 $i 时间内启动 Caddy 失败。重试..."
  402. fi
  403. fi
  404. done
  405. fi
  406. }
  407. if [ "$package_manager" = "dnf" ]; then
  408. if which caddy &>/dev/null; then
  409. INFO "Caddy 已经安装."
  410. else
  411. INFO "正在安装Caddy程序,请稍候..."
  412. $package_manager -y install 'dnf-command(copr)' &>/dev/null
  413. $package_manager -y copr enable @caddy/caddy &>/dev/null
  414. while [ $attempts -lt $maxAttempts ]; do
  415. $package_manager -y install caddy &>/dev/null
  416. if [ $? -ne 0 ]; then
  417. ((attempts++))
  418. WARN "正在尝试安装Caddy >>> (Attempt: $attempts)"
  419. if [ $attempts -eq $maxAttempts ]; then
  420. ERROR "Caddy installation failed. Please try installing manually."
  421. echo "命令: $package_manager -y install 'dnf-command(copr)' && $package_manager -y copr enable @caddy/caddy && $package_manager -y install caddy"
  422. exit 1
  423. fi
  424. else
  425. INFO "已安装 Caddy."
  426. break
  427. fi
  428. done
  429. fi
  430. check_caddy
  431. elif [ "$package_manager" = "yum" ]; then
  432. if which caddy &>/dev/null; then
  433. INFO "Caddy 已经安装."
  434. else
  435. INFO "正在安装Caddy程序,请稍候..."
  436. $package_manager -y install yum-plugin-copr &>/dev/null
  437. $package_manager -y copr enable @caddy/caddy &>/dev/null
  438. while [ $attempts -lt $maxAttempts ]; do
  439. $package_manager -y install caddy &>/dev/null
  440. if [ $? -ne 0 ]; then
  441. ((attempts++))
  442. WARN "正在尝试安装Caddy >>> (Attempt: $attempts)"
  443. if [ $attempts -eq $maxAttempts ]; then
  444. ERROR "Caddy installation failed. Please try installing manually."
  445. echo "命令: $package_manager -y install 'dnf-command(copr)' && $package_manager -y copr enable @caddy/caddy && $package_manager -y install caddy"
  446. exit 1
  447. fi
  448. else
  449. INFO "已安装 Caddy."
  450. break
  451. fi
  452. done
  453. fi
  454. check_caddy
  455. elif [ "$package_manager" = "apt" ] || [ "$package_manager" = "apt-get" ];then
  456. dpkg --configure -a &>/dev/null
  457. $package_manager update &>/dev/null
  458. if $pkg_manager -s "caddy" &>/dev/null; then
  459. INFO "Caddy 已安装,跳过..."
  460. else
  461. INFO "安装 Caddy 请稍等 ..."
  462. $package_manager install -y debian-keyring debian-archive-keyring apt-transport-https &>/dev/null
  463. 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
  464. curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list &>/dev/null
  465. $package_manager update &>/dev/null
  466. $package_manager install -y caddy &>/dev/null
  467. if [ $? -ne 0 ]; then
  468. ERROR "安装 Caddy 失败,请检查系统安装源之后再次运行此脚本!请尝试手动执行安装:$package_manager -y install caddy"
  469. exit 1
  470. fi
  471. fi
  472. check_caddy
  473. else
  474. WARN "无法确定包管理系统."
  475. exit 1
  476. fi
  477. }
  478. function CONFIG_CADDY() {
  479. SEPARATOR "配置Caddy"
  480. while true; do
  481. INFO "${LIGHT_GREEN}>>> 域名解析主机记录(即域名前缀):${RESET} ${LIGHT_CYAN}${REGISTRY_SLD}${RESET}"
  482. WARN "${LIGHT_GREEN}>>> 只需选择你部署的服务进行解析即可${RESET},${LIGHT_YELLOW}无需将上面提示中所有的主机记录进行解析${RESET}"
  483. read -e -p "$(WARN "是否配置Caddy,实现自动HTTPS? 执行前需在DNS服务商对部署服务解析主机记录 ${PROMPT_YES_NO}")" caddy_conf
  484. case "$caddy_conf" in
  485. y|Y )
  486. read -e -p "$(INFO "请输入你的域名${LIGHT_BLUE}[例: baidu.com]${RESET} ${LIGHT_RED}不可为空${RESET}: ")" caddy_domain
  487. read -e -p "$(INFO "请输入要配置的${LIGHT_MAGENTA}主机记录${RESET},用逗号分隔${LIGHT_BLUE}[例: ui,hub]${RESET}: ")" selected_records
  488. # 验证输入的主机记录
  489. local valid_records=("${RECORDS[@]}")
  490. IFS=',' read -r -a records_array <<< "$selected_records"
  491. local invalid_records=()
  492. for record in "${records_array[@]}"; do
  493. if ! [[ " ${valid_records[@]} " =~ " ${record} " ]]; then
  494. invalid_records+=("$record")
  495. fi
  496. done
  497. if [[ ${#invalid_records[@]} -gt 0 ]]; then
  498. ERROR "无效的主机记录: ${LIGHT_RED}${invalid_records[@]}${RESET}"
  499. INFO "请输入有效的主机记录: ${LIGHT_GREEN}${REGISTRY_SLD}${RESET}"
  500. continue
  501. fi
  502. declare -A record_templates
  503. record_templates[ui]="ui.$caddy_domain {
  504. reverse_proxy localhost:50000 {
  505. header_up Host {host}
  506. header_up Origin {scheme}://{host}
  507. header_up X-Forwarded-For {remote_addr}
  508. header_up X-Forwarded-Proto {scheme}
  509. header_up X-Forwarded-Ssl on
  510. header_up X-Forwarded-Port {server_port}
  511. header_up X-Forwarded-Host {host}
  512. }
  513. }"
  514. record_templates[hub]="hub.$caddy_domain {
  515. reverse_proxy localhost:51000 {
  516. header_up Host {host}
  517. header_up X-Real-IP {remote_addr}
  518. header_up X-Forwarded-For {remote_addr}
  519. header_up X-Nginx-Proxy true
  520. }
  521. }"
  522. record_templates[ghcr]="ghcr.$caddy_domain {
  523. reverse_proxy localhost:52000 {
  524. header_up Host {host}
  525. header_up X-Real-IP {remote_addr}
  526. header_up X-Forwarded-For {remote_addr}
  527. header_up X-Nginx-Proxy true
  528. }
  529. }"
  530. record_templates[gcr]="gcr.$caddy_domain {
  531. reverse_proxy localhost:53000 {
  532. header_up Host {host}
  533. header_up X-Real-IP {remote_addr}
  534. header_up X-Forwarded-For {remote_addr}
  535. header_up X-Nginx-Proxy true
  536. }
  537. }"
  538. record_templates[k8sgcr]="k8sgcr.$caddy_domain {
  539. reverse_proxy localhost:54000 {
  540. header_up Host {host}
  541. header_up X-Real-IP {remote_addr}
  542. header_up X-Forwarded-For {remote_addr}
  543. header_up X-Nginx-Proxy true
  544. }
  545. }"
  546. record_templates[k8s]="k8s.$caddy_domain {
  547. reverse_proxy localhost:55000 {
  548. header_up Host {host}
  549. header_up X-Real-IP {remote_addr}
  550. header_up X-Forwarded-For {remote_addr}
  551. header_up X-Nginx-Proxy true
  552. }
  553. }"
  554. record_templates[quay]="quay.$caddy_domain {
  555. reverse_proxy localhost:56000 {
  556. header_up Host {host}
  557. header_up X-Real-IP {remote_addr}
  558. header_up X-Forwarded-For {remote_addr}
  559. header_up X-Nginx-Proxy true
  560. }
  561. }"
  562. record_templates[mcr]="mcr.$caddy_domain {
  563. reverse_proxy localhost:57000 {
  564. header_up Host {host}
  565. header_up X-Real-IP {remote_addr}
  566. header_up X-Forwarded-For {remote_addr}
  567. header_up X-Nginx-Proxy true
  568. }
  569. }"
  570. record_templates[elastic]="elastic.$caddy_domain {
  571. reverse_proxy localhost:58000 {
  572. header_up Host {host}
  573. header_up X-Real-IP {remote_addr}
  574. header_up X-Forwarded-For {remote_addr}
  575. header_up X-Nginx-Proxy true
  576. }
  577. }"
  578. record_templates[nvcr]="nvcr.$caddy_domain {
  579. reverse_proxy localhost:59000 {
  580. header_up Host {host}
  581. header_up X-Real-IP {remote_addr}
  582. header_up X-Forwarded-For {remote_addr}
  583. header_up X-Nginx-Proxy true
  584. }
  585. }"
  586. > /etc/caddy/Caddyfile
  587. for record in "${records_array[@]}"; do
  588. if [[ -n "${record_templates[$record]}" ]]; then
  589. echo "${record_templates[$record]}" >> /etc/caddy/Caddyfile
  590. fi
  591. done
  592. start_attempts=3
  593. for ((i=1; i<=$start_attempts; i++)); do
  594. start_caddy
  595. if pgrep "caddy" > /dev/null; then
  596. INFO "重新载入配置成功. Caddy服务启动完成"
  597. break
  598. else
  599. if [ $i -eq $start_attempts ]; then
  600. ERROR "Caddy 在尝试 $start_attempts 后无法启动。请检查配置"
  601. exit 1
  602. else
  603. WARN "第 $i 次启动 Caddy 失败。重试..."
  604. fi
  605. fi
  606. done
  607. break;;
  608. n|N )
  609. WARN "退出配置 Caddy 操作。"
  610. break;;
  611. * )
  612. INFO "请输入 ${LIGHT_GREEN}y${RESET} 或 ${LIGHT_YELLOW}n${RESET}";;
  613. esac
  614. done
  615. }
  616. function INSTALL_NGINX() {
  617. SEPARATOR "安装Nginx"
  618. start_nginx() {
  619. systemctl enable nginx &>/dev/null
  620. systemctl restart nginx
  621. status=$(systemctl is-active nginx)
  622. if [ "$status" = "active" ]; then
  623. INFO "Nginx 服务运行正常,请继续..."
  624. else
  625. ERROR "Nginx 服务未运行,请查看日志报错,定位问题后再次执行脚本!"
  626. ERROR "-----------服务启动失败,请查看错误日志 ↓↓↓-----------"
  627. journalctl -u nginx.service --no-pager
  628. ERROR "-----------服务启动失败,请查看错误日志 ↑↑↑-----------"
  629. exit 1
  630. fi
  631. }
  632. check_nginx() {
  633. if pgrep "nginx" > /dev/null; then
  634. INFO "Nginx 已在运行."
  635. else
  636. WARN "Nginx 未运行。尝试启动 Nginx..."
  637. start_attempts=3
  638. for ((i=1; i<=$start_attempts; i++)); do
  639. start_nginx
  640. if pgrep "nginx" > /dev/null; then
  641. INFO "Nginx 已成功启动."
  642. break
  643. else
  644. if [ $i -eq $start_attempts ]; then
  645. ERROR "Nginx 在尝试 $start_attempts 次后无法启动。请检查配置"
  646. exit 1
  647. else
  648. WARN "第 $i 次启动 Nginx 失败。重试..."
  649. fi
  650. fi
  651. done
  652. fi
  653. }
  654. if [ "$package_manager" = "dnf" ] || [ "$package_manager" = "yum" ]; then
  655. if which nginx &>/dev/null; then
  656. INFO "Nginx 已经安装."
  657. else
  658. INFO "正在安装Nginx程序,请稍候..."
  659. NGINX="nginx-1.24.0-1.el${OSVER}.ngx.x86_64.rpm"
  660. rm -f ${NGINX}
  661. wget http://nginx.org/packages/centos/${OSVER}/x86_64/RPMS/${NGINX} &>/dev/null
  662. while [ $attempts -lt $maxAttempts ]; do
  663. $package_manager -y install ${NGINX} &>/dev/null
  664. if [ $? -ne 0 ]; then
  665. ((attempts++))
  666. WARN "正在尝试安装Nginx >>> (Attempt: $attempts)"
  667. if [ $attempts -eq $maxAttempts ]; then
  668. ERROR "Nginx installation failed. Please try installing manually."
  669. rm -f ${NGINX}
  670. echo "命令: wget http://nginx.org/packages/centos/${OSVER}/x86_64/RPMS/${NGINX} && $package_manager -y install ${NGINX}"
  671. exit 1
  672. fi
  673. else
  674. INFO "已安装 Nginx."
  675. rm -f ${NGINX}
  676. break
  677. fi
  678. done
  679. fi
  680. check_nginx
  681. elif [ "$package_manager" = "apt-get" ] || [ "$package_manager" = "apt" ];then
  682. dpkg --configure -a &>/dev/null
  683. $package_manager update &>/dev/null
  684. if $pkg_manager -s "nginx" &>/dev/null; then
  685. INFO "nginx 已安装,跳过..."
  686. else
  687. INFO "安装 nginx 请稍等 ..."
  688. $package_manager install -y nginx > /dev/null 2>&1
  689. if [ $? -ne 0 ]; then
  690. ERROR "安装 nginx 失败,请检查系统安装源之后再次运行此脚本!请尝试手动执行安装:$package_manager -y install nginx"
  691. exit 1
  692. fi
  693. fi
  694. check_nginx
  695. else
  696. WARN "无法确定包管理系统."
  697. exit 1
  698. fi
  699. }
  700. function CONFIG_NGINX() {
  701. SEPARATOR "配置Nginx"
  702. while true; do
  703. WARN "自行安装的 Nginx ${LIGHT_RED}请勿执行此操作${RESET},${LIGHT_BLUE}以防覆盖原有配置${RESET}"
  704. INFO "${LIGHT_GREEN}>>> 域名解析主机记录(即域名前缀):${RESET} ${LIGHT_CYAN}${REGISTRY_SLD}${RESET}"
  705. WARN "${LIGHT_GREEN}>>> 只需选择你部署的服务进行解析即可${RESET},${LIGHT_YELLOW}无需将上面提示中所有的主机记录进行解析${RESET}"
  706. read -e -p "$(WARN "是否配置 Nginx?配置完成后需在DNS服务商解析主机记录 ${PROMPT_YES_NO}")" nginx_conf
  707. case "$nginx_conf" in
  708. y|Y )
  709. read -e -p "$(INFO "请输入你的域名${LIGHT_BLUE}[例: baidu.com]${RESET} ${LIGHT_RED}不可为空${RESET}: ")" nginx_domain
  710. read -e -p "$(INFO "请输入要配置的${LIGHT_MAGENTA}主机记录${RESET},用逗号分隔${LIGHT_BLUE}[例: ui,hub]${RESET}: ")" selected_records
  711. # 验证输入的主机记录
  712. local valid_records=("${RECORDS[@]}")
  713. IFS=',' read -r -a records_array <<< "$selected_records"
  714. local invalid_records=()
  715. for record in "${records_array[@]}"; do
  716. if ! [[ " ${valid_records[@]} " =~ " ${record} " ]]; then
  717. invalid_records+=("$record")
  718. fi
  719. done
  720. if [[ ${#invalid_records[@]} -gt 0 ]]; then
  721. ERROR "无效的主机记录: ${LIGHT_RED}${invalid_records[@]}${RESET}"
  722. INFO "请输入有效的主机记录: ${LIGHT_GREEN}${REGISTRY_SLD}${RESET}"
  723. continue
  724. fi
  725. declare -A record_templates
  726. record_templates[ui]="server {
  727. listen 80;
  728. #listen 443 ssl;
  729. server_name ui.$nginx_domain;
  730. #ssl_certificate /path/to/your_domain_name.crt;
  731. #ssl_certificate_key /path/to/your_domain_name.key;
  732. #ssl_session_timeout 1d;
  733. #ssl_session_cache shared:SSL:50m;
  734. #ssl_session_tickets off;
  735. #ssl_protocols TLSv1.2 TLSv1.3;
  736. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  737. #ssl_prefer_server_ciphers on;
  738. #ssl_buffer_size 8k;
  739. proxy_connect_timeout 600;
  740. proxy_send_timeout 600;
  741. proxy_read_timeout 600;
  742. send_timeout 600;
  743. location / {
  744. proxy_pass http://localhost:50000;
  745. proxy_set_header Host \$host;
  746. proxy_set_header Origin \$scheme://\$host;
  747. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  748. proxy_set_header X-Forwarded-Proto \$scheme;
  749. proxy_set_header X-Forwarded-Ssl on;
  750. proxy_set_header X-Forwarded-Port \$server_port;
  751. proxy_set_header X-Forwarded-Host \$host;
  752. }
  753. }"
  754. record_templates[hub]="server {
  755. listen 80;
  756. #listen 443 ssl;
  757. server_name hub.$nginx_domain;
  758. #ssl_certificate /path/to/your_domain_name.crt;
  759. #ssl_certificate_key /path/to/your_domain_name.key;
  760. #ssl_session_timeout 1d;
  761. #ssl_session_cache shared:SSL:50m;
  762. #ssl_session_tickets off;
  763. #ssl_protocols TLSv1.2 TLSv1.3;
  764. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  765. #ssl_prefer_server_ciphers on;
  766. #ssl_buffer_size 8k;
  767. proxy_connect_timeout 600;
  768. proxy_send_timeout 600;
  769. proxy_read_timeout 600;
  770. send_timeout 600;
  771. location / {
  772. proxy_pass http://localhost:51000;
  773. proxy_set_header Host \$host;
  774. proxy_set_header X-Real-IP \$remote_addr;
  775. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  776. proxy_set_header X-Nginx-Proxy true;
  777. proxy_buffering off;
  778. proxy_redirect off;
  779. }
  780. }"
  781. record_templates[ghcr]="server {
  782. listen 80;
  783. #listen 443 ssl;
  784. server_name ghcr.$nginx_domain;
  785. #ssl_certificate /path/to/your_domain_name.crt;
  786. #ssl_certificate_key /path/to/your_domain_name.key;
  787. #ssl_session_timeout 1d;
  788. #ssl_session_cache shared:SSL:50m;
  789. #ssl_session_tickets off;
  790. #ssl_protocols TLSv1.2 TLSv1.3;
  791. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  792. #ssl_prefer_server_ciphers on;
  793. #ssl_buffer_size 8k;
  794. proxy_connect_timeout 600;
  795. proxy_send_timeout 600;
  796. proxy_read_timeout 600;
  797. send_timeout 600;
  798. location / {
  799. proxy_pass http://localhost:52000;
  800. proxy_set_header Host \$host;
  801. proxy_set_header X-Real-IP \$remote_addr;
  802. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  803. proxy_set_header X-Nginx-Proxy true;
  804. proxy_buffering off;
  805. proxy_redirect off;
  806. }
  807. }"
  808. record_templates[gcr]="server {
  809. listen 80;
  810. #listen 443 ssl;
  811. server_name gcr.$nginx_domain;
  812. #ssl_certificate /path/to/your_domain_name.crt;
  813. #ssl_certificate_key /path/to/your_domain_name.key;
  814. #ssl_session_timeout 1d;
  815. #ssl_session_cache shared:SSL:50m;
  816. #ssl_session_tickets off;
  817. #ssl_protocols TLSv1.2 TLSv1.3;
  818. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  819. #ssl_prefer_server_ciphers on;
  820. #ssl_buffer_size 8k;
  821. proxy_connect_timeout 600;
  822. proxy_send_timeout 600;
  823. proxy_read_timeout 600;
  824. send_timeout 600;
  825. location / {
  826. proxy_pass http://localhost:53000;
  827. proxy_set_header Host \$host;
  828. proxy_set_header X-Real-IP \$remote_addr;
  829. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  830. proxy_set_header X-Nginx-Proxy true;
  831. proxy_buffering off;
  832. proxy_redirect off;
  833. }
  834. }"
  835. record_templates[k8sgcr]="server {
  836. listen 80;
  837. #listen 443 ssl;
  838. server_name k8sgcr.$nginx_domain;
  839. #ssl_certificate /path/to/your_domain_name.crt;
  840. #ssl_certificate_key /path/to/your_domain_name.key;
  841. #ssl_session_timeout 1d;
  842. #ssl_session_cache shared:SSL:50m;
  843. #ssl_session_tickets off;
  844. #ssl_protocols TLSv1.2 TLSv1.3;
  845. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  846. #ssl_prefer_server_ciphers on;
  847. #ssl_buffer_size 8k;
  848. proxy_connect_timeout 600;
  849. proxy_send_timeout 600;
  850. proxy_read_timeout 600;
  851. send_timeout 600;
  852. location / {
  853. proxy_pass http://localhost:54000;
  854. proxy_set_header Host \$host;
  855. proxy_set_header X-Real-IP \$remote_addr;
  856. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  857. proxy_set_header X-Nginx-Proxy true;
  858. proxy_buffering off;
  859. proxy_redirect off;
  860. }
  861. }"
  862. record_templates[k8s]="server {
  863. listen 80;
  864. #listen 443 ssl;
  865. server_name k8s.$nginx_domain;
  866. #ssl_certificate /path/to/your_domain_name.crt;
  867. #ssl_certificate_key /path/to/your_domain_name.key;
  868. #ssl_session_timeout 1d;
  869. #ssl_session_cache shared:SSL:50m;
  870. #ssl_session_tickets off;
  871. #ssl_protocols TLSv1.2 TLSv1.3;
  872. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  873. #ssl_prefer_server_ciphers on;
  874. #ssl_buffer_size 8k;
  875. proxy_connect_timeout 600;
  876. proxy_send_timeout 600;
  877. proxy_read_timeout 600;
  878. send_timeout 600;
  879. location / {
  880. proxy_pass http://localhost:55000;
  881. proxy_set_header Host \$host;
  882. proxy_set_header X-Real-IP \$remote_addr;
  883. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  884. proxy_set_header X-Nginx-Proxy true;
  885. proxy_buffering off;
  886. proxy_redirect off;
  887. }
  888. }"
  889. record_templates[quay]="server {
  890. listen 80;
  891. #listen 443 ssl;
  892. server_name quay.$nginx_domain;
  893. #ssl_certificate /path/to/your_domain_name.crt;
  894. #ssl_certificate_key /path/to/your_domain_name.key;
  895. #ssl_session_timeout 1d;
  896. #ssl_session_cache shared:SSL:50m;
  897. #ssl_session_tickets off;
  898. #ssl_protocols TLSv1.2 TLSv1.3;
  899. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  900. #ssl_prefer_server_ciphers on;
  901. #ssl_buffer_size 8k;
  902. proxy_connect_timeout 600;
  903. proxy_send_timeout 600;
  904. proxy_read_timeout 600;
  905. send_timeout 600;
  906. location / {
  907. proxy_pass http://localhost:56000;
  908. proxy_set_header Host \$host;
  909. proxy_set_header X-Real-IP \$remote_addr;
  910. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  911. proxy_set_header X-Nginx-Proxy true;
  912. proxy_buffering off;
  913. proxy_redirect off;
  914. }
  915. }"
  916. record_templates[mcr]="server {
  917. listen 80;
  918. #listen 443 ssl;
  919. server_name mcr.$nginx_domain;
  920. #ssl_certificate /path/to/your_domain_name.crt;
  921. #ssl_certificate_key /path/to/your_domain_name.key;
  922. #ssl_session_timeout 1d;
  923. #ssl_session_cache shared:SSL:50m;
  924. #ssl_session_tickets off;
  925. #ssl_protocols TLSv1.2 TLSv1.3;
  926. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  927. #ssl_prefer_server_ciphers on;
  928. #ssl_buffer_size 8k;
  929. proxy_connect_timeout 600;
  930. proxy_send_timeout 600;
  931. proxy_read_timeout 600;
  932. send_timeout 600;
  933. location / {
  934. proxy_pass http://localhost:57000;
  935. proxy_set_header Host \$host;
  936. proxy_set_header X-Real-IP \$remote_addr;
  937. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  938. proxy_set_header X-Nginx-Proxy true;
  939. proxy_buffering off;
  940. proxy_redirect off;
  941. }
  942. }"
  943. record_templates[elastic]="server {
  944. listen 80;
  945. #listen 443 ssl;
  946. server_name elastic.$nginx_domain;
  947. #ssl_certificate /path/to/your_domain_name.crt;
  948. #ssl_certificate_key /path/to/your_domain_name.key;
  949. #ssl_session_timeout 1d;
  950. #ssl_session_cache shared:SSL:50m;
  951. #ssl_session_tickets off;
  952. #ssl_protocols TLSv1.2 TLSv1.3;
  953. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  954. #ssl_prefer_server_ciphers on;
  955. #ssl_buffer_size 8k;
  956. proxy_connect_timeout 600;
  957. proxy_send_timeout 600;
  958. proxy_read_timeout 600;
  959. send_timeout 600;
  960. location / {
  961. proxy_pass http://localhost:58000;
  962. proxy_set_header Host \$host;
  963. proxy_set_header X-Real-IP \$remote_addr;
  964. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  965. proxy_set_header X-Nginx-Proxy true;
  966. proxy_buffering off;
  967. proxy_redirect off;
  968. }
  969. }"
  970. record_templates[nvcr]="server {
  971. listen 80;
  972. #listen 443 ssl;
  973. server_name nvcr.$nginx_domain;
  974. #ssl_certificate /path/to/your_domain_name.crt;
  975. #ssl_certificate_key /path/to/your_domain_name.key;
  976. #ssl_session_timeout 1d;
  977. #ssl_session_cache shared:SSL:50m;
  978. #ssl_session_tickets off;
  979. #ssl_protocols TLSv1.2 TLSv1.3;
  980. #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  981. #ssl_prefer_server_ciphers on;
  982. #ssl_buffer_size 8k;
  983. proxy_connect_timeout 600;
  984. proxy_send_timeout 600;
  985. proxy_read_timeout 600;
  986. send_timeout 600;
  987. location / {
  988. proxy_pass http://localhost:59000;
  989. proxy_set_header Host \$host;
  990. proxy_set_header X-Real-IP \$remote_addr;
  991. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  992. proxy_set_header X-Nginx-Proxy true;
  993. proxy_buffering off;
  994. proxy_redirect off;
  995. }
  996. }"
  997. > /etc/nginx/conf.d/docker-proxy.conf
  998. for record in "${records_array[@]}"; do
  999. if [[ -n "${record_templates[$record]}" ]]; then
  1000. echo "${record_templates[$record]}" >> /etc/nginx/conf.d/docker-proxy.conf
  1001. fi
  1002. done
  1003. start_attempts=3
  1004. for ((i=1; i<=$start_attempts; i++)); do
  1005. start_nginx
  1006. if pgrep "nginx" > /dev/null; then
  1007. INFO "重新载入配置成功. Nginx服务启动完成"
  1008. break
  1009. else
  1010. if [ $i -eq $start_attempts ]; then
  1011. ERROR "Nginx 在尝试 $start_attempts 后无法启动。请检查配置"
  1012. exit 1
  1013. else
  1014. WARN "第 $i 次启动 Nginx 失败。重试..."
  1015. fi
  1016. fi
  1017. done
  1018. break;;
  1019. n|N )
  1020. WARN "退出配置 Nginx 操作。"
  1021. break;;
  1022. * )
  1023. INFO "请输入 ${LIGHT_GREEN}y${RESET} 或 ${LIGHT_YELLOW}n${RESET}";;
  1024. esac
  1025. done
  1026. }
  1027. function CHECK_DOCKER() {
  1028. status=$(systemctl is-active docker)
  1029. if [ "$status" = "active" ]; then
  1030. INFO "Docker 服务运行正常,请继续..."
  1031. else
  1032. ERROR "Docker 服务未运行,请查看日志报错,定位问题后再次执行脚本!"
  1033. ERROR "-----------服务启动失败,请查看错误日志 ↓↓↓-----------"
  1034. journalctl -u docker.service --no-pager
  1035. ERROR "-----------服务启动失败,请查看错误日志 ↑↑↑-----------"
  1036. exit 1
  1037. fi
  1038. }
  1039. function INSTALL_DOCKER() {
  1040. repo_file="docker-ce.repo"
  1041. url="https://download.docker.com/linux/$repo_type"
  1042. MAX_ATTEMPTS=3
  1043. attempt=0
  1044. success=false
  1045. if [ "$repo_type" = "centos" ] || [ "$repo_type" = "rhel" ]; then
  1046. if ! command -v docker &> /dev/null;then
  1047. while [[ $attempt -lt $MAX_ATTEMPTS ]]; do
  1048. attempt=$((attempt + 1))
  1049. WARN "Docker 未安装,正在进行安装..."
  1050. yum-config-manager --add-repo $url/$repo_file &>/dev/null
  1051. $package_manager -y install docker-ce &>/dev/null
  1052. if [ $? -eq 0 ]; then
  1053. success=true
  1054. break
  1055. fi
  1056. ERROR "Docker 安装失败,正在尝试重新下载 (尝试次数: $attempt)"
  1057. done
  1058. if $success; then
  1059. INFO "Docker 安装成功,版本为:$(docker --version)"
  1060. systemctl restart docker &>/dev/null
  1061. CHECK_DOCKER
  1062. systemctl enable docker &>/dev/null
  1063. else
  1064. ERROR "Docker 安装失败,请尝试手动安装"
  1065. exit 1
  1066. fi
  1067. else
  1068. INFO "Docker 已安装,安装版本为:$(docker --version)"
  1069. systemctl restart docker | grep -E "ERROR|ELIFECYCLE|WARN"
  1070. fi
  1071. elif [ "$repo_type" == "ubuntu" ]; then
  1072. if ! command -v docker &> /dev/null;then
  1073. while [[ $attempt -lt $MAX_ATTEMPTS ]]; do
  1074. attempt=$((attempt + 1))
  1075. WARN "Docker 未安装,正在进行安装..."
  1076. curl -fsSL $url/gpg | sudo apt-key add - &>/dev/null
  1077. add-apt-repository "deb [arch=amd64] $url $(lsb_release -cs) stable" <<< $'\n' &>/dev/null
  1078. $package_manager -y install docker-ce docker-ce-cli containerd.io &>/dev/null
  1079. if [ $? -eq 0 ]; then
  1080. success=true
  1081. break
  1082. fi
  1083. ERROR "Docker 安装失败,正在尝试重新下载 (尝试次数: $attempt)"
  1084. done
  1085. if $success; then
  1086. INFO "Docker 安装成功,版本为:$(docker --version)"
  1087. systemctl restart docker &>/dev/null
  1088. CHECK_DOCKER
  1089. systemctl enable docker &>/dev/null
  1090. else
  1091. ERROR "Docker 安装失败,请尝试手动安装"
  1092. exit 1
  1093. fi
  1094. else
  1095. INFO "Docker 已安装,安装版本为:$(docker --version)"
  1096. systemctl restart docker | grep -E "ERROR|ELIFECYCLE|WARN"
  1097. fi
  1098. elif [ "$repo_type" == "debian" ]; then
  1099. if ! command -v docker &> /dev/null;then
  1100. while [[ $attempt -lt $MAX_ATTEMPTS ]]; do
  1101. attempt=$((attempt + 1))
  1102. WARN "Docker 未安装,正在进行安装..."
  1103. curl -fsSL $url/gpg | sudo apt-key add - &>/dev/null
  1104. add-apt-repository "deb [arch=amd64] $url $(lsb_release -cs) stable" <<< $'\n' &>/dev/null
  1105. $package_manager -y install docker-ce docker-ce-cli containerd.io &>/dev/null
  1106. if [ $? -eq 0 ]; then
  1107. success=true
  1108. break
  1109. fi
  1110. ERROR "Docker 安装失败,正在尝试重新下载 (尝试次数: $attempt)"
  1111. done
  1112. if $success; then
  1113. INFO "Docker 安装成功,版本为:$(docker --version)"
  1114. systemctl restart docker &>/dev/null
  1115. CHECK_DOCKER
  1116. systemctl enable docker &>/dev/null
  1117. else
  1118. ERROR "Docker 安装失败,请尝试手动安装"
  1119. exit 1
  1120. fi
  1121. else
  1122. INFO "Docker 已安装,安装版本为:$(docker --version)"
  1123. systemctl restart docker &>/dev/null
  1124. CHECK_DOCKER
  1125. fi
  1126. else
  1127. ERROR "不支持的操作系统."
  1128. exit 1
  1129. fi
  1130. }
  1131. function INSTALL_COMPOSE() {
  1132. SEPARATOR "安装Docker Compose"
  1133. TAG=`curl -s https://api.github.com/repos/docker/compose/releases/latest | jq -r '.tag_name'`
  1134. url="https://github.com/docker/compose/releases/download/$TAG/docker-compose-$(uname -s)-$(uname -m)"
  1135. MAX_ATTEMPTS=3
  1136. attempt=0
  1137. success=false
  1138. save_path="/usr/local/bin"
  1139. chmod +x $save_path/docker-compose &>/dev/null
  1140. if ! command -v docker-compose &> /dev/null || [ -z "$(docker-compose --version)" ]; then
  1141. WARN "Docker Compose 未安装或安装不完整,正在进行安装..."
  1142. while [ $attempt -lt $MAX_ATTEMPTS ]; do
  1143. attempt=$((attempt + 1))
  1144. wget --continue -q $url -O $save_path/docker-compose
  1145. if [ $? -eq 0 ]; then
  1146. chmod +x $save_path/docker-compose
  1147. version_check=$(docker-compose --version)
  1148. if [ -n "$version_check" ]; then
  1149. success=true
  1150. chmod +x $save_path/docker-compose
  1151. break
  1152. else
  1153. WARN "Docker Compose 下载的文件不完整,正在尝试重新下载 (尝试次数: $attempt)"
  1154. rm -f $save_path/docker-compose
  1155. fi
  1156. fi
  1157. ERROR "Docker Compose 下载失败,正在尝试重新下载 (尝试次数: $attempt)"
  1158. done
  1159. if $success; then
  1160. INFO "Docker Compose 安装成功,版本为:$(docker-compose --version)"
  1161. else
  1162. ERROR "Docker Compose 下载失败,请尝试手动安装docker-compose"
  1163. exit 1
  1164. fi
  1165. else
  1166. chmod +x $save_path/docker-compose
  1167. INFO "Docker Compose 已经安装,版本为:$(docker-compose --version)"
  1168. fi
  1169. }
  1170. function INSTALL_DOCKER_CN() {
  1171. MAX_ATTEMPTS=3
  1172. attempt=0
  1173. success=false
  1174. cpu_arch=$(uname -m)
  1175. save_path="/opt/docker_tgz"
  1176. mkdir -p $save_path
  1177. docker_ver="docker-27.1.2.tgz"
  1178. case $cpu_arch in
  1179. "arm64")
  1180. url="https://raw.gitcode.com/dqzboy/docker/blobs/2ce4d6bc245ab1c4525b3e6f55db7d710681e56f/$docker_ver"
  1181. ;;
  1182. "aarch64")
  1183. url="https://raw.gitcode.com/dqzboy/docker/blobs/2ce4d6bc245ab1c4525b3e6f55db7d710681e56f/$docker_ver"
  1184. ;;
  1185. "x86_64")
  1186. url="https://raw.gitcode.com/dqzboy/docker/blobs/179729785ed2c4a8c99aeb546fb6ac2864d7da5c/$docker_ver"
  1187. ;;
  1188. *)
  1189. ERROR "不支持的CPU架构: $cpu_arch"
  1190. exit 1
  1191. ;;
  1192. esac
  1193. if ! command -v docker &> /dev/null; then
  1194. while [ $attempt -lt $MAX_ATTEMPTS ]; do
  1195. attempt=$((attempt + 1))
  1196. WARN "Docker 未安装,正在进行安装..."
  1197. wget -P "$save_path" "$url" &>/dev/null
  1198. if [ $? -eq 0 ]; then
  1199. success=true
  1200. break
  1201. fi
  1202. ERROR "Docker 安装失败,正在尝试重新下载 (尝试次数: $attempt)"
  1203. done
  1204. if $success; then
  1205. tar -xzf $save_path/$docker_ver -C $save_path
  1206. \cp $save_path/docker/* /usr/bin/ &>/dev/null
  1207. rm -rf $save_path
  1208. INFO "Docker 安装成功,版本为:$(docker --version)"
  1209. cat > /usr/lib/systemd/system/docker.service <<EOF
  1210. [Unit]
  1211. Description=Docker Application Container Engine
  1212. Documentation=https://docs.docker.com
  1213. After=network-online.target firewalld.service
  1214. Wants=network-online.target
  1215. [Service]
  1216. Type=notify
  1217. ExecStart=/usr/bin/dockerd
  1218. ExecReload=/bin/kill -s HUP
  1219. LimitNOFILE=infinity
  1220. LimitNPROC=infinity
  1221. LimitCORE=infinity
  1222. TimeoutStartSec=0
  1223. Delegate=yes
  1224. KillMode=process
  1225. Restart=on-failure
  1226. StartLimitBurst=3
  1227. StartLimitInterval=60s
  1228. [Install]
  1229. WantedBy=multi-user.target
  1230. EOF
  1231. systemctl daemon-reload
  1232. systemctl restart docker &>/dev/null
  1233. CHECK_DOCKER
  1234. systemctl enable docker &>/dev/null
  1235. else
  1236. ERROR "Docker 安装失败,请尝试手动安装"
  1237. exit 1
  1238. fi
  1239. else
  1240. INFO "Docker 已安装,安装版本为:$(docker --version)"
  1241. systemctl restart docker &>/dev/null
  1242. CHECK_DOCKER
  1243. fi
  1244. }
  1245. function INSTALL_COMPOSE_CN() {
  1246. SEPARATOR "安装Docker Compose"
  1247. MAX_ATTEMPTS=3
  1248. attempt=0
  1249. cpu_arch=$(uname -m)
  1250. success=false
  1251. save_path="/usr/local/bin"
  1252. case $cpu_arch in
  1253. "arm64")
  1254. url="https://raw.gitcode.com/dqzboy/docker/blobs/b7be39a4442a103749c769ca48740e8e1a93a16c/docker-compose-linux-aarch64"
  1255. ;;
  1256. "aarch64")
  1257. url="https://raw.gitcode.com/dqzboy/docker/blobs/b7be39a4442a103749c769ca48740e8e1a93a16c/docker-compose-linux-aarch64"
  1258. ;;
  1259. "x86_64")
  1260. url="https://raw.gitcode.com/dqzboy/docker/blobs/df1b7935ced481a20d16141d97e163823ee793f5/docker-compose-linux-x86_64"
  1261. ;;
  1262. *)
  1263. ERROR "不支持的CPU架构: $cpu_arch"
  1264. exit 1
  1265. ;;
  1266. esac
  1267. chmod +x $save_path/docker-compose &>/dev/null
  1268. if ! command -v docker-compose &> /dev/null || [ -z "$(docker-compose --version)" ]; then
  1269. WARN "Docker Compose 未安装或安装不完整,正在进行安装..."
  1270. while [ $attempt -lt $MAX_ATTEMPTS ]; do
  1271. attempt=$((attempt + 1))
  1272. wget --continue -q $url -O $save_path/docker-compose
  1273. if [ $? -eq 0 ]; then
  1274. chmod +x $save_path/docker-compose
  1275. version_check=$(docker-compose --version)
  1276. if [ -n "$version_check" ]; then
  1277. success=true
  1278. chmod +x $save_path/docker-compose
  1279. break
  1280. else
  1281. WARN "Docker Compose 下载的文件不完整,正在尝试重新下载 (尝试次数: $attempt)"
  1282. rm -f $save_path/docker-compose
  1283. fi
  1284. fi
  1285. ERROR "Docker Compose 下载失败,正在尝试重新下载 (尝试次数: $attempt)"
  1286. done
  1287. if $success; then
  1288. INFO "Docker Compose 安装成功,版本为:$(docker-compose --version)"
  1289. else
  1290. ERROR "Docker Compose 下载失败,请尝试手动安装docker-compose"
  1291. exit 1
  1292. fi
  1293. else
  1294. chmod +x $save_path/docker-compose
  1295. INFO "Docker Compose 安装成功,版本为:$(docker-compose --version)"
  1296. fi
  1297. }
  1298. function update_docker_registry_url() {
  1299. local container_name=$1
  1300. if [[ -f "${PROXY_DIR}/${DOCKER_COMPOSE_FILE}" ]]; then
  1301. sed -i "s@- DOCKER_REGISTRY_URL=.*@- DOCKER_REGISTRY_URL=http://${container_name}:5000@g" ${PROXY_DIR}/${DOCKER_COMPOSE_FILE}
  1302. else
  1303. ERROR "文件 ${LIGHT_CYAN}${PROXY_DIR}/${DOCKER_COMPOSE_FILE} ${RESET} ${LIGHT_RED}不存在${RESET},导致容器无法应用新配置"
  1304. exit 1
  1305. fi
  1306. }
  1307. function CONFIG_FILES() {
  1308. while true; do
  1309. read -e -p "$(INFO "安装环境确认 [${LIGHT_GREEN}国外输1${RESET} ${LIGHT_YELLOW}国内输2${RESET}] > ")" install_docker_reg
  1310. case "$install_docker_reg" in
  1311. 1 )
  1312. files=(
  1313. "dockerhub reg-docker-hub ${GITRAW}/config/registry-hub.yml"
  1314. "gcr reg-gcr ${GITRAW}/config/registry-gcr.yml"
  1315. "ghcr reg-ghcr ${GITRAW}/config/registry-ghcr.yml"
  1316. "quay reg-quay ${GITRAW}/config/registry-quay.yml"
  1317. "k8sgcr reg-k8s-gcr ${GITRAW}/config/registry-k8sgcr.yml"
  1318. "k8s reg-k8s ${GITRAW}/config/registry-k8s.yml"
  1319. "mcr reg-mcr ${GITRAW}/config/registry-mcr.yml"
  1320. "elastic reg-elastic ${GITRAW}/config/registry-elastic.yml"
  1321. "nvcr reg-nvcr ${GITRAW}/config/registry-nvcr.yml"
  1322. )
  1323. break;;
  1324. 2 )
  1325. files=(
  1326. "dockerhub reg-docker-hub ${CNGITRAW}/config/registry-hub.yml"
  1327. "gcr reg-gcr ${CNGITRAW}/config/registry-gcr.yml"
  1328. "ghcr reg-ghcr ${CNGITRAW}/config/registry-ghcr.yml"
  1329. "quay reg-quay ${CNGITRAW}/config/registry-quay.yml"
  1330. "k8sgcr reg-k8s-gcr ${CNGITRAW}/config/registry-k8sgcr.yml"
  1331. "k8s reg-k8s ${CNGITRAW}/config/registry-k8s.yml"
  1332. "mcr reg-mcr ${CNGITRAW}/config/registry-mcr.yml"
  1333. "elastic reg-elastic ${CNGITRAW}/config/registry-elastic.yml"
  1334. "nvcr reg-nvcr ${CNGITRAW}/config/registry-nvcr.yml"
  1335. )
  1336. break;;
  1337. * )
  1338. INFO "请输入 ${LIGHT_GREEN}1${RESET} 表示国外 或者 ${LIGHT_YELLOW}2${RESET} 表示大陆";;
  1339. esac
  1340. done
  1341. }
  1342. function DOWN_CONFIG() {
  1343. selected_names=()
  1344. selected_files=()
  1345. selected_containers=()
  1346. REGISTRY_MENU
  1347. read -e -p "$(INFO "输入序号下载对应配置文件,${LIGHT_YELLOW}空格分隔${RESET}多个选项. ${LIGHT_CYAN}all下载所有${RESET} > ")" choices_reg
  1348. while true; do
  1349. if [[ "$choices_reg" =~ ^[0-9]+([[:space:]][0-9]+)*$ ]]; then
  1350. valid=true
  1351. for choice in $choices_reg; do
  1352. if ((choice < 0 || choice > 10)); then
  1353. valid=false
  1354. break
  1355. fi
  1356. done
  1357. if $valid; then
  1358. break
  1359. fi
  1360. fi
  1361. WARN "无效输入,请重新输入${LIGHT_YELLOW} 0-10 ${RESET}序号"
  1362. read -e -p "$(INFO "输入序号下载对应配置文件,${LIGHT_YELLOW}空格分隔${RESET}多个选项. ${LIGHT_CYAN}all下载所有${RESET} > ")" choices_reg
  1363. done
  1364. if [[ "$choices_reg" == "10" ]]; then
  1365. for file in "${files[@]}"; do
  1366. file_name=$(echo "$file" | cut -d' ' -f1)
  1367. container_name=$(echo "$file" | cut -d' ' -f2)
  1368. file_url=$(echo "$file" | cut -d' ' -f3-)
  1369. selected_names+=("$file_name")
  1370. selected_containers+=("$container_name")
  1371. selected_files+=("$file_url")
  1372. wget -NP ${PROXY_DIR}/ $file_url &>/dev/null
  1373. done
  1374. selected_all=true
  1375. elif [[ "$choices_reg" == "0" ]]; then
  1376. WARN "退出下载配置! ${LIGHT_YELLOW}首次安装如果没有配置无法启动服务,只能启动UI服务${RESET}"
  1377. return
  1378. else
  1379. for choice in ${choices_reg}; do
  1380. if ((choice > 0 && choice < 10)); then
  1381. file_name=$(echo "${files[$((choice - 1))]}" | cut -d' ' -f1)
  1382. container_name=$(echo "${files[$((choice - 1))]}" | cut -d' ' -f2)
  1383. file_url=$(echo "${files[$((choice - 1))]}" | cut -d' ' -f3-)
  1384. selected_names+=("$file_name")
  1385. selected_containers+=("$container_name")
  1386. selected_files+=("$file_url")
  1387. wget -NP ${PROXY_DIR}/ $file_url &>/dev/null
  1388. fi
  1389. done
  1390. selected_all=false
  1391. # 非更新配置操作则执行下面步骤
  1392. if [[ "$main_choice" != "4" ]]; then
  1393. first_selected_container=${selected_containers[0]}
  1394. update_docker_registry_url "$first_selected_container"
  1395. fi
  1396. fi
  1397. WARN "${LIGHT_GREEN}>>> 提示:${RESET} ${LIGHT_BLUE}Proxy代理缓存过期时间${RESET} ${MAGENTA}单位:ns、us、ms、s、m、h.默认ns,0禁用缓存过期${RESET}"
  1398. read -e -p "$(INFO "是否要修改缓存时间? ${PROMPT_YES_NO}")" modify_cache
  1399. while [[ "$modify_cache" != "y" && "$modify_cache" != "n" ]]; do
  1400. WARN "无效输入,请输入 ${LIGHT_GREEN}y${RESET} 或 ${LIGHT_YELLOW}n${RESET}"
  1401. read -e -p "$(INFO "是否要修改缓存时间? ${PROMPT_YES_NO}")" modify_cache
  1402. done
  1403. if [[ "$modify_cache" == "y" ]]; then
  1404. while true; do
  1405. read -e -p "$(INFO "请输入新的缓存时间值: ")" new_ttl
  1406. for file_url in "${selected_files[@]}"; do
  1407. yml_name=$(basename "$file_url")
  1408. sed -ri "s/ttl: 168h/ttl: ${new_ttl}/g" ${PROXY_DIR}/${yml_name} &>/dev/null
  1409. done
  1410. break
  1411. done
  1412. fi
  1413. }
  1414. # 一键部署调此函数
  1415. function PROXY_HTTP() {
  1416. read -e -p "$(INFO "是否添加代理? ${PROMPT_YES_NO}")" modify_config
  1417. case $modify_config in
  1418. [Yy]* )
  1419. read -e -p "$(INFO "输入代理地址 ${LIGHT_MAGENTA}(eg: host:port)${RESET}: ")" url
  1420. while [[ -z "$url" ]]; do
  1421. WARN "代理${LIGHT_YELLOW}地址不能为空${RESET},请重新输入!"
  1422. read -e -p "$(INFO "输入代理地址 ${LIGHT_MAGENTA}(eg: host:port)${RESET}: ")" url
  1423. done
  1424. sed -i "s@#- http=http://host:port@- http_proxy=http://${url}@g" ${PROXY_DIR}/${DOCKER_COMPOSE_FILE}
  1425. sed -i "s@#- https=http://host:port@- https_proxy=http://${url}@g" ${PROXY_DIR}/${DOCKER_COMPOSE_FILE}
  1426. INFO "你配置代理地址为: ${CYAN}http://${url}${RESET}"
  1427. ;;
  1428. [Nn]* )
  1429. WARN "跳过添加代理配置"
  1430. ;;
  1431. * )
  1432. ERROR "无效的输入。请重新输入${LIGHT_GREEN}Y or N ${RESET}的选项"
  1433. PROXY_HTTP
  1434. ;;
  1435. esac
  1436. }
  1437. # 7) 本机Docker代理,调此函数
  1438. function DOCKER_PROXY_HTTP() {
  1439. WARN "${BOLD}${LIGHT_GREEN}提示:${RESET} ${LIGHT_CYAN}配置本机Docker服务走代理,加速本机Docker镜像下载${RESET}"
  1440. read -e -p "$(INFO "是否添加本机Docker服务代理? ${PROMPT_YES_NO}")" modify_proxy
  1441. case $modify_proxy in
  1442. [Yy]* )
  1443. read -e -p "$(INFO "输入代理地址 ${LIGHT_MAGENTA}(eg: host:port)${RESET}: ")" url
  1444. while [[ -z "$url" ]]; do
  1445. WARN "代理${LIGHT_YELLOW}地址不能为空${RESET},请重新输入。"
  1446. read -e -p "$(INFO "输入代理地址 ${LIGHT_MAGENTA}(eg: host:port)${RESET}: ")" url
  1447. done
  1448. INFO "你配置代理地址为: ${CYAN}http://${url}${RESET}"
  1449. ;;
  1450. [Nn]* )
  1451. WARN "退出本机Docker服务代理配置"
  1452. exit 1
  1453. ;;
  1454. * )
  1455. ERROR "无效的输入。请重新输入${LIGHT_GREEN}Y or N ${RESET}的选项"
  1456. DOCKER_PROXY_HTTP
  1457. ;;
  1458. esac
  1459. }
  1460. function CHECK_DOCKER_PROXY() {
  1461. local url=$1
  1462. local http_proxy=$(docker info 2>/dev/null | grep -i "HTTP Proxy" | awk -F ': ' '{print $2}')
  1463. local https_proxy=$(docker info 2>/dev/null | grep -i "HTTPS Proxy" | awk -F ': ' '{print $2}')
  1464. if [[ "$http_proxy" == "http://$url" && "$https_proxy" == "http://$url" ]]; then
  1465. INFO "Docker 代理${LIGHT_GREEN}配置成功${RESET},当前 HTTP Proxy: ${LIGHT_CYAN}$http_proxy${RESET}, HTTPS Proxy: ${LIGHT_CYAN}$https_proxy${RESET}"
  1466. else
  1467. ERROR "Docker 代理${LIGHT_RED}配置失败${RESET},请检查配置并重新执行配置"
  1468. DOCKER_PROXY_HTTP
  1469. fi
  1470. }
  1471. function ADD_DOCKERD_PROXY() {
  1472. mkdir -p /etc/systemd/system/docker.service.d
  1473. if [ ! -f /etc/systemd/system/docker.service.d/http-proxy.conf ]; then
  1474. cat > /etc/systemd/system/docker.service.d/http-proxy.conf <<EOF
  1475. [Service]
  1476. Environment="HTTP_PROXY=http://$url"
  1477. Environment="HTTPS_PROXY=http://$url"
  1478. EOF
  1479. systemctl daemon-reload
  1480. systemctl restart docker &>/dev/null
  1481. CHECK_DOCKER
  1482. CHECK_DOCKER_PROXY "$url"
  1483. else
  1484. 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
  1485. cat >> /etc/systemd/system/docker.service.d/http-proxy.conf <<EOF
  1486. [Service]
  1487. Environment="HTTP_PROXY=http://$url"
  1488. Environment="HTTPS_PROXY=http://$url"
  1489. EOF
  1490. systemctl daemon-reload
  1491. systemctl restart docker &>/dev/null
  1492. CHECK_DOCKER
  1493. CHECK_DOCKER_PROXY "$url"
  1494. else
  1495. if [[ "$main_choice" = "7" ]]; then
  1496. WARN "已经存在相同的代理配置,${LIGHT_RED}请勿重复配置${RESET}"
  1497. fi
  1498. fi
  1499. fi
  1500. }
  1501. # 一键部署、安装指定容器加速服务时调用START_CONTAINER
  1502. function START_CONTAINER() {
  1503. CHECK_COMPOSE_CMD
  1504. if [ "$modify_config" = "y" ] || [ "$modify_config" = "Y" ]; then
  1505. ADD_DOCKERD_PROXY
  1506. else
  1507. INFO "拉取服务镜像并启动服务中,请稍等..."
  1508. fi
  1509. # DOWN_CONFIG函数执行后判断selected_all变量
  1510. if [ "$selected_all" = true ]; then
  1511. $DOCKER_COMPOSE_CMD up -d --force-recreate
  1512. # 检查命令执行是否成功
  1513. if [ $? -ne 0 ]; then
  1514. ERROR "Docker 容器${LIGHT_RED}启动失败${RESET},请通过查看日志确认启动失败原因"
  1515. exit 1
  1516. fi
  1517. else
  1518. $DOCKER_COMPOSE_CMD up -d "${selected_names[@]}" registry-ui
  1519. # 检查命令执行是否成功
  1520. if [ $? -ne 0 ]; then
  1521. ERROR "Docker 容器${LIGHT_RED}启动失败${RESET},请通过查看日志确认启动失败原因"
  1522. exit 1
  1523. else
  1524. INFO "容器${LIGHT_GREEN}安装完成${RESET},并${LIGHT_GREEN}成功启动${RESET}"
  1525. fi
  1526. fi
  1527. }
  1528. # 使用函数UPDATE_CONFIG时调用RESTART_CONTAINER
  1529. function RESTART_CONTAINER() {
  1530. CHECK_COMPOSE_CMD
  1531. # DOWN_CONFIG函数执行后判断selected_all变量
  1532. if [ "$selected_all" = true ]; then
  1533. $DOCKER_COMPOSE_CMD restart
  1534. # 检查命令执行是否成功
  1535. if [ $? -ne 0 ]; then
  1536. ERROR "Docker 容器启动失败,请通过查看日志确认启动失败原因"
  1537. exit 1
  1538. fi
  1539. else
  1540. $DOCKER_COMPOSE_CMD restart "${selected_names[@]}"
  1541. # 检查命令执行是否成功
  1542. if [ $? -ne 0 ]; then
  1543. ERROR "Docker 容器启动失败,请通过查看日志确认启动失败原因"
  1544. exit 1
  1545. fi
  1546. fi
  1547. }
  1548. function INSTALL_DOCKER_PROXY() {
  1549. SEPARATOR "部署Docker Proxy"
  1550. CONFIG_FILES
  1551. if [[ "$install_docker_reg" == "1" ]]; then
  1552. wget -NP ${PROXY_DIR}/ ${GITRAW}/${DOCKER_COMPOSE_FILE} &>/dev/null
  1553. elif [[ "$install_docker_reg" == "2" ]]; then
  1554. wget -NP ${PROXY_DIR}/ ${CNGITRAW}/${DOCKER_COMPOSE_FILE} &>/dev/null
  1555. fi
  1556. DOWN_CONFIG
  1557. PROXY_HTTP
  1558. START_CONTAINER
  1559. }
  1560. function STOP_REMOVE_CONTAINER() {
  1561. CHECK_COMPOSE_CMD
  1562. if [[ -f "${PROXY_DIR}/${DOCKER_COMPOSE_FILE}" ]]; then
  1563. INFO "停止和移除所有容器"
  1564. $DOCKER_COMPOSE_CMD -f "${PROXY_DIR}/${DOCKER_COMPOSE_FILE}" down --remove-orphans
  1565. else
  1566. WARN "${LIGHT_YELLOW}容器目前未处于运行状态,无需进行删除操作!${RESET}"
  1567. exit 1
  1568. fi
  1569. }
  1570. function UPDATE_CONFIG() {
  1571. while true; do
  1572. read -e -p "$(WARN "是否更新配置,更新前请确保您已备份现有配置,此操作不可逆? ${PROMPT_YES_NO}")" update_conf
  1573. case "$update_conf" in
  1574. y|Y )
  1575. CONFIG_FILES
  1576. DOWN_CONFIG
  1577. RESTART_CONTAINER
  1578. break;;
  1579. n|N )
  1580. WARN "退出配置更新操作。"
  1581. break;;
  1582. * )
  1583. INFO "请输入 ${LIGHT_GREEN}y${RESET} 或 ${LIGHT_YELLOW}n${RESET}";;
  1584. esac
  1585. done
  1586. }
  1587. function REMOVE_NONE_TAG() {
  1588. docker images | grep "^${IMAGE_NAME}.*<none>" | awk '{print $3}' | xargs -r docker rmi
  1589. images=$(docker images ${IMAGE_NAME} --format '{{.Repository}}:{{.Tag}}')
  1590. latest=$(echo "$images" | sort -V | tail -n1)
  1591. for image in $images
  1592. do
  1593. if [ "$image" != "$latest" ];then
  1594. docker rmi $image
  1595. fi
  1596. done
  1597. }
  1598. function PACKAGE() {
  1599. while true; do
  1600. read -e -p "$(INFO "是否执行软件包安装? (${LIGHT_YELLOW}首次部署需安装依赖${RESET}) ${PROMPT_YES_NO}")" choice_package
  1601. case "$choice_package" in
  1602. y|Y )
  1603. INSTALL_PACKAGE
  1604. break;;
  1605. n|N )
  1606. WARN "跳过软件包安装步骤"
  1607. break;;
  1608. * )
  1609. INFO "请输入 ${LIGHT_GREEN}y${RESET} 或 ${LIGHT_YELLOW}n${RESET}";;
  1610. esac
  1611. done
  1612. }
  1613. function INSTALL_WEB() {
  1614. while true; do
  1615. SEPARATOR "安装WEB服务"
  1616. read -e -p "$(INFO "是否安装WEB服务? (用来通过域名方式访问加速服务) ${PROMPT_YES_NO}")" choice_service
  1617. if [[ "$choice_service" =~ ^[YyNn]$ ]]; then
  1618. if [[ "$choice_service" == "Y" || "$choice_service" == "y" ]]; then
  1619. while true; do
  1620. read -e -p "$(INFO "选择安装的WEB服务。安装${LIGHT_CYAN}Caddy可自动开启HTTPS${RESET} [Nginx/Caddy]: ")" web_service
  1621. if [[ "$web_service" =~ ^(nginx|Nginx|caddy|Caddy)$ ]]; then
  1622. if [[ "$web_service" == "nginx" || "$web_service" == "Nginx" ]]; then
  1623. INSTALL_NGINX
  1624. CONFIG_NGINX
  1625. break
  1626. elif [[ "$web_service" == "caddy" || "$web_service" == "Caddy" ]]; then
  1627. INSTALL_CADDY
  1628. CONFIG_CADDY
  1629. break
  1630. fi
  1631. else
  1632. WARN "请输入 ${LIGHT_CYAN}nginx${RESET} 或 ${LIGHT_BLUE}caddy${RESET}"
  1633. fi
  1634. done
  1635. break
  1636. else
  1637. WARN "跳过WEB服务安装步骤"
  1638. break
  1639. fi
  1640. else
  1641. INFO "请输入 ${LIGHT_GREEN}y${RESET} 或 ${LIGHT_YELLOW}n${RESET}"
  1642. fi
  1643. done
  1644. }
  1645. function PROMPT(){
  1646. PUBLIC_IP=$(curl -s https://ifconfig.me)
  1647. ALL_IPS=$(hostname -I)
  1648. INTERNAL_IP=$(echo "$ALL_IPS" | awk '$1!="127.0.0.1" && $1!="::1" && $1!="docker0" {print $1}')
  1649. echo
  1650. INFO "=================感谢您的耐心等待,安装已经完成=================="
  1651. INFO
  1652. INFO "请用浏览器访问 UI 面板: "
  1653. INFO "公网访问地址: ${UNDERLINE}http://$PUBLIC_IP:50000${RESET}"
  1654. INFO "内网访问地址: ${UNDERLINE}http://$INTERNAL_IP:50000${RESET}"
  1655. INFO
  1656. INFO "服务安装路径: ${LIGHT_BLUE}${PROXY_DIR}${RESET}"
  1657. INFO
  1658. INFO "作者博客: https://dqzboy.com"
  1659. INFO "技术交流: https://t.me/dqzboyblog"
  1660. INFO "代码仓库: https://github.com/dqzboy/Docker-Proxy"
  1661. INFO
  1662. INFO "若用云服务器并设域名及证书,需在安全组开放80、443端口;否则开放对应服务监听端口"
  1663. INFO
  1664. INFO "VPS推荐: https://my.racknerd.com/aff.php?aff=12151"
  1665. INFO
  1666. INFO "================================================================"
  1667. }
  1668. function INSTALL_PROXY() {
  1669. ALL_IN_ONE() {
  1670. CHECK_OS
  1671. CHECK_PACKAGE_MANAGER
  1672. CHECK_PKG_MANAGER
  1673. CHECK_COMPOSE_CMD
  1674. CHECKMEM
  1675. CHECKFIRE
  1676. CHECKBBR
  1677. PACKAGE
  1678. INSTALL_WEB
  1679. while true; do
  1680. SEPARATOR "安装Docker"
  1681. read -e -p "$(INFO "安装环境确认 [${LIGHT_GREEN}国外输1${RESET} ${LIGHT_YELLOW}国内输2${RESET}] > ")" deploy_docker
  1682. case "$deploy_docker" in
  1683. 1 )
  1684. INSTALL_DOCKER
  1685. INSTALL_COMPOSE
  1686. break;;
  1687. 2 )
  1688. INSTALL_DOCKER_CN
  1689. INSTALL_COMPOSE_CN
  1690. break;;
  1691. * )
  1692. INFO "请输入 ${LIGHT_GREEN}1${RESET} 表示国外 或者 ${LIGHT_YELLOW}2${RESET} 表示大陆";;
  1693. esac
  1694. done
  1695. INSTALL_DOCKER_PROXY
  1696. PROMPT
  1697. }
  1698. ADD_DOCKER_SERVICE() {
  1699. WARN "提示: 此操作是在你的服务器${LIGHT_CYAN}已经部署对应组件${RESET}后才可执行,否则执行过程将会出现${LIGHT_RED}各种报错!${RESET}"
  1700. INSTALL_DOCKER_PROXY
  1701. }
  1702. SEPARATOR "安装服务"
  1703. echo -e "1) 一键${BOLD}${LIGHT_GREEN}部署所有${RESET}服务"
  1704. echo -e "2) ${BOLD}${LIGHT_CYAN}安装指定${RESET}容器服务"
  1705. echo -e "3) ${BOLD}返回${LIGHT_RED}主菜单${RESET}"
  1706. echo -e "0) ${BOLD}退出脚本${RESET}"
  1707. echo "---------------------------------------------------------------"
  1708. read -e -p "$(INFO "输入${LIGHT_CYAN}对应数字${RESET}并按${LIGHT_GREEN}Enter${RESET}键 > ")" proxy_install
  1709. case $proxy_install in
  1710. 1)
  1711. ALL_IN_ONE
  1712. ;;
  1713. 2)
  1714. ADD_DOCKER_SERVICE
  1715. INSTALL_PROXY
  1716. ;;
  1717. 3)
  1718. main_menu
  1719. ;;
  1720. 0)
  1721. exit 1
  1722. ;;
  1723. *)
  1724. WARN "输入了无效的选择。请重新${LIGHT_GREEN}选择0-3${RESET}的选项."
  1725. INSTALL_PROXY
  1726. ;;
  1727. esac
  1728. }
  1729. function REMOVE_CMDUI() {
  1730. CHECK_COMPOSE_CMD
  1731. CMDUI_NAME="hubcmd-ui"
  1732. CMDUI_DIR="${PROXY_DIR}/hubcmdui"
  1733. if [ -d "${CMDUI_DIR}" ]; then
  1734. if [ -f "${CMDUI_DIR}/${DOCKER_COMPOSE_FILE}" ]; then
  1735. INFO "停止和移除HubCMD-UI容器"
  1736. $DOCKER_COMPOSE_CMD -f "${CMDUI_DIR}/${DOCKER_COMPOSE_FILE}" down --remove-orphans
  1737. rm -rf "${CMDUI_DIR}"
  1738. else
  1739. WARN "${LIGHT_YELLOW}文件${CMDUI_DIR}/${DOCKER_COMPOSE_FILE} 不存在,无需进行删除操作!${RESET}"
  1740. fi
  1741. else
  1742. WARN "${LIGHT_YELLOW}目录 ${CMDUI_DIR} 不存在,无需进行删除操作!${RESET}"
  1743. fi
  1744. docker images | grep "^${CMDUI_IMAGE_NAME}.*<none>" | awk '{print $3}' | xargs -r docker rmi
  1745. images=$(docker images ${CMDUI_IMAGE_NAME} --format '{{.Repository}}:{{.Tag}}')
  1746. latest=$(echo "$images" | sort -V | tail -n1)
  1747. for image in $images; do
  1748. if [ "$image" != "$latest" ]; then
  1749. docker rmi $image
  1750. fi
  1751. done
  1752. # 强制移除所有相关镜像
  1753. docker rmi --force $(docker images -q ${CMDUI_IMAGE_NAME}) &>/dev/null
  1754. }
  1755. function HUBCMDUI() {
  1756. CHECK_COMPOSE_CMD
  1757. CMDUI_NAME="hubcmd-ui"
  1758. CMDUI_DIR="${PROXY_DIR}/hubcmdui"
  1759. CMDUI_PROMPT() {
  1760. PUBLIC_IP=$(curl -s https://ifconfig.me)
  1761. ALL_IPS=$(hostname -I)
  1762. INTERNAL_IP=$(echo "$ALL_IPS" | awk '$1!="127.0.0.1" && $1!="::1" && $1!="docker0" {print $1}')
  1763. echo
  1764. INFO "=================感谢您的耐心等待,安装已经完成=================="
  1765. INFO
  1766. INFO "请用浏览器访问 HubCMD-UI 面板: "
  1767. INFO "公网访问地址: ${UNDERLINE}http://$PUBLIC_IP:30080${RESET}"
  1768. INFO "内网访问地址: ${UNDERLINE}http://$INTERNAL_IP:30080${RESET}"
  1769. INFO
  1770. INFO "后端访问地址: 地址后面跟admin,例: ${UNDERLINE}http://$INTERNAL_IP:30080/admin${RESET}"
  1771. INFO "默认账号密码: ${LIGHT_GREEN}root${RESET}/${LIGHT_CYAN}admin@123${RESET}"
  1772. INFO
  1773. INFO "服务安装路径: ${LIGHT_BLUE}${CMDUI_DIR}${RESET}"
  1774. INFO
  1775. INFO "作者博客: https://dqzboy.com"
  1776. INFO "技术交流: https://t.me/dqzboyblog"
  1777. INFO "代码仓库: https://github.com/dqzboy/Docker-Proxy"
  1778. INFO
  1779. INFO "VPS推荐: https://my.racknerd.com/aff.php?aff=12151"
  1780. INFO
  1781. INFO "================================================================"
  1782. }
  1783. INSTALL_HUBCMDUI() {
  1784. mkdir -p ${CMDUI_DIR}
  1785. INFO "正在安装HubCMD-UI服务,请稍等!安装路径 ${LIGHT_CYAN}${CMDUI_DIR}${RESET}"
  1786. if [[ -f "${CMDUI_DIR}/${DOCKER_COMPOSE_FILE}" ]]; then
  1787. if $DOCKER_COMPOSE_CMD ps --services 2>/dev/null | grep -q "^${CMDUI_NAME}$"; then
  1788. INFO "${CMDUI_NAME} 已经安装并启动,无需重复执行安装!"
  1789. else
  1790. $DOCKER_COMPOSE_CMD -f "${CMDUI_DIR}/${DOCKER_COMPOSE_FILE}" up -d
  1791. fi
  1792. else
  1793. wget -NP ${CMDUI_DIR}/ ${CMDUI_COMPOSE_FILE} &>/dev/null
  1794. if [ $? -ne 0 ]; then
  1795. WARN "下载${LIGHT_YELLOW}docker-compose.yaml 文件失败${RESET},请稍后重试!"
  1796. HUBCMDUI
  1797. fi
  1798. $DOCKER_COMPOSE_CMD -f "${CMDUI_DIR}/${DOCKER_COMPOSE_FILE}" up -d
  1799. if [ $? -eq 0 ]; then
  1800. CMDUI_PROMPT
  1801. exit 1
  1802. else
  1803. WARN "服务安装失败,请稍后重试!"
  1804. HUBCMDUI
  1805. fi
  1806. fi
  1807. }
  1808. UPDATE_HUBCMDUI() {
  1809. if [ -d "${CMDUI_DIR}" ]; then
  1810. if [ -f "${CMDUI_DIR}/${DOCKER_COMPOSE_FILE}" ]; then
  1811. INFO "正在更新HubCMD-UI容器"
  1812. $DOCKER_COMPOSE_CMD -f "${CMDUI_DIR}/${DOCKER_COMPOSE_FILE}" pull
  1813. if [ $? -ne 0 ]; then
  1814. WARN "HubCMD-UI ${LIGHT_YELLOW}镜像拉取失败${RESET},请稍后重试!"
  1815. HUBCMDUI
  1816. fi
  1817. $DOCKER_COMPOSE_CMD -f "${CMDUI_DIR}/${DOCKER_COMPOSE_FILE}" up -d --force-recreate
  1818. if [ $? -ne 0 ]; then
  1819. WARN "HubCMD-UI ${LIGHT_YELLOW}服务启动失败${RESET},请稍后重试!"
  1820. HUBCMDUI
  1821. else
  1822. INFO "HubCMD-UI ${LIGHT_GREEN}服务更新并启动完成${RESET}"
  1823. fi
  1824. else
  1825. WARN "${LIGHT_YELLOW}文件${CMDUI_DIR}/${DOCKER_COMPOSE_FILE} 不存在,无法进行更新操作!${RESET}"
  1826. fi
  1827. else
  1828. WARN "${LIGHT_YELLOW}目录 ${CMDUI_DIR} 不存在,无法进行更新操作!${RESET}"
  1829. fi
  1830. }
  1831. UNINSTALL_HUBCMDUI() {
  1832. WARN "${LIGHT_RED}注意:${RESET} ${LIGHT_YELLOW}请执行删除之前确定是否需要备份配置文件${RESET}"
  1833. while true; do
  1834. read -e -p "$(INFO "本人${LIGHT_RED}已知晓后果,确认删除${RESET}服务? ${PROMPT_YES_NO}")" delcmdui
  1835. case "$delcmdui" in
  1836. y|Y )
  1837. REMOVE_CMDUI
  1838. break;;
  1839. n|N )
  1840. WARN "退出执行卸载服务"
  1841. break;;
  1842. * )
  1843. INFO "请输入 ${LIGHT_GREEN}y${RESET} 或 ${LIGHT_YELLOW}n${RESET}";;
  1844. esac
  1845. done
  1846. }
  1847. SEPARATOR "HubCMD-UI管理"
  1848. echo -e "1) ${BOLD}${LIGHT_GREEN}安装${RESET}HubCMD-UI"
  1849. echo -e "2) ${BOLD}${LIGHT_YELLOW}卸载${RESET}HubCMD-UI"
  1850. echo -e "3) ${BOLD}${LIGHT_CYAN}更新${RESET}HubCMD-UI"
  1851. echo -e "4) ${BOLD}返回${LIGHT_RED}主菜单${RESET}"
  1852. echo -e "0) ${BOLD}退出脚本${RESET}"
  1853. echo "---------------------------------------------------------------"
  1854. read -e -p "$(INFO "输入${LIGHT_CYAN}对应数字${RESET}并按${LIGHT_GREEN}Enter${RESET}键 > ")" cmdui_choice
  1855. case $cmdui_choice in
  1856. 1)
  1857. INSTALL_HUBCMDUI
  1858. HUBCMDUI
  1859. ;;
  1860. 2)
  1861. UNINSTALL_HUBCMDUI
  1862. HUBCMDUI
  1863. ;;
  1864. 3)
  1865. UPDATE_HUBCMDUI
  1866. HUBCMDUI
  1867. ;;
  1868. 4)
  1869. main_menu
  1870. ;;
  1871. 0)
  1872. exit 1
  1873. ;;
  1874. *)
  1875. WARN "输入了无效的选择。请重新${LIGHT_GREEN}选择0-4${RESET}的选项."
  1876. HUBCMDUI
  1877. ;;
  1878. esac
  1879. }
  1880. function COMP_INST() {
  1881. CHECK_COMPOSE_CMD
  1882. SEPARATOR "安装组件"
  1883. echo -e "1) ${BOLD}安装${LIGHT_GREEN}环境依赖${RESET}"
  1884. echo -e "2) ${BOLD}安装${LIGHT_CYAN}Docker${RESET}"
  1885. echo -e "3) ${BOLD}安装${LIGHT_MAGENTA}Compose${RESET}"
  1886. echo -e "4) ${BOLD}安装${GREEN}Nginx${RESET}"
  1887. echo -e "5) ${BOLD}安装${LIGHT_BLUE}Caddy${RESET}"
  1888. echo -e "6) ${BOLD}配置${LIGHT_YELLOW}Nginx${RESET}"
  1889. echo -e "7) ${BOLD}配置${CYAN}Caddy${RESET}"
  1890. echo -e "8) ${BOLD}安装${BLUE}HubCMD-UI${RESET}"
  1891. echo -e "9) ${BOLD}返回${LIGHT_RED}主菜单${RESET}"
  1892. echo -e "0) ${BOLD}退出脚本${RESET}"
  1893. echo "---------------------------------------------------------------"
  1894. read -e -p "$(INFO "输入${LIGHT_CYAN}对应数字${RESET}并按${LIGHT_GREEN}Enter${RESET}键 > ")" comp_choice
  1895. case $comp_choice in
  1896. 1)
  1897. CHECK_OS
  1898. CHECK_PACKAGE_MANAGER
  1899. CHECK_PKG_MANAGER
  1900. CHECKMEM
  1901. PACKAGE
  1902. COMP_INST
  1903. ;;
  1904. 2)
  1905. CHECK_OS
  1906. CHECK_PACKAGE_MANAGER
  1907. CHECK_PKG_MANAGER
  1908. while true; do
  1909. SEPARATOR "安装Docker"
  1910. read -e -p "$(INFO "安装环境确认 [${LIGHT_GREEN}国外输1${RESET} ${LIGHT_YELLOW}国内输2${RESET}] > ")" deploy_docker
  1911. case "$deploy_docker" in
  1912. 1 )
  1913. INSTALL_DOCKER
  1914. break;;
  1915. 2 )
  1916. INSTALL_DOCKER_CN
  1917. break;;
  1918. * )
  1919. INFO "请输入 ${LIGHT_GREEN}1${RESET} 表示国外 或者 ${LIGHT_YELLOW}2${RESET} 表示大陆";;
  1920. esac
  1921. done
  1922. COMP_INST
  1923. ;;
  1924. 3)
  1925. CHECK_OS
  1926. CHECK_PACKAGE_MANAGER
  1927. CHECK_PKG_MANAGER
  1928. while true; do
  1929. read -e -p "$(INFO "安装环境确认 [${LIGHT_GREEN}国外输1${RESET} ${LIGHT_YELLOW}国内输2${RESET}] > ")" deploy_compose
  1930. case "$deploy_compose" in
  1931. 1 )
  1932. INSTALL_COMPOSE
  1933. break;;
  1934. 2 )
  1935. INSTALL_COMPOSE_CN
  1936. break;;
  1937. * )
  1938. INFO "请输入 ${LIGHT_GREEN}1${RESET} 表示国外 或者 ${LIGHT_YELLOW}2${RESET} 表示大陆";;
  1939. esac
  1940. done
  1941. COMP_INST
  1942. ;;
  1943. 4)
  1944. CHECK_OS
  1945. CHECK_PACKAGE_MANAGER
  1946. CHECK_PKG_MANAGER
  1947. INSTALL_NGINX
  1948. COMP_INST
  1949. ;;
  1950. 5)
  1951. CHECK_OS
  1952. CHECK_PACKAGE_MANAGER
  1953. CHECK_PKG_MANAGER
  1954. INSTALL_CADDY
  1955. COMP_INST
  1956. ;;
  1957. 6)
  1958. CONFIG_NGINX
  1959. COMP_INST
  1960. ;;
  1961. 7)
  1962. CONFIG_CADDY
  1963. COMP_INST
  1964. ;;
  1965. 8)
  1966. HUBCMDUI
  1967. COMP_INST
  1968. ;;
  1969. 9)
  1970. main_menu
  1971. ;;
  1972. 0)
  1973. exit 1
  1974. ;;
  1975. *)
  1976. WARN "输入了无效的选择。请重新${LIGHT_GREEN}选择0-8${RESET}的选项."
  1977. COMP_INST
  1978. ;;
  1979. esac
  1980. }
  1981. function SVC_MGMT() {
  1982. CHECK_COMPOSE_CMD
  1983. RESTART_SERVICE() {
  1984. CONTAINER_SERVICES
  1985. selected_services=()
  1986. WARN "重启服务请在${LIGHT_GREEN}${DOCKER_COMPOSE_FILE}${RESET}文件存储目录下执行脚本.默认安装路径: ${LIGHT_BLUE}${PROXY_DIR}${RESET}"
  1987. REGISTRY_MENU
  1988. read -e -p "$(INFO "输入序号选择对应服务,${LIGHT_YELLOW}空格分隔${RESET}多个选项. ${LIGHT_CYAN}all表示所有${RESET} > ")" restart_service
  1989. while true; do
  1990. if [[ "$restart_service" =~ ^[0-9]+([[:space:]][0-9]+)*$ ]]; then
  1991. valid=true
  1992. for choice in $restart_service; do
  1993. if ((choice < 0 || choice > 10)); then
  1994. valid=false
  1995. break
  1996. fi
  1997. done
  1998. if $valid; then
  1999. break
  2000. fi
  2001. fi
  2002. WARN "无效输入,请重新输入${LIGHT_YELLOW} 0-10 ${RESET}序号"
  2003. read -e -p "$(INFO "输入序号选择对应服务,${LIGHT_YELLOW}空格分隔${RESET}多个选项. ${LIGHT_CYAN}all表示所有${RESET} > ")" restart_service
  2004. done
  2005. if [[ "$restart_service" == "10" ]]; then
  2006. for service_name in "${services[@]}"; do
  2007. if $DOCKER_COMPOSE_CMD ps --services 2>/dev/null | grep -q "^${service_name}$"; then
  2008. selected_services+=("$service_name")
  2009. else
  2010. WARN "服务 ${service_name}未运行,跳过重启。"
  2011. fi
  2012. done
  2013. if [ ${#selected_services[@]} -eq 0 ]; then
  2014. WARN "选择的服务未运行,无需进行重启"
  2015. else
  2016. INFO "更新的服务: ${selected_services[*]}"
  2017. fi
  2018. elif [[ "$restart_service" == "0" ]]; then
  2019. WARN "退出重启服务!"
  2020. return
  2021. else
  2022. for choice in ${restart_service}; do
  2023. if ((choice > 0 && choice < 10)); then
  2024. service_name="${services[$((choice -1))]}"
  2025. if $DOCKER_COMPOSE_CMD ps --services 2>/dev/null | grep -q "^${service_name}$"; then
  2026. selected_services+=("$service_name")
  2027. else
  2028. WARN "服务 ${service_name} 未运行,跳过重启。"
  2029. fi
  2030. else
  2031. ERROR "无效的选择: $choice. 请重新${LIGHT_GREEN}选择0-9${RESET}的选项"
  2032. RESTART_SERVICE # 选择无效重新调用当前函数进行选择
  2033. fi
  2034. done
  2035. if [ ${#selected_services[@]} -eq 0 ]; then
  2036. WARN "选择的服务未运行,无需进行重启"
  2037. else
  2038. INFO "更新的服务: ${selected_services[*]}"
  2039. fi
  2040. fi
  2041. }
  2042. UPDATE_SERVICE() {
  2043. CONTAINER_SERVICES
  2044. selected_services=()
  2045. WARN "更新服务请在${LIGHT_GREEN}${DOCKER_COMPOSE_FILE}${RESET}文件存储目录下执行脚本.默认安装路径: ${LIGHT_BLUE}${PROXY_DIR}${RESET}"
  2046. REGISTRY_MENU
  2047. read -e -p "$(INFO "输入序号选择对应服务,${LIGHT_YELLOW}空格分隔${RESET}多个选项. ${LIGHT_CYAN}all表示所有${RESET} > ")" update_service
  2048. while true; do
  2049. if [[ "$update_service" =~ ^[0-9]+([[:space:]][0-9]+)*$ ]]; then
  2050. valid=true
  2051. for choice in $update_service; do
  2052. if ((choice < 0 || choice > 10)); then
  2053. valid=false
  2054. break
  2055. fi
  2056. done
  2057. if $valid; then
  2058. break
  2059. fi
  2060. fi
  2061. WARN "无效输入,请重新输入${LIGHT_YELLOW} 0-10 ${RESET}序号"
  2062. read -e -p "$(INFO "输入序号选择对应服务,${LIGHT_YELLOW}空格分隔${RESET}多个选项. ${LIGHT_CYAN}all表示所有${RESET} > ")" update_service
  2063. done
  2064. if [[ "$update_service" == "10" ]]; then
  2065. for service_name in "${services[@]}"; do
  2066. if $DOCKER_COMPOSE_CMD ps --services 2>/dev/null | grep -q "^${service_name}$"; then
  2067. selected_services+=("$service_name")
  2068. else
  2069. WARN "服务 ${service_name}未运行,跳过更新。"
  2070. fi
  2071. done
  2072. if [ ${#selected_services[@]} -eq 0 ]; then
  2073. WARN "选择的服务未运行,无法进行更新"
  2074. else
  2075. INFO "更新的服务: ${selected_services[*]}"
  2076. fi
  2077. elif [[ "$update_service" == "0" ]]; then
  2078. WARN "退出更新服务!"
  2079. return
  2080. else
  2081. for choice in ${update_service}; do
  2082. if ((choice > 0 && choice < 10)); then
  2083. service_name="${services[$((choice -1))]}"
  2084. if $DOCKER_COMPOSE_CMD ps --services 2>/dev/null | grep -q "^${service_name}$"; then
  2085. selected_services+=("$service_name")
  2086. else
  2087. WARN "服务 ${service_name} 未运行,跳过更新。"
  2088. fi
  2089. else
  2090. ERROR "无效的选择: $choice. 请重新${LIGHT_GREEN}选择0-9${RESET}的选项"
  2091. UPDATE_SERVICE # 选择无效重新调用当前函数进行选择
  2092. fi
  2093. done
  2094. if [ ${#selected_services[@]} -eq 0 ]; then
  2095. WARN "选择的服务未运行,无法进行更新"
  2096. else
  2097. INFO "更新的服务: ${selected_services[*]}"
  2098. fi
  2099. fi
  2100. }
  2101. CONTAIENR_LOGS() {
  2102. CONTAINER_SERVICES
  2103. selected_services=()
  2104. REGISTRY_SER_MENU
  2105. read -e -p "$(INFO "输入序号选择对应服务,${LIGHT_YELLOW}空格分隔${RESET}多个选项. ${LIGHT_CYAN}all选择所有${RESET} > ")" restart_service
  2106. if [[ "$restart_service" == "0" ]]; then
  2107. WARN "退出查看容器服务日志操作!"
  2108. return
  2109. else
  2110. for choice in ${restart_service}; do
  2111. if [[ $choice =~ ^[0-9]+$ ]] && ((choice >0 && choice <= ${#services[@]})); then
  2112. service_name="${services[$((choice -1))]}"
  2113. if $DOCKER_COMPOSE_CMD ps --services 2>/dev/null | grep -q "^${service_name}$"; then
  2114. selected_services+=("$service_name")
  2115. else
  2116. WARN "服务 ${service_name} 未运行,无法查看容器日志。"
  2117. fi
  2118. else
  2119. ERROR "无效的选择: $choice. 请重新${LIGHT_GREEN}选择0-9${RESET}的选项"
  2120. CONTAIENR_LOGS # 选择无效重新调用当前函数进行选择
  2121. fi
  2122. done
  2123. if [ ${#selected_services[@]} -eq 0 ]; then
  2124. WARN "选择的服务未运行,无法查看日志"
  2125. else
  2126. INFO "查看日志的服务: ${selected_services[*]}"
  2127. fi
  2128. fi
  2129. }
  2130. MODIFY_SERVICE_TTL_CONFIG() {
  2131. selected_services=()
  2132. selected_files=()
  2133. existing_files=()
  2134. non_existing_files=()
  2135. REGISTRY_FILES
  2136. while true; do
  2137. REGISTRY_SER_MENU
  2138. read -e -p "$(INFO "输入序号修改服务对应配置文件,${LIGHT_YELLOW}空格分隔${RESET}多个选项 > ")" ttl_service
  2139. if [[ "$ttl_service" == "0" ]]; then
  2140. WARN "退出修改容器服务配置操作!"
  2141. return
  2142. elif [[ "$ttl_service" =~ ^([1-8]+[[:space:]]*)+$ ]]; then
  2143. break
  2144. else
  2145. WARN "无效输入,请重新输入${LIGHT_YELLOW} 0-9 ${RESET}序号"
  2146. fi
  2147. done
  2148. for choice in ${ttl_service}; do
  2149. file_name=$(echo "${files[$((choice - 1))]}" | cut -d' ' -f2)
  2150. service_name=$(echo "${files[$((choice - 1))]}" | cut -d' ' -f1)
  2151. selected_files+=("$file_name")
  2152. if [ -f "${PROXY_DIR}/${file_name}" ]; then
  2153. existing_files+=("$file_name")
  2154. selected_services+=("$service_name")
  2155. else
  2156. non_existing_files+=("$file_name")
  2157. fi
  2158. if ! $DOCKER_COMPOSE_CMD ps --services 2>/dev/null | grep -q "^${service_name}$"; then
  2159. WARN "服务 ${service_name} 未运行。"
  2160. fi
  2161. done
  2162. if [ ${#existing_files[@]} -gt 0 ]; then
  2163. INFO "${GREEN}存在的配置文件:${RESET} ${existing_files[*]}${RESET}"
  2164. fi
  2165. if [ ${#non_existing_files[@]} -gt 0 ]; then
  2166. WARN "${RED}不存在的配置文件:${RESET} ${non_existing_files[*]}"
  2167. fi
  2168. if [ ${#existing_files[@]} -gt 0 ]; then
  2169. WARN "${LIGHT_GREEN}>>> 提示:${RESET} ${LIGHT_BLUE}Proxy代理缓存过期时间${RESET} ${MAGENTA}单位:ns、us、ms、s、m、h.默认ns,0禁用缓存过期${RESET}"
  2170. read -e -p "$(INFO "是否要修改缓存时间? ${PROMPT_YES_NO}")" modify_cache
  2171. while [[ "$modify_cache" != "y" && "$modify_cache" != "n" ]]; do
  2172. WARN "无效输入,请输入 ${LIGHT_GREEN}y${RESET} 或 ${LIGHT_YELLOW}n${RESET}"
  2173. read -e -p "$(INFO "是否要修改缓存时间? ${PROMPT_YES_NO}")" modify_cache
  2174. done
  2175. if [[ "$modify_cache" == "y" ]]; then
  2176. while true; do
  2177. read -e -p "$(INFO "请输入新的缓存时间值: ")" new_ttl
  2178. for file_url in "${existing_files[@]}"; do
  2179. yml_name=$(basename "$file_url")
  2180. WARN "${YELLOW}正在修改配置文件: ${PROXY_DIR}/${yml_name}${RESET}"
  2181. sed -i "s/ttl: .*/ttl: ${new_ttl}/g" "${PROXY_DIR}/${yml_name}" &>/dev/null
  2182. INFO "${GREEN}配置文件 ${yml_name} 修改完成,代理缓存过期时间已设置为: ${new_ttl}${RESET}"
  2183. done
  2184. break
  2185. done
  2186. fi
  2187. else
  2188. WARN "未选择有效的配置文件进行修改。"
  2189. fi
  2190. }
  2191. ### 启动新容器
  2192. START_NEW_SERVER_DOWN_CONFIG() {
  2193. selected_names=()
  2194. selected_files=()
  2195. selected_containers=()
  2196. REGISTRY_SER_MENU
  2197. read -e -p "$(INFO "输入序号下载对应配置文件,${LIGHT_YELLOW}空格分隔${RESET}多个选项 > ")" choices_newser
  2198. while [[ ! "$choices_newser" =~ ^([0-9]+[[:space:]]*)+$ ]]; do
  2199. WARN "无效输入,请重新输入${LIGHT_YELLOW} 0-9 ${RESET}序号"
  2200. read -e -p "$(INFO "输入序号下载对应配置文件,${LIGHT_YELLOW}空格分隔${RESET}多个选项 > ")" choices_newser
  2201. done
  2202. if [[ "$choices_newser" == "0" ]]; then
  2203. WARN "退出下载配置! ${LIGHT_YELLOW}没有配置将无法启动服务!!!${RESET}"
  2204. return
  2205. else
  2206. for choice in ${choices_newser}; do
  2207. if [[ $choice =~ ^[0-9]+$ ]] && ((choice > 0 && choice <= ${#files[@]})); then
  2208. file_name=$(echo "${files[$((choice - 1))]}" | cut -d' ' -f1)
  2209. container_name=$(echo "${files[$((choice - 1))]}" | cut -d' ' -f2)
  2210. file_url=$(echo "${files[$((choice - 1))]}" | cut -d' ' -f3-)
  2211. selected_names+=("$file_name")
  2212. selected_containers+=("$container_name")
  2213. selected_files+=("$file_url")
  2214. wget -NP ${PROXY_DIR}/ $file_url &>/dev/null
  2215. else
  2216. WARN "无效输入,请重新输入${LIGHT_YELLOW} 0-9 ${RESET}序号"
  2217. fi
  2218. done
  2219. fi
  2220. WARN "${LIGHT_GREEN}>>> 提示:${RESET} ${LIGHT_BLUE}Proxy代理缓存过期时间${RESET} ${MAGENTA}单位:ns、us、ms、s、m、h.默认ns,0禁用缓存过期${RESET}"
  2221. read -e -p "$(INFO "是否要修改缓存时间? ${PROMPT_YES_NO}")" modify_cache
  2222. while [[ "$modify_cache" != "y" && "$modify_cache" != "n" ]]; do
  2223. WARN "无效输入,请输入 ${LIGHT_GREEN}y${RESET} 或 ${LIGHT_YELLOW}n${RESET}"
  2224. read -e -p "$(INFO "是否要修改缓存时间? ${PROMPT_YES_NO}")" modify_cache
  2225. done
  2226. if [[ "$modify_cache" == "y" ]]; then
  2227. while true; do
  2228. read -e -p "$(INFO "请输入新的缓存时间值: ")" new_ttl
  2229. for file_url in "${selected_files[@]}"; do
  2230. yml_name=$(basename "$file_url")
  2231. sed -ri "s/ttl: 168h/ttl: ${new_ttl}/g" ${PROXY_DIR}/${yml_name} &>/dev/null
  2232. done
  2233. break
  2234. done
  2235. fi
  2236. }
  2237. START_NEW_DOCKER_SERVICE() {
  2238. if [ -d "${PROXY_DIR}" ]; then
  2239. if [ -f "${PROXY_DIR}/${DOCKER_COMPOSE_FILE}" ]; then
  2240. CONFIG_FILES
  2241. START_NEW_SERVER_DOWN_CONFIG
  2242. PROXY_HTTP
  2243. INFO "正在启动新的容器服务,请稍等..."
  2244. $DOCKER_COMPOSE_CMD -f "${PROXY_DIR}/${DOCKER_COMPOSE_FILE}" up -d "${selected_names[@]}"
  2245. if [ $? -ne 0 ]; then
  2246. WARN "${selected_names[*]} ${LIGHT_YELLOW}服务启动失败${RESET},请排查!"
  2247. else
  2248. INFO "${selected_names[*]} ${LIGHT_GREEN}服务启动完成${RESET}"
  2249. fi
  2250. else
  2251. WARN "${LIGHT_YELLOW}文件${PROXY_DIR}/${DOCKER_COMPOSE_FILE} 不存在,无法启动新的容器!${RESET}"
  2252. fi
  2253. else
  2254. WARN "${LIGHT_YELLOW}目录 ${PROXY_DIR} 不存在,无法启动新的容器!${RESET}"
  2255. fi
  2256. }
  2257. ### 启动新容器 END
  2258. SEPARATOR "服务管理"
  2259. echo -e "1) ${BOLD}${LIGHT_GREEN}重启${RESET}服务"
  2260. echo -e "2) ${BOLD}${LIGHT_CYAN}更新${RESET}服务"
  2261. echo -e "3) ${BOLD}${LIGHT_MAGENTA}查看${RESET}日志"
  2262. echo -e "4) ${BOLD}${LIGHT_BLUE}缓存${RESET}时效"
  2263. echo -e "5) ${BOLD}启动${CYAN}新服务${RESET}"
  2264. echo -e "6) ${BOLD}返回${LIGHT_RED}主菜单${RESET}"
  2265. echo -e "0) ${BOLD}退出脚本${RESET}"
  2266. echo "---------------------------------------------------------------"
  2267. read -e -p "$(INFO "输入${LIGHT_CYAN}对应数字${RESET}并按${LIGHT_GREEN}Enter${RESET}键 > ")" ser_choice
  2268. case $ser_choice in
  2269. 1)
  2270. RESTART_SERVICE
  2271. if [ ${#selected_services[@]} -eq 0 ]; then
  2272. ERROR "没有需要重启的服务,请重新选择"
  2273. RESTART_SERVICE
  2274. else
  2275. $DOCKER_COMPOSE_CMD stop ${selected_services[*]}
  2276. $DOCKER_COMPOSE_CMD up -d --force-recreate ${selected_services[*]}
  2277. fi
  2278. SVC_MGMT
  2279. ;;
  2280. 2)
  2281. UPDATE_SERVICE
  2282. if [ ${#selected_services[@]} -eq 0 ]; then
  2283. ERROR "没有需要更新的服务,请重新选择"
  2284. UPDATE_SERVICE
  2285. else
  2286. $DOCKER_COMPOSE_CMD pull ${selected_services[*]}
  2287. $DOCKER_COMPOSE_CMD up -d --force-recreate ${selected_services[*]}
  2288. fi
  2289. SVC_MGMT
  2290. ;;
  2291. 3)
  2292. CONTAIENR_LOGS
  2293. if [ ${#selected_services[@]} -eq 0 ]; then
  2294. ERROR "没有需要查看的服务,请重新选择"
  2295. CONTAIENR_LOGS
  2296. else
  2297. # 查看最近30条日志
  2298. $DOCKER_COMPOSE_CMD logs --tail=30 ${selected_services[*]}
  2299. fi
  2300. SVC_MGMT
  2301. ;;
  2302. 4)
  2303. MODIFY_SERVICE_TTL_CONFIG
  2304. if [ ${#selected_services[@]} -eq 0 ]; then
  2305. ERROR "修改的服务未运行,请重新选择"
  2306. MODIFY_SERVICE_TTL_CONFIG
  2307. else
  2308. $DOCKER_COMPOSE_CMD restart ${selected_services[*]}
  2309. fi
  2310. SVC_MGMT
  2311. ;;
  2312. 5)
  2313. START_NEW_DOCKER_SERVICE
  2314. SVC_MGMT
  2315. ;;
  2316. 6)
  2317. main_menu
  2318. ;;
  2319. 0)
  2320. exit 1
  2321. ;;
  2322. *)
  2323. WARN "输入了无效的选择。请重新${LIGHT_GREEN}选择0-5${RESET}的选项."
  2324. SVC_MGMT
  2325. ;;
  2326. esac
  2327. }
  2328. function ADD_SYS_CMD() {
  2329. MAX_ATTEMPTS=3
  2330. attempt=0
  2331. success=false
  2332. TARGET_PATH="/usr/bin/hub"
  2333. INSTALL_ENV() {
  2334. while true; do
  2335. read -e -p "$(INFO "安装环境确认 [${LIGHT_GREEN}国外输1${RESET} ${LIGHT_YELLOW}国内输2${RESET}] > ")" sys_cmd
  2336. case "$sys_cmd" in
  2337. 1 )
  2338. DOWNLOAD_URL="https://raw.githubusercontent.com/dqzboy/Docker-Proxy/main/install/DockerProxy_Install.sh"
  2339. break;;
  2340. 2 )
  2341. DOWNLOAD_URL="https://cdn.jsdelivr.net/gh/dqzboy/Docker-Proxy/install/DockerProxy_Install.sh"
  2342. break;;
  2343. * )
  2344. INFO "请输入 ${LIGHT_GREEN}1${RESET} 表示国外 或者 ${LIGHT_YELLOW}2${RESET} 表示大陆";;
  2345. esac
  2346. done
  2347. }
  2348. INSTALL_OR_UPDATE_CMD() {
  2349. local action=$1
  2350. while [[ $attempt -lt $MAX_ATTEMPTS ]]; do
  2351. attempt=$((attempt + 1))
  2352. if [[ "$action" == "安装" ]]; then
  2353. if command -v hub &> /dev/null; then
  2354. INFO "系统命令已存在,无需安装。"
  2355. success=true
  2356. break
  2357. fi
  2358. WARN "正在安装脚本中,请稍等..."
  2359. else
  2360. WARN "正在进行脚本更新,请稍等..."
  2361. if [ -f "$TARGET_PATH" ]; then
  2362. rm -f "$TARGET_PATH" &>/dev/null
  2363. fi
  2364. fi
  2365. wget -q -O "$TARGET_PATH" "$DOWNLOAD_URL" &>/dev/null
  2366. if [ $? -eq 0 ]; then
  2367. success=true
  2368. chmod +x "$TARGET_PATH"
  2369. break
  2370. fi
  2371. ERROR "${action}脚本${RED}失败${RESET},正在尝试重新${action} (尝试次数: $attempt)"
  2372. done
  2373. if $success; then
  2374. INFO "${action}脚本${GREEN}成功${RESET},命令行输入 ${LIGHT_GREEN}hub${RESET} 运行"
  2375. else
  2376. ERROR "设置系统命令失败"
  2377. exit 1
  2378. fi
  2379. }
  2380. SEPARATOR "设置脚本为系统命令"
  2381. echo -e "1) ${BOLD}安装${LIGHT_GREEN}系统命令${RESET}"
  2382. echo -e "2) ${BOLD}更新${LIGHT_CYAN}系统命令${RESET}"
  2383. echo -e "3) ${BOLD}返回${LIGHT_RED}主菜单${RESET}"
  2384. echo -e "0) ${BOLD}退出脚本${RESET}"
  2385. echo "---------------------------------------------------------------"
  2386. read -e -p "$(INFO "输入${LIGHT_CYAN}对应数字${RESET}并按${LIGHT_GREEN}Enter${RESET}键 > ")" cmd_choice
  2387. case $cmd_choice in
  2388. 1)
  2389. INSTALL_ENV
  2390. INSTALL_OR_UPDATE_CMD "安装"
  2391. ;;
  2392. 2)
  2393. INSTALL_ENV
  2394. INSTALL_OR_UPDATE_CMD "更新"
  2395. ;;
  2396. 3)
  2397. main_menu
  2398. ;;
  2399. 0)
  2400. exit 1
  2401. ;;
  2402. *)
  2403. WARN "输入了无效的选择。请重新${LIGHT_GREEN}选择0-3${RESET}的选项."
  2404. ADD_SYS_CMD
  2405. ;;
  2406. esac
  2407. }
  2408. function UNI_DOCKER_SERVICE() {
  2409. CHECK_COMPOSE_CMD
  2410. RM_SERVICE() {
  2411. selected_containers=()
  2412. REGISTRY_FILES
  2413. REGISTRY_SER_MENU
  2414. read -e -p "$(INFO "输入序号删除服务和对应配置文件,${LIGHT_YELLOW}空格分隔${RESET}多个选项 > ")" rm_service
  2415. while [[ ! "$rm_service" =~ ^([0-9]+[[:space:]]*)+$ ]]; do
  2416. WARN "无效输入,请重新输入${LIGHT_YELLOW} 0-9 ${RESET}序号"
  2417. read -e -p "$(INFO "输入序号删除服务和对应配置文件,${LIGHT_YELLOW}空格分隔${RESET}多个选项 > ")" rm_service
  2418. done
  2419. if [[ "$rm_service" == "0" ]]; then
  2420. WARN "退出删除容器服务操作!"
  2421. return
  2422. else
  2423. selected_services=()
  2424. for choice in ${rm_service}; do
  2425. if [[ $choice =~ ^[0-9]+$ ]] && ((choice > 0 && choice <= ${#files[@]})); then
  2426. file_name=$(echo "${files[$((choice - 1))]}" | cut -d' ' -f2)
  2427. service_name=$(echo "${files[$((choice - 1))]}" | cut -d' ' -f1)
  2428. if $DOCKER_COMPOSE_CMD ps --services 2>/dev/null | grep -q "^${service_name}$"; then
  2429. selected_services+=("$service_name")
  2430. else
  2431. WARN "服务 ${LIGHT_MAGENTA}${service_name} 未运行${RESET},但将尝试删除相关文件。"
  2432. fi
  2433. if [ -f "${PROXY_DIR}/${file_name}" ]; then
  2434. rm -f "${PROXY_DIR}/${file_name}"
  2435. INFO "配置文件 ${LIGHT_CYAN}${file_name}${RESET} ${LIGHT_GREEN}已被删除${RESET}"
  2436. else
  2437. WARN "配置文件 ${LIGHT_CYAN}${file_name}${RESET} 不存在,${LIGHT_YELLOW}无需删除${RESET}"
  2438. fi
  2439. else
  2440. WARN "无效输入,请重新输入${LIGHT_YELLOW} 0-9 ${RESET}序号"
  2441. UNI_DOCKER_SERVICE
  2442. return
  2443. fi
  2444. done
  2445. # 一次性删除所有选中的服务
  2446. if [ ${#selected_services[@]} -gt 0 ]; then
  2447. INFO "删除的服务: ${LIGHT_RED}${selected_services[*]}${RESET}"
  2448. $DOCKER_COMPOSE_CMD down ${selected_services[*]}
  2449. fi
  2450. fi
  2451. }
  2452. RM_ALLSERVICE() {
  2453. STOP_REMOVE_CONTAINER
  2454. REMOVE_NONE_TAG
  2455. REMOVE_CMDUI
  2456. docker rmi --force $(docker images -q ${IMAGE_NAME}) &>/dev/null
  2457. docker rmi --force $(docker images -q ${UI_IMAGE_NAME}) &>/dev/null
  2458. if [ -d "${PROXY_DIR}" ]; then
  2459. rm -rf "${PROXY_DIR}" &>/dev/null
  2460. fi
  2461. if [ -f "/usr/bin/hub" ]; then
  2462. rm -f /usr/bin/hub &>/dev/null
  2463. fi
  2464. INFO "${LIGHT_YELLOW}感谢您的使用,Docker-Proxy服务已卸载。欢迎您再次使用!${RESET}"
  2465. SEPARATOR "DONE"
  2466. }
  2467. CONFIREM_ACTION() {
  2468. local action_name=$1
  2469. local action_function=$2
  2470. WARN "${LIGHT_RED}注意:${RESET} ${LIGHT_YELLOW}卸载服务会一同将本地的配置和对应服务删除,请执行删除之前确定是否需要备份本地的配置文件${RESET}"
  2471. while true; do
  2472. read -e -p "$(INFO "本人${LIGHT_RED}已知晓后果,确认${action_name}${RESET}服务? ${PROMPT_YES_NO}")" uniservice
  2473. case "$uniservice" in
  2474. y|Y )
  2475. $action_function
  2476. break;;
  2477. n|N )
  2478. WARN "退出${action_name}服务."
  2479. break;;
  2480. * )
  2481. INFO "请输入 ${LIGHT_GREEN}y${RESET} 或 ${LIGHT_YELLOW}n${RESET}";;
  2482. esac
  2483. done
  2484. }
  2485. SEPARATOR "卸载服务"
  2486. echo -e "1) ${BOLD}卸载${LIGHT_YELLOW}所有服务${RESET}"
  2487. echo -e "2) ${BOLD}删除${LIGHT_CYAN}指定服务${RESET}"
  2488. echo -e "3) ${BOLD}返回${LIGHT_RED}主菜单${RESET}"
  2489. echo -e "0) ${BOLD}退出脚本${RESET}"
  2490. echo "---------------------------------------------------------------"
  2491. read -e -p "$(INFO "输入${LIGHT_CYAN}对应数字${RESET}并按${LIGHT_GREEN}Enter${RESET}键 > ")" rm_choice
  2492. case $rm_choice in
  2493. 1)
  2494. CONFIREM_ACTION "卸载所有" RM_ALLSERVICE
  2495. ;;
  2496. 2)
  2497. CONFIREM_ACTION "删除指定" RM_SERVICE
  2498. UNI_DOCKER_SERVICE
  2499. ;;
  2500. 3)
  2501. main_menu
  2502. ;;
  2503. 0)
  2504. exit 1
  2505. ;;
  2506. *)
  2507. WARN "输入了无效的选择。请重新${LIGHT_GREEN}选择0-3${RESET}的选项."
  2508. UNI_DOCKER_SERVICE
  2509. ;;
  2510. esac
  2511. }
  2512. function AUTH_SERVICE_CONFIG() {
  2513. CHECK_COMPOSE_CMD
  2514. CHECK_REG_AUTH() {
  2515. if ! command -v docker &> /dev/null; then
  2516. ERROR "docker 命令未找到,请确保 Docker 已正确安装"
  2517. AUTH_SERVICE_CONFIG
  2518. fi
  2519. # 重置数组
  2520. running_containers=()
  2521. stopped_containers=()
  2522. auth_containers=()
  2523. non_auth_containers=()
  2524. declare -A services
  2525. services=(
  2526. ["reg-docker-hub"]="dockerhub"
  2527. ["reg-gcr"]="gcr"
  2528. ["reg-ghcr"]="ghcr"
  2529. ["reg-quay"]="quay"
  2530. ["reg-k8s-gcr"]="k8sgcr"
  2531. ["reg-k8s"]="k8s"
  2532. ["reg-mcr"]="mcr"
  2533. ["reg-elastic"]="elastic"
  2534. ["reg-nvcr"]="nvcr"
  2535. )
  2536. container_names=$(docker ps --filter "name=reg-" --filter "status=running" --format "{{.Names}}")
  2537. # 检查哪些容器正在运行
  2538. for container_name in "${!services[@]}"; do
  2539. if docker ps --filter "name=$container_name" --filter "status=running" --format "{{.Names}}" | grep -q "$container_name"; then
  2540. running_containers+=("${services[$container_name]}")
  2541. else
  2542. stopped_containers+=("${services[$container_name]}")
  2543. fi
  2544. done
  2545. if [ ${#running_containers[@]} -gt 0 ]; then
  2546. INFO "当前运行的 Docker 容器有: ${LIGHT_CYAN}${running_containers[*]}${RESET}"
  2547. else
  2548. WARN "当前没有运行的 Docker 容器"
  2549. AUTH_SERVICE_CONFIG # 如果没有运行的容器,直接返回
  2550. fi
  2551. auth_containers=()
  2552. non_auth_containers=()
  2553. for container_name in $container_names; do
  2554. specified_name=${services[$container_name]}
  2555. if [ -z "$specified_name" ]; then
  2556. specified_name=$container_name
  2557. fi
  2558. if docker exec $container_name grep -q "auth" /etc/distribution/config.yml; then
  2559. auth_containers+=("$specified_name")
  2560. else
  2561. non_auth_containers+=("$specified_name")
  2562. fi
  2563. done
  2564. if [ ${#auth_containers[@]} -gt 0 ]; then
  2565. INFO "当前运行的 Docker 容器中${LIGHT_GREEN}包含认证${RESET}的容器有: ${LIGHT_CYAN}${auth_containers[*]}${RESET}"
  2566. else
  2567. WARN "当前运行的 Docker 容器中${LIGHT_YELLOW}没有包含认证${RESET}的容器"
  2568. fi
  2569. if [ ${#non_auth_containers[@]} -gt 0 ]; then
  2570. WARN "当前运行的 Docker 容器中${LIGHT_YELLOW}没有包含认证${RESET}的容器有: ${LIGHT_BLUE}${non_auth_containers[*]}${RESET}"
  2571. else
  2572. INFO "当前运行的 Docker 容器中${LIGHT_GREEN}所有容器都包含认证${RESET}"
  2573. fi
  2574. }
  2575. AUTH_MENU() {
  2576. CHECK_REG_AUTH
  2577. selected_files=()
  2578. selected_services=()
  2579. REGISTRY_FILES
  2580. REGISTRY_SER_MENU
  2581. read -e -p "$(INFO "输入序号选择添加认证的服务,${LIGHT_YELLOW}空格分隔${RESET}多个选项 > ")" auth_service
  2582. while [[ ! "$auth_service" =~ ^([0-9]+[[:space:]]*)+$ ]]; do
  2583. WARN "无效输入,请重新输入${LIGHT_YELLOW} 0-9 ${RESET}序号"
  2584. read -e -p "$(INFO "输入序号选择添加认证的服务,${LIGHT_YELLOW}空格分隔${RESET}多个选项 > ")" auth_service
  2585. done
  2586. }
  2587. ADD_AUTH_CONFIG() {
  2588. local FILE=$1
  2589. local auth_config="
  2590. auth:
  2591. htpasswd:
  2592. realm: basic-realm
  2593. path: /auth/htpasswd"
  2594. if [ ! -f "$FILE" ]; then
  2595. ERROR "配置文件 ${LIGHT_BLUE}$FILE${RESET} 不存在"
  2596. exit 1
  2597. else
  2598. if ! grep -q "auth:" "$FILE" || ! grep -q "htpasswd:" "$FILE" || ! grep -q "realm: basic-realm" "$FILE" || ! grep -q "path: /auth/htpasswd" "$FILE"; then
  2599. echo -e "$auth_config" | sudo tee -a "$FILE" > /dev/null
  2600. INFO "配置文件 ${LIGHT_BLUE}$FILE${RESET} 添加认证配置成功"
  2601. else
  2602. WARN "配置文件 ${LIGHT_BLUE}$FILE${RESET} 已添加认证配置"
  2603. fi
  2604. fi
  2605. }
  2606. ADD_AUTH_COMPOSE() {
  2607. local SERVICES=$1
  2608. local FILE=${DOCKER_COMPOSE_FILE}
  2609. local HTPASSWD_CONFIG=" - ./${SERVICES}_htpasswd:/auth/htpasswd"
  2610. if [ ! -f "$FILE" ]; then
  2611. ERROR "配置文件 ${LIGHT_BLUE}$FILE${RESET} 不存在"
  2612. exit 1
  2613. fi
  2614. for SERVICE in "${SERVICES[@]}"; do
  2615. if grep -q " $SERVICE:" "$FILE"; then
  2616. if ! grep -A10 " $SERVICE:" "$FILE" | grep -q " - ./${SERVICES}_htpasswd:/auth/htpasswd"; then
  2617. sed -i "/ $SERVICE:/,/volumes:/ {
  2618. /volumes:/a\\
  2619. $HTPASSWD_CONFIG
  2620. }" "$FILE"
  2621. INFO "Htpasswd配置添加到 ${LIGHT_GREEN}$SERVICE${RESET} 服务中"
  2622. else
  2623. WARN "Htpasswd配置已存在 ${LIGHT_YELLOW}$SERVICE${RESET} 服务中"
  2624. fi
  2625. else
  2626. ERROR "服务 $SERVICE 在 $FILE 中不存在"
  2627. fi
  2628. done
  2629. }
  2630. DEL_AUTH_CONFIG() {
  2631. local FILE=$1
  2632. if [ ! -f "$FILE" ]; then
  2633. ERROR "配置文件 $FILE 不存在"
  2634. else
  2635. if grep -q "auth:" "$FILE"; then
  2636. sed -i '/^auth:$/,/^[^[:space:]]/d' "$FILE" >/dev/null
  2637. INFO "配置文件 ${LIGHT_BLUE}$FILE${RESET} 成功移除认证信息"
  2638. else
  2639. WARN "配置文件 ${LIGHT_BLUE}$FILE${RESET} 不存在认证信息"
  2640. fi
  2641. fi
  2642. }
  2643. DEL_AUTH_COMPOSE() {
  2644. local SERVICES=$1
  2645. local FILE=${DOCKER_COMPOSE_FILE}
  2646. if [ ! -f "$FILE" ]; then
  2647. ERROR "$File 不存在"
  2648. exit 1
  2649. fi
  2650. for SERVICE in "${SERVICES[@]}"; do
  2651. if grep -q " $SERVICE:" "$FILE"; then
  2652. sed -i "/ $SERVICE:/,/^[^[:space:]]/ {/^[[:space:]]*- .\/${SERVICES}_htpasswd:\/auth\/htpasswd/d}" "$FILE"
  2653. else
  2654. ERROR "$FILE 中不存在服务 $SERVICE"
  2655. fi
  2656. done
  2657. }
  2658. ENABLE_AUTH() {
  2659. AUTH_MENU
  2660. if [[ "$auth_service" == "0" ]]; then
  2661. WARN "退出添加容器认证操作!"
  2662. return
  2663. else
  2664. for choice in ${auth_service}; do
  2665. if [[ $choice =~ ^[0-9]+$ ]] && ((choice > 0 && choice <= ${#files[@]})); then
  2666. file_name=$(echo "${files[$((choice - 1))]}" | cut -d' ' -f2)
  2667. service_name=$(echo "${files[$((choice - 1))]}" | cut -d' ' -f1)
  2668. selected_files+=("$file_name")
  2669. if $DOCKER_COMPOSE_CMD ps --services 2>/dev/null | grep -q "^${service_name}$"; then
  2670. selected_services+=("$service_name")
  2671. else
  2672. WARN "服务 ${LIGHT_MAGENTA}${service_name} 未运行${RESET},无法添加认证授权"
  2673. fi
  2674. else
  2675. WARN "无效输入,请重新输入${LIGHT_YELLOW} 0-9 ${RESET}序号"
  2676. AUTH_MENU
  2677. return
  2678. fi
  2679. done
  2680. WARN "${LIGHT_GREEN}>>> 提示:${RESET} ${LIGHT_CYAN}配置认证后,执行镜像拉取需先通过 docker login登入后使用.访问UI需输入账号密码${RESET}"
  2681. read -e -p "$(INFO "是否需要配置镜像仓库访问账号和密码? ${PROMPT_YES_NO}")" enable_auth
  2682. while [[ "$enable_auth" != "y" && "$enable_auth" != "n" ]]; do
  2683. WARN "无效输入,请输入 ${LIGHT_GREEN}y${RESET} 或 ${LIGHT_YELLOW}n${RESET}"
  2684. read -e -p "$(INFO "是否需要配置镜像仓库访问账号和密码? ${PROMPT_YES_NO}")" enable_auth
  2685. done
  2686. if [[ "$enable_auth" == "y" ]]; then
  2687. while true; do
  2688. read -e -p "$(INFO "请输入账号名称: ")" username
  2689. if [[ -z "$username" ]]; then
  2690. ERROR "用户名不能为空。请重新输入"
  2691. else
  2692. break
  2693. fi
  2694. done
  2695. while true; do
  2696. read -e -p "$(INFO "请输入账号密码: ")" password
  2697. if [[ -z "$password" ]]; then
  2698. ERROR "密码不能为空。请重新输入"
  2699. else
  2700. break
  2701. fi
  2702. done
  2703. for file_url in "${selected_files[@]}"; do
  2704. yml_name=$(basename "$file_url")
  2705. ADD_AUTH_CONFIG "${PROXY_DIR}/${yml_name}"
  2706. done
  2707. for server in "${selected_services[@]}"; do
  2708. htpasswd -Bbc ${PROXY_DIR}/${server}_htpasswd "$username" "$password" 2>/dev/null
  2709. ADD_AUTH_COMPOSE "${server}"
  2710. done
  2711. fi
  2712. fi
  2713. }
  2714. DELETE_AUTH() {
  2715. AUTH_MENU
  2716. if [[ "$auth_service" == "0" ]]; then
  2717. WARN "退出移除容器认证操作!"
  2718. return
  2719. else
  2720. for choice in ${auth_service}; do
  2721. if [[ $choice =~ ^[0-9]+$ ]] && ((choice > 0 && choice <= ${#files[@]})); then
  2722. file_name=$(echo "${files[$((choice - 1))]}" | cut -d' ' -f2)
  2723. service_name=$(echo "${files[$((choice - 1))]}" | cut -d' ' -f1)
  2724. selected_files+=("$file_name")
  2725. if $DOCKER_COMPOSE_CMD ps --services 2>/dev/null | grep -q "^${service_name}$"; then
  2726. selected_services+=("$service_name")
  2727. else
  2728. WARN "服务 ${LIGHT_MAGENTA}${service_name} 未运行${RESET},无法添加认证授权"
  2729. fi
  2730. else
  2731. WARN "无效输入,请重新输入${LIGHT_YELLOW} 0-9 ${RESET}序号"
  2732. AUTH_MENU
  2733. return
  2734. fi
  2735. done
  2736. for file_url in "${selected_files[@]}"; do
  2737. yml_name=$(basename "$file_url")
  2738. DEL_AUTH_CONFIG "${PROXY_DIR}/${yml_name}"
  2739. done
  2740. for server in "${selected_services[@]}"; do
  2741. DEL_AUTH_COMPOSE "${server}"
  2742. rm -f ${PROXY_DIR}/${server}_htpasswd
  2743. done
  2744. fi
  2745. }
  2746. SEPARATOR "认证授权"
  2747. echo -e "1) ${BOLD}${LIGHT_YELLOW}添加${RESET}认证"
  2748. echo -e "2) ${BOLD}${LIGHT_CYAN}删除${RESET}认证"
  2749. echo -e "3) ${BOLD}返回${LIGHT_RED}主菜单${RESET}"
  2750. echo -e "0) ${BOLD}退出脚本${RESET}"
  2751. echo "---------------------------------------------------------------"
  2752. read -e -p "$(INFO "输入${LIGHT_CYAN}对应数字${RESET}并按${LIGHT_GREEN}Enter${RESET}键 > ")" auth_choice
  2753. case $auth_choice in
  2754. 1)
  2755. ENABLE_AUTH
  2756. if [ ${#selected_services[@]} -eq 0 ]; then
  2757. WARN "退出认证授权,请${LIGHT_CYAN}重新选择${RESET}服务认证的操作"
  2758. AUTH_SERVICE_CONFIG # 没有服务运行调用函数
  2759. else
  2760. $DOCKER_COMPOSE_CMD down ${selected_services[*]}
  2761. $DOCKER_COMPOSE_CMD up -d --force-recreate ${selected_services[*]}
  2762. fi
  2763. AUTH_SERVICE_CONFIG
  2764. ;;
  2765. 2)
  2766. DELETE_AUTH
  2767. if [ ${#selected_services[@]} -eq 0 ]; then
  2768. WARN "退出认证授权,请${LIGHT_CYAN}重新选择${RESET}服务认证的操作"
  2769. AUTH_SERVICE_CONFIG # 没有服务运行调用函数
  2770. else
  2771. $DOCKER_COMPOSE_CMD down ${selected_services[*]}
  2772. $DOCKER_COMPOSE_CMD up -d --force-recreate ${selected_services[*]}
  2773. fi
  2774. AUTH_SERVICE_CONFIG
  2775. ;;
  2776. 3)
  2777. main_menu
  2778. ;;
  2779. 0)
  2780. exit 1
  2781. ;;
  2782. *)
  2783. WARN "输入了无效的选择。请重新${LIGHT_GREEN}选择0-3${RESET}的选项."
  2784. AUTH_SERVICE_CONFIG
  2785. ;;
  2786. esac
  2787. }
  2788. # IP 黑白名单
  2789. function IP_BLACKWHITE_LIST() {
  2790. if ! command -v iptables &> /dev/null
  2791. then
  2792. WARN "iptables 未安装. 请安装后再运行此脚本."
  2793. exit 1
  2794. fi
  2795. IPTABLES=$(which iptables)
  2796. BLACKLIST_CHAIN="IP_BLACKLIST"
  2797. WHITELIST_CHAIN="IP_WHITELIST"
  2798. get_chain_name() {
  2799. local chain=$1
  2800. case $chain in
  2801. $BLACKLIST_CHAIN) echo "黑名单" ;;
  2802. $WHITELIST_CHAIN) echo "白名单" ;;
  2803. *) echo "未知名单" ;;
  2804. esac
  2805. }
  2806. create_chains() {
  2807. $IPTABLES -N $BLACKLIST_CHAIN 2>/dev/null
  2808. $IPTABLES -N $WHITELIST_CHAIN 2>/dev/null
  2809. }
  2810. create_chains
  2811. check_ip() {
  2812. local ip=$1
  2813. local ipv4_regex='^([0-9]{1,3}\.){3}[0-9]{1,3}$'
  2814. local ipv6_regex='^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$'
  2815. if [[ $ip =~ $ipv4_regex ]] || [[ $ip =~ $ipv6_regex ]]; then
  2816. return 0
  2817. else
  2818. return 1
  2819. fi
  2820. }
  2821. ip_exists_in_chain() {
  2822. local ip=$1
  2823. local chain=$2
  2824. local action=$3
  2825. $IPTABLES -C $chain -s $ip -j $action &>/dev/null
  2826. return $?
  2827. }
  2828. clear_chain() {
  2829. local chain=$1
  2830. $IPTABLES -F $chain
  2831. }
  2832. add_ip_to_chain() {
  2833. local ip=$1
  2834. local chain=$2
  2835. local action=$3
  2836. local chain_name=$(get_chain_name $chain)
  2837. if ! ip_exists_in_chain $ip $chain $action; then
  2838. $IPTABLES -A $chain -s $ip -j $action
  2839. INFO "${LIGHT_BLUE}$ip${RESET} ${LIGHT_GREEN}已添加${RESET}到$(get_chain_name $chain)"
  2840. else
  2841. WARN "${LIGHT_BLUE}$ip${RESET} ${LIGHT_YELLOW}已存在${RESET}于$(get_chain_name $chain),跳过添加"
  2842. fi
  2843. }
  2844. # 白名单
  2845. handle_whitelist() {
  2846. if ! $IPTABLES -L $WHITELIST_CHAIN >/dev/null 2>&1; then
  2847. $IPTABLES -N $WHITELIST_CHAIN
  2848. fi
  2849. if $IPTABLES -C INPUT -j $BLACKLIST_CHAIN >/dev/null 2>&1; then
  2850. read -e -p "$(WARN "${LIGHT_YELLOW}当前使用黑名单模式${RESET},${LIGHT_CYAN}是否切换到白名单模式?(y/n)${RESET}: ")" switch
  2851. if [[ $switch == "y" ]]; then
  2852. $IPTABLES -D INPUT -j $BLACKLIST_CHAIN
  2853. clear_chain $BLACKLIST_CHAIN
  2854. $IPTABLES -D INPUT -j $WHITELIST_CHAIN 2>/dev/null
  2855. else
  2856. return
  2857. fi
  2858. fi
  2859. clear_chain $WHITELIST_CHAIN
  2860. add_ip_to_chain 127.0.0.1 $WHITELIST_CHAIN ACCEPT
  2861. read -e -p "$(INFO "${LIGHT_CYAN}请输入白名单IP (用逗号分隔多个IP)${RESET}: ")" ips
  2862. IFS=',' read -ra ip_array <<< "$ips"
  2863. for ip in "${ip_array[@]}"; do
  2864. if check_ip $ip; then
  2865. add_ip_to_chain $ip $WHITELIST_CHAIN ACCEPT
  2866. else
  2867. WARN "无效IP: $ip"
  2868. fi
  2869. done
  2870. $IPTABLES -A $WHITELIST_CHAIN -j DROP
  2871. $IPTABLES -D INPUT -j $WHITELIST_CHAIN 2>/dev/null
  2872. $IPTABLES -I INPUT 1 -j $WHITELIST_CHAIN
  2873. INFO "${LIGHT_YELLOW}白名单已更新${RESET},只有指定的IP和本地回环可以访问"
  2874. IP_BLACKWHITE_LIST
  2875. }
  2876. # 黑名单
  2877. handle_blacklist() {
  2878. if ! $IPTABLES -L $BLACKLIST_CHAIN >/dev/null 2>&1; then
  2879. $IPTABLES -N $BLACKLIST_CHAIN
  2880. fi
  2881. if $IPTABLES -C INPUT -j $WHITELIST_CHAIN >/dev/null 2>&1; then
  2882. read -e -p "$(WARN "${LIGHT_YELLOW}当前使用白名单模式${RESET},${LIGHT_CYAN}是否切换到黑名单模式?(y/n)${RESET}: ")" switch
  2883. if [[ $switch == "y" ]]; then
  2884. $IPTABLES -D INPUT -j $WHITELIST_CHAIN
  2885. clear_chain $WHITELIST_CHAIN
  2886. $IPTABLES -D INPUT -j $BLACKLIST_CHAIN 2>/dev/null
  2887. else
  2888. return
  2889. fi
  2890. fi
  2891. read -e -p "$(INFO "${LIGHT_CYAN}请输入黑名单IP (用逗号分隔多个IP)${RESET}: ")" ips
  2892. IFS=',' read -ra ip_array <<< "$ips"
  2893. for ip in "${ip_array[@]}"; do
  2894. if check_ip $ip; then
  2895. add_ip_to_chain $ip $BLACKLIST_CHAIN DROP
  2896. else
  2897. WARN "无效IP: $ip"
  2898. fi
  2899. done
  2900. $IPTABLES -D INPUT -j $BLACKLIST_CHAIN 2>/dev/null
  2901. $IPTABLES -I INPUT 1 -j $BLACKLIST_CHAIN
  2902. INFO "${LIGHT_YELLOW}黑名单已更新${RESET},黑名单里的IP将无法访问"
  2903. IP_BLACKWHITE_LIST
  2904. }
  2905. SEPARATOR "设置IP黑白名单"
  2906. echo -e "1) ${BOLD}设置${LIGHT_GREEN}白名单${RESET}"
  2907. echo -e "2) ${BOLD}设置${LIGHT_CYAN}黑名单${RESET}"
  2908. echo -e "3) ${BOLD}返回${LIGHT_RED}主菜单${RESET}"
  2909. echo -e "0) ${BOLD}退出脚本${RESET}"
  2910. echo "---------------------------------------------------------------"
  2911. read -e -p "$(INFO "输入${LIGHT_CYAN}对应数字${RESET}并按${LIGHT_GREEN}Enter${RESET}键 > ")" ipblack_choice
  2912. case $ipblack_choice in
  2913. 1)
  2914. handle_whitelist
  2915. ;;
  2916. 2)
  2917. handle_blacklist
  2918. ;;
  2919. 3)
  2920. main_menu
  2921. ;;
  2922. 0)
  2923. exit 1
  2924. ;;
  2925. *)
  2926. WARN "输入了无效的选择。请重新${LIGHT_GREEN}选择0-3${RESET}的选项."
  2927. IP_BLACKWHITE_LIST
  2928. ;;
  2929. esac
  2930. }
  2931. # 其他工具
  2932. function OtherTools() {
  2933. echo -e "1) 设置${BOLD}${YELLOW}系统命令${RESET}"
  2934. echo -e "2) 配置${BOLD}${LIGHT_MAGENTA}IP黑白名单${RESET}"
  2935. echo -e "3) ${BOLD}返回${LIGHT_RED}主菜单${RESET}"
  2936. echo -e "0) ${BOLD}退出脚本${RESET}"
  2937. echo "---------------------------------------------------------------"
  2938. read -e -p "$(INFO "输入${LIGHT_CYAN}对应数字${RESET}并按${LIGHT_GREEN}Enter${RESET}键 > ")" main_choice
  2939. case $main_choice in
  2940. 1)
  2941. ADD_SYS_CMD
  2942. ;;
  2943. 2)
  2944. IP_BLACKWHITE_LIST
  2945. ;;
  2946. 3)
  2947. main_menu
  2948. ;;
  2949. 0)
  2950. exit 1
  2951. ;;
  2952. *)
  2953. WARN "输入了无效的选择。请重新${LIGHT_GREEN}选择0-3${RESET}的选项."
  2954. sleep 2; main_menu
  2955. ;;
  2956. esac
  2957. }
  2958. ## 主菜单
  2959. function main_menu() {
  2960. echo -e "╔════════════════════════════════════════════════════╗"
  2961. echo -e "║ ║"
  2962. echo -e "║ ${LIGHT_CYAN}欢迎使用Docker-Proxy${RESET} ║"
  2963. echo -e "║ ║"
  2964. echo -e "║ TG频道: ${UNDERLINE}https://t.me/dqzboyblog${RESET} ║"
  2965. echo -e "║ ║"
  2966. echo -e "║ ${LIGHT_BLUE}by dqzboy${RESET} ║"
  2967. echo -e "║ ║"
  2968. echo -e "╚════════════════════════════════════════════════════╝"
  2969. echo
  2970. SEPARATOR "请选择操作"
  2971. echo -e "1) ${BOLD}${LIGHT_GREEN}安装${RESET}服务"
  2972. echo -e "2) ${BOLD}${LIGHT_MAGENTA}组件${RESET}安装"
  2973. echo -e "3) ${BOLD}${LIGHT_YELLOW}管理${RESET}服务"
  2974. echo -e "4) ${BOLD}${LIGHT_CYAN}更新${RESET}配置"
  2975. echo -e "5) ${BOLD}${LIGHT_RED}卸载${RESET}服务"
  2976. echo -e "6) ${BOLD}${LIGHT_BLUE}认证${RESET}授权"
  2977. echo -e "7) 本机${BOLD}${CYAN}Docker代理${RESET}"
  2978. echo -e "8) 其他${BOLD}${YELLOW}工具${RESET}"
  2979. echo -e "0) ${BOLD}退出脚本${RESET}"
  2980. echo "---------------------------------------------------------------"
  2981. read -e -p "$(INFO "输入${LIGHT_CYAN}对应数字${RESET}并按${LIGHT_GREEN}Enter${RESET}键 > ")" main_choice
  2982. case $main_choice in
  2983. 1)
  2984. INSTALL_PROXY
  2985. ;;
  2986. 2)
  2987. COMP_INST
  2988. ;;
  2989. 3)
  2990. SVC_MGMT
  2991. ;;
  2992. 4)
  2993. SEPARATOR "更新配置"
  2994. UPDATE_CONFIG
  2995. SEPARATOR "更新完成"
  2996. ;;
  2997. 5)
  2998. UNI_DOCKER_SERVICE
  2999. ;;
  3000. 6)
  3001. AUTH_SERVICE_CONFIG
  3002. ;;
  3003. 7)
  3004. SEPARATOR "配置本机Docker代理"
  3005. DOCKER_PROXY_HTTP
  3006. ADD_DOCKERD_PROXY
  3007. SEPARATOR "Docker代理配置完成"
  3008. ;;
  3009. 8)
  3010. OtherTools
  3011. ;;
  3012. 0)
  3013. exit 1
  3014. ;;
  3015. *)
  3016. WARN "输入了无效的选择。请重新${LIGHT_GREEN}选择0-8${RESET}的选项."
  3017. sleep 2; main_menu
  3018. ;;
  3019. esac
  3020. }
  3021. main_menu