#!/bin/bash # 定义变量 CONTAINER_NAME="itc-web" IMAGE_NAME="127.0.0.1:5000/itc-web" IMAGE_VERSION="1.0.0" IMAGE_FULL="$IMAGE_NAME:$IMAGE_VERSION" PORT=9502 # 服务暴露端口 file="$CONTAINER_NAME-version.txt" CONF_PATH="/docker-data/itc-web/conf" # 检查文件是否存在(假设 $file 是目标文件变量,已在别处定义) if [ ! -f "$file" ]; then echo "文件 $file 不存在" touch "$file" # 变量加引号,处理含空格的文件名 echo "$IMAGE_FULL" >> "$file" echo "记录版本【$IMAGE_FULL】到 $file" else # 检查参数数量(建议移到脚本开头统一检查) if [ $# -eq 2 ]; then IMAGE_FULL="$IMAGE_NAME:$2" echo "$IMAGE_FULL" >> "$file" echo "记录版本【$IMAGE_FULL】到 $file" else # 修正赋值语法:等号两侧无空格 last_version=$(tail -n 1 "$file") IMAGE_FULL="$last_version" # 建议添加对 $IMAGE_FULL 的后续处理(如使用该变量) fi fi # 显示帮助信息 show_help() { echo "使用方法: $0 [操作类型]" echo "操作类型:" echo " deploy - 部署并启动服务容器" echo " remove - 停止并删除容器及数据/日志目录" echo " logs - 查看容器日志" echo " help - 显示帮助信息" } # 创建目录并设置权限函数 create_dirs() { # 创建数据目录并设置权限 if [ ! -d "$CONF_PATH" ]; then mkdir -p "$CONF_PATH" echo "创建数据目录: $CONF_PATH" chmod -R 777 "$CONF_PATH" echo "设置数据目录权限: $CONF_PATH" fi # 生成单机模式配置文件(若不存在) if [ ! -f "$CONF_PATH/nginx.conf" ]; then echo "生成配置文件: $CONF_PATH/nginx.conf" cat > "$CONF_PATH/nginx.conf" << EOF #user nobody; # 工作进程数:自动匹配CPU核心数(比固定值更灵活) worker_processes 4; # 错误日志:开启并按级别分离(方便问题定位) error_log /var/log/nginx/error.log notice; pid /run/nginx.pid; # 全局资源限制(避免文件描述符不足) worker_rlimit_nofile 65535; events { # 每个工作进程最大连接数(结合系统ulimit调整) worker_connections 8192; # 高效事件模型(Linux推荐epoll,FreeBSD用kqueue) use epoll; # 一次性接受所有新连接(提高连接处理效率) multi_accept on; } http { include mime.types; default_type application/octet-stream; # 日志格式优化:增加响应时间和 upstream 信息(便于性能分析) log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" ' '\$status $body_bytes_sent "\$http_referer" ' '"\$http_user_agent" "\$http_x_forwarded_for" ' '\$request_time \$upstream_response_time'; # 访问日志:开启(生产环境可按需关闭或调整路径) access_log /var/log/nginx/access.log main; # 高效文件传输 sendfile on; # 静态文件传输优化(配合sendfile使用,减少TCP包数量) tcp_nopush on; # 动态内容优化(减少网络延迟) tcp_nodelay on; # 长连接设置 keepalive_timeout 65; # 连接超时时间 keepalive_requests 1000; # 每个连接最大请求数(防止长连接占用) keepalive_disable msie6; # 对老旧IE禁用长连接 # 客户端请求限制(防攻击) client_max_body_size 100m; # 缩小上传限制(1024m过大,按需调整) client_body_buffer_size 1m; # 客户端请求体缓冲区(原1024k保留,单位统一) client_body_timeout 120s; # 客户端发送请求体超时 client_header_timeout 120s; # 客户端发送请求头超时 # Gzip压缩优化 gzip on; gzip_min_length 1k; # 最小压缩尺寸 gzip_comp_level 5; # 压缩级别(平衡CPU和带宽) gzip_types text/plain text/css text/xml application/json application/javascript application/x-javascript text/javascript application/xml application/xml+rss text/rss; # 明确需要压缩的类型 gzip_disable "MSIE [1-6]\."; # 禁用老旧IE压缩 gzip_vary on; # 告诉代理服务器缓存压缩和非压缩版本 gzip_buffers 16 8k; # 压缩缓冲区(默认值优化) gzip_http_version 1.1; # 仅对HTTP/1.1及以上启用(避免兼容问题) gzip_proxied any; # 对代理请求也启用压缩 # 隐藏nginx版本号(安全加固) server_tokens off; # 通用安全响应头(全局生效) add_header X-Frame-Options "SAMEORIGIN"; # 防止点击劫持 add_header X-XSS-Protection "1; mode=block"; # 防XSS攻击 add_header X-Content-Type-Options "nosniff"; # 防止MIME类型嗅探 # 反向代理配置 http://10.4.126.112:23000 upstream upstream_name{ server 10.10.2.102:9500; keepalive 32; # 长连接池大小,减少连接建立开销 keepalive_timeout 60s; keepalive_requests 1000; } # 虚拟主机配置 server { listen 8080; listen [::]:8080; # 建议替换为实际域名(如example.com),避免用localhost #server_name 10.4.126.116; # 网站根目录 root /usr/share/nginx/html; # 默认索引文件 index index.html; # API接口代理配置(优化版) location ^~/api/ { # 代理目标地址 proxy_pass http://upstream_name/; # 增强头信息转发 proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; gzip off; # 禁用该接口的 gzip 压缩 proxy_set_header Accept-Encoding ""; # 清除传给后端的 Accept-Encoding 头 # 超时设置(API专用,可根据业务调整) proxy_connect_timeout 300s; proxy_send_timeout 300s; proxy_read_timeout 300s; } location ^~/preview/ { # 代理目标地址 proxy_pass http://10.10.2.102:8012/preview/; # 增强头信息转发 proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; gzip off; # 禁用该接口的 gzip 压缩 proxy_set_header Accept-Encoding ""; # 清除传给后端的 Accept-Encoding 头 # 超时设置(API专用,可根据业务调整) proxy_connect_timeout 300s; proxy_send_timeout 300s; proxy_read_timeout 300s; } # 主路径匹配 location / { try_files \$uri \$uri/ /index.html; # 适合SPA应用(如Vue/React) # 缓存控制:动态内容不缓存 add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Pragma "no-cache"; add_header Expires "0"; } # 静态资源缓存优化(比原配置更精细) location ~* \.(gif|jpg|jpeg|png|ico|svg|js|css|json|txt)\$ { # 缓存1天(可根据资源更新频率调整,如图片可设30d) expires 1d; add_header Cache-Control "public, max-age=86400"; } # 错误页面配置 error_page 500 502 503 504 /50x.html; location = /50x.html { # 显式指定root(避免继承外层可能的变更) root /usr/share/nginx/html; } # 禁止访问隐藏文件(如.git .env等) location ~ /\. { deny all; access_log off; log_not_found off; } } } EOF fi } # 部署服务 deploy_service() { echo "部署镜像【$IMAGE_FULL】" # 检查容器是否已存在,存在则停止并删除 if [ "$(docker ps -aq -f name=$CONTAINER_NAME)" ]; then echo "停止并删除现有容器: $CONTAINER_NAME" docker stop $CONTAINER_NAME >/dev/null docker rm $CONTAINER_NAME >/dev/null fi # 启动服务容器 echo "启动服务容器..." create_dirs docker run -d --privileged --restart always --name $CONTAINER_NAME \ -p $PORT:8080 \ -v $CONF_PATH/nginx.conf:/etc/nginx/nginx.conf \ $IMAGE_FULL # 检查启动状态 if [ "$(docker ps -aq -f name=$CONTAINER_NAME -f status=running)" ]; then echo "服务启动成功!" echo "容器名称: $CONTAINER_NAME" echo "访问地址: http://localhost:$PORT" else echo "服务启动失败,日志如下:" docker logs $CONTAINER_NAME exit 1 fi } # 删除服务 remove_service() { # 检查容器是否存在 if [ "$(docker ps -aq -f name=$CONTAINER_NAME)" ]; then echo "停止容器: $CONTAINER_NAME" docker stop $CONTAINER_NAME >/dev/null echo "删除容器: $CONTAINER_NAME" docker rm $CONTAINER_NAME >/dev/null else echo "容器 $CONTAINER_NAME 不存在" fi } # 查看日志 show_logs() { if [ "$(docker ps -aq -f name=$CONTAINER_NAME)" ]; then echo "查看 $CONTAINER_NAME 容器日志 (按 Ctrl+C 退出)..." docker logs -f $CONTAINER_NAME else echo "容器 $CONTAINER_NAME 不存在" fi } # 主逻辑 if [ $# -lt 1 ]; then show_help exit 1 fi case "$1" in deploy) deploy_service ;; remove) remove_service ;; logs) show_logs ;; help) show_help ;; *) echo "无效的操作类型: $1" show_help exit 1 ;; esac