This commit is contained in:
vet
2026-04-13 01:27:34 +07:00
commit c7c3c02bc3
18 changed files with 2730 additions and 0 deletions

227
03-start-infra.sh Executable file
View File

@@ -0,0 +1,227 @@
#!/usr/bin/env bash
# =============================================================================
# 03-start-infra.sh — 启动 Docker 基础设施Redis / Kafka / Etcd / LiveKit
#
# 数据目录: .local-dev/docker-data/<svc>/
# 容器日志: .local-dev/docker-logs/<svc>/<svc>-YYYYMMDD.log每日一文件
# 脚本日志: .local-dev/script-logs/03-start-infra-<ts>.log
#
# 后续步骤04-build.sh编译后端服务
# =============================================================================
set -euo pipefail
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common.sh"
load_env
init_dirs
init_script_log # ← 脚本执行日志
require_docker_running
# Docker 日志驱动公共参数JSON 文件,最多 5 个 50MB 轮转)
LOG_OPTS=(
--log-driver json-file
--log-opt max-size=50m
--log-opt max-file=5
)
header "步骤 3 / 5 — 启动 Docker 基础设施"
# ──────────────────────────────────────────────────────────────────────────────
# Redis
# ──────────────────────────────────────────────────────────────────────────────
step "Redis"
if docker ps --format '{{.Names}}' | grep -q '^dev-redis$'; then
success "Redis 已在运行 (container=dev-redis) :${REDIS_PORT}"
elif docker ps -a --format '{{.Names}}' | grep -q '^dev-redis$'; then
info "重新启动已有容器 dev-redis..."
docker start dev-redis > /dev/null
success "Redis 已启动 :${REDIS_PORT}"
else
info "创建并启动 Redis 容器..."
docker run -d \
--name dev-redis \
--restart unless-stopped \
-p "${REDIS_PORT}:6379" \
-v "${DATA_DIR}/redis:/data" \
"${LOG_OPTS[@]}" \
redis:7-alpine \
redis-server --requirepass "${REDIS_PASSWORD:-openIM123}" --appendonly yes \
> /dev/null
success "Redis 容器已创建并启动 :${REDIS_PORT} (密码: ${REDIS_PASSWORD:-openIM123})"
fi
sleep 1
if docker exec dev-redis redis-cli -a "${REDIS_PASSWORD:-openIM123}" ping 2>/dev/null | grep -q PONG; then
success "Redis 连通性: PONG ✓"
else
warn "Redis 未响应 PING请查看日志: ./deploy-test/logs.sh redis"
fi
start_docker_logger "dev-redis"
# ──────────────────────────────────────────────────────────────────────────────
# KafkaKRaft 模式)
# ──────────────────────────────────────────────────────────────────────────────
step "Kafka (KRaft)"
if docker ps --format '{{.Names}}' | grep -q '^dev-kafka$'; then
success "Kafka 已在运行 (container=dev-kafka) :${KAFKA_PORT}"
elif docker ps -a --format '{{.Names}}' | grep -q '^dev-kafka$'; then
info "重新启动已有容器 dev-kafka..."
docker start dev-kafka > /dev/null
info "等待 Kafka 就绪 (8s)..."
sleep 8
success "Kafka 已启动 :${KAFKA_PORT}"
else
info "创建并启动 Kafka 容器(首次拉取镜像可能较慢)..."
KAFKA_CLUSTER_ID="MkU3OEVBNTcwNTJENDM2Qk"
docker run -d \
--name dev-kafka \
--restart unless-stopped \
-p "${KAFKA_PORT}:9092" \
-v "${DATA_DIR}/kafka:/bitnami/kafka" \
-e KAFKA_CFG_NODE_ID=0 \
-e KAFKA_CFG_PROCESS_ROLES=controller,broker \
-e KAFKA_CFG_LISTENERS="PLAINTEXT://:9092,CONTROLLER://:9093" \
-e KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP="CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT" \
-e KAFKA_CFG_CONTROLLER_QUORUM_VOTERS="0@localhost:9093" \
-e KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER \
-e KAFKA_CFG_ADVERTISED_LISTENERS="PLAINTEXT://127.0.0.1:${KAFKA_PORT}" \
-e KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=true \
-e KAFKA_KRAFT_CLUSTER_ID="$KAFKA_CLUSTER_ID" \
"${LOG_OPTS[@]}" \
bitnami/kafka:3.7 \
> /dev/null
info "等待 Kafka 就绪 (15s)..."
sleep 15
success "Kafka 容器已创建并启动 :${KAFKA_PORT}"
fi
start_docker_logger "dev-kafka"
# 初始化必要 Topics
step "Kafka Topics 初始化"
TOPICS=(toRedis toMongo toPush toOfflinePush)
for topic in "${TOPICS[@]}"; do
if docker exec dev-kafka kafka-topics.sh \
--bootstrap-server localhost:9092 \
--list 2>/dev/null | grep -q "^${topic}$"; then
info " topic 已存在: $topic"
else
docker exec dev-kafka kafka-topics.sh \
--create \
--topic "$topic" \
--bootstrap-server localhost:9092 \
--partitions 8 \
--replication-factor 1 \
2>/dev/null \
&& success " ✓ 创建 topic: $topic" \
|| warn " ✗ 创建失败: $topicKafka 未就绪,重试: ./deploy-test/03-start-infra.sh"
fi
done
# ──────────────────────────────────────────────────────────────────────────────
# Etcd
# ──────────────────────────────────────────────────────────────────────────────
step "Etcd"
if docker ps --format '{{.Names}}' | grep -q '^dev-etcd$'; then
success "Etcd 已在运行 (container=dev-etcd) :${ETCD_PORT}"
elif docker ps -a --format '{{.Names}}' | grep -q '^dev-etcd$'; then
info "重新启动已有容器 dev-etcd..."
docker start dev-etcd > /dev/null
sleep 2
success "Etcd 已启动 :${ETCD_PORT}"
else
info "创建并启动 Etcd 容器..."
docker run -d \
--name dev-etcd \
--restart unless-stopped \
-p "${ETCD_PORT}:2379" \
-v "${DATA_DIR}/etcd:/etcd-data" \
-e ALLOW_NONE_AUTHENTICATION=yes \
-e ETCD_DATA_DIR=/etcd-data \
"${LOG_OPTS[@]}" \
bitnami/etcd:3.5 \
> /dev/null
sleep 2
success "Etcd 容器已创建并启动 :${ETCD_PORT}"
fi
if docker exec dev-etcd etcdctl endpoint health 2>/dev/null | grep -q 'is healthy'; then
success "Etcd 连通性: healthy ✓"
else
warn "Etcd 未返回健康状态,可能仍在启动中"
fi
start_docker_logger "dev-etcd"
# ──────────────────────────────────────────────────────────────────────────────
# LiveKit本地 Docker 容器,复用 dev-redis
# ──────────────────────────────────────────────────────────────────────────────
step "LiveKit"
LK_CONF="$ROOT_DIR/livekit/livekit.yaml"
if [[ ! -f "$LK_CONF" ]]; then
warn "livekit/livekit.yaml 不存在,请先执行: ./deploy-test/02-patch-config.sh"
else
if docker ps --format '{{.Names}}' | grep -q '^dev-livekit$'; then
success "LiveKit 已在运行 (container=dev-livekit) :7880"
elif docker ps -a --format '{{.Names}}' | grep -q '^dev-livekit$'; then
info "重新启动已有容器 dev-livekit..."
docker start dev-livekit > /dev/null
sleep 2
success "LiveKit 已启动 :7880"
else
info "创建并启动 LiveKit 容器(首次拉取镜像需要一点时间)..."
EXTRA_HOSTS=""
[[ "$(uname -s)" == "Linux" ]] && EXTRA_HOSTS="--add-host host.docker.internal:host-gateway"
# shellcheck disable=SC2086
docker run -d \
--name dev-livekit \
--restart unless-stopped \
-p 7880:7880 \
-p 7882:7882/tcp \
-p 7882:7882/udp \
-p 50000-51000:50000-51000/udp \
-v "${LK_CONF}:/etc/livekit.yaml:ro" \
"${LOG_OPTS[@]}" \
$EXTRA_HOSTS \
livekit/livekit-server:latest \
--config /etc/livekit.yaml \
> /dev/null
sleep 3
if docker ps --format '{{.Names}}' | grep -q '^dev-livekit$'; then
success "LiveKit 容器已创建并启动 :7880"
info " 公网 IP: ${LIVEKIT_NODE_IP} (WebRTC 媒体流直连)"
info " API Key: ${LIVEKIT_API_KEY}"
else
error "LiveKit 启动失败,查看日志: ./deploy-test/logs.sh livekit"
fi
fi
start_docker_logger "dev-livekit"
fi
# ──────────────────────────────────────────────────────────────────────────────
# 汇总
# ──────────────────────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}基础设施状态:${NC}"
print_container_status "Redis" "dev-redis" "${REDIS_PORT}"
print_container_status "Kafka" "dev-kafka" "${KAFKA_PORT}"
print_container_status "Etcd" "dev-etcd" "${ETCD_PORT}"
print_container_status "LiveKit" "dev-livekit" "7880"
echo ""
echo -e "${BOLD}日志目录:${NC}"
echo " Docker 容器日志: $DOCKER_LOG_DIR/"
echo " 本脚本执行日志: $_CURRENT_SCRIPT_LOG"
echo ""
echo -e " LiveKit 公网: ${LIVEKIT_NODE_IP}:50000-51000/udp (WebRTC 媒体流)"
echo ""
success "Docker 基础设施已就绪!"
echo ""
echo -e "${BOLD}下一步:${NC}"
echo -e " 编译所有后端 Go 服务:"
echo -e " ${CYAN}./deploy-test/04-build.sh${NC}"