增加docke部署

This commit is contained in:
2026-04-10 16:44:13 +08:00
parent e2f8054794
commit cd4ddb606d
5076 changed files with 701092 additions and 0 deletions

View File

@@ -0,0 +1,194 @@
#!/bin/bash
# ============================================
# SSL 证书初始化脚本(首次部署时运行)
#
# 使用 Let's Encrypt (certbot) 为 3 个域名申请证书
# 流程:
# 1. 启动 Nginx仅 HTTP 80 端口,用于 ACME 验证)
# 2. 用 certbot 对每个域名申请证书
# 3. 重新加载 Nginx 以启用 HTTPS
#
# 用法:
# ./init-ssl.sh # 正式申请证书
# ./init-ssl.sh --staging # 使用 staging 环境测试(不受速率限制)
# ./init-ssl.sh --dry-run # 仅测试,不真正申请
# ============================================
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$SCRIPT_DIR"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# 加载 .env
if [ ! -f .env ]; then
log_error ".env 文件不存在!请先执行: cp .env.example .env 并填写配置"
exit 1
fi
source .env
# 检查必要变量
if [ -z "$SSL_EMAIL" ]; then
log_error "请在 .env 中设置 SSL_EMAIL用于 Let's Encrypt 证书申请通知)"
exit 1
fi
if [ -z "$API_DOMAIN" ] || [ -z "$DLWEB_DOMAIN" ] || [ -z "$WX_DOMAIN" ]; then
log_error "请在 .env 中设置 API_DOMAIN, DLWEB_DOMAIN, WX_DOMAIN"
exit 1
fi
DOMAINS=("$API_DOMAIN" "$DLWEB_DOMAIN" "$WX_DOMAIN")
# 判断使用 docker-compose 还是 docker compose
COMPOSE_CMD="docker compose"
if ! docker compose version &> /dev/null 2>&1; then
COMPOSE_CMD="docker-compose"
fi
# 解析参数
STAGING_ARG=""
DRY_RUN=""
for arg in "$@"; do
case $arg in
--staging)
STAGING_ARG="--staging"
log_warn "使用 Let's Encrypt Staging 环境(测试用,证书不受信任)"
;;
--dry-run)
DRY_RUN="--dry-run"
log_warn "Dry-run 模式,不会真正申请证书"
;;
esac
done
# ============================================
# Step 1: 生成临时自签名证书(让 Nginx 能先启动)
# ============================================
log_info "Step 1: 生成临时自签名证书..."
for domain in "${DOMAINS[@]}"; do
CERT_DIR="./docker/nginx/dummy-certs/$domain"
mkdir -p "$CERT_DIR"
if [ ! -f "$CERT_DIR/fullchain.pem" ]; then
openssl req -x509 -nodes -newkey rsa:2048 -days 1 \
-keyout "$CERT_DIR/privkey.pem" \
-out "$CERT_DIR/fullchain.pem" \
-subj "/CN=$domain" 2>/dev/null
log_info " 已生成临时自签名证书: $domain"
fi
done
# ============================================
# Step 2: 将临时证书复制到 certbot volume
# ============================================
log_info "Step 2: 初始化证书 volume..."
# 确保容器和 volume 存在
$COMPOSE_CMD up -d nginx 2>/dev/null || true
# 将临时证书复制到 certbot-certs volume
for domain in "${DOMAINS[@]}"; do
CERT_DIR="./docker/nginx/dummy-certs/$domain"
LIVE_DIR="/etc/letsencrypt/live/$domain"
# 通过 nginx 容器操作 volume
docker exec youle-nginx sh -c "mkdir -p $LIVE_DIR" 2>/dev/null || true
docker cp "$CERT_DIR/fullchain.pem" "youle-nginx:$LIVE_DIR/fullchain.pem"
docker cp "$CERT_DIR/privkey.pem" "youle-nginx:$LIVE_DIR/privkey.pem"
done
# 重新加载 Nginx 以使用临时证书
docker exec youle-nginx nginx -s reload 2>/dev/null || true
log_info " Nginx 已使用临时证书启动"
# ============================================
# Step 3: 用 certbot 申请真实证书
# ============================================
log_info "Step 3: 申请 Let's Encrypt 证书..."
for domain in "${DOMAINS[@]}"; do
log_info " 正在为 $domain 申请证书..."
$COMPOSE_CMD run --rm certbot certonly \
--webroot \
-w /var/www/certbot \
--email "$SSL_EMAIL" \
--agree-tos \
--no-eff-email \
--force-renewal \
-d "$domain" \
$STAGING_ARG \
$DRY_RUN
if [ $? -eq 0 ]; then
log_info "$domain 证书申请成功"
else
log_error "$domain 证书申请失败!请检查:"
log_error " - 域名 DNS 是否已正确解析到本服务器"
log_error " - 服务器 80 端口是否对外开放"
log_error " - 是否超过 Let's Encrypt 速率限制(可用 --staging 测试)"
fi
done
# ============================================
# Step 4: 重新加载 Nginx 以使用真实证书
# ============================================
log_info "Step 4: 重新加载 Nginx..."
docker exec youle-nginx nginx -s reload
# ============================================
# Step 5: 清理临时文件并启动 certbot 定时续签
# ============================================
rm -rf ./docker/nginx/dummy-certs
log_info "Step 5: 启动 certbot 自动续签服务..."
$COMPOSE_CMD up -d certbot
# ============================================
# Step 6: 安装 crontab 定时重载 Nginx使续签生效
# ============================================
log_info "Step 6: 设置自动重载 Nginx 的 crontab..."
CRON_JOB="0 */12 * * * docker exec youle-nginx nginx -s reload >/dev/null 2>&1"
CRON_MARKER="# youle-nginx-ssl-reload"
# 检查是否已存在
if crontab -l 2>/dev/null | grep -q "$CRON_MARKER"; then
log_info " crontab 已存在,跳过"
else
# 追加到当前用户的 crontab
(crontab -l 2>/dev/null; echo "$CRON_JOB $CRON_MARKER") | crontab -
log_info " 已添加 crontab: 每 12 小时重载 Nginx使续签的证书生效"
fi
echo ""
log_info "============================================"
log_info "SSL 初始化完成!"
log_info "============================================"
echo ""
echo " 证书信息:"
for domain in "${DOMAINS[@]}"; do
echo " https://$domain"
done
echo ""
echo " 证书有效期: 90 天"
echo " 自动续签: certbot 容器每 12 小时检查一次"
echo " 自动重载: crontab 每 12 小时执行 nginx -s reload"
echo ""
echo " 查看证书状态:"
echo " $COMPOSE_CMD run --rm certbot certificates"
echo ""
echo " 手动续签:"
echo " ./deploy.sh ssl-renew"
echo ""