服务器部署
...大约 23 分钟
服务器部署
首先在Linux服务器上创建一个项目部署根目录
MySQL安装
# Docker Compose 文件版本
# 3.8 版本功能完善且兼容性好,支持大多数 Docker 版本
version: '3.8'
# 服务定义
services:
# MySQL 服务
mysql:
# 使用 MySQL 8.0 官方镜像
image: mysql:8.0
# 容器名称(方便管理和识别)
container_name: mysql8.0
# 重启策略
# - no: 不自动重启(默认)
# - always: 总是自动重启
# - on-failure: 仅在异常退出时重启
# - unless-stopped: 除非手动停止,否则自动重启
restart: always
# 环境变量
environment:
# root用户密码(生产环境建议使用强密码)
MYSQL_ROOT_PASSWORD: root
# 容器启动时自动创建的数据库
# MYSQL_DATABASE: auto-report
# 时区设置(东八区)
TZ: Asia/Shanghai
# 端口映射
# 格式: "宿主机端口:容器端口"
ports:
# 宿主机 13306 端口 -> 容器 3306 端口
# 外部访问: mysql -h 127.0.0.1 -P 13306 -uroot -proot
- "13306:3306"
# 数据卷挂载 格式: 宿主机路径:容器路径
volumes:
# 数据持久化(存储数据库文件)
# 容器删除后数据依然保留
- ./mysql-data:/var/lib/mysql
# 初始化脚本目录
# 首次启动时自动执行该目录下的 .sql/.sh 文件
# 仅在数据目录为空时执行一次
- ./mysql-init:/docker-entrypoint-initdb.d
# 自定义配置文件目录
# 在此目录放置 my.cnf 文件覆盖默认配置
- ./conf:/etc/mysql/conf.d
# 日志目录(慢查询日志、错误日志等)
- ./mysql-logs:/var/log/mysql
# 启动命令参数
command:
# 使用传统密码验证方式
# MySQL 8.0 默认 caching_sha2_password,部分客户端不兼容
- --default-authentication-plugin=mysql_native_password
# 定期检测容器内服务是否正常运行
healthcheck:
# 检测命令
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-proot"]
# 检查间隔
interval: 10s
# 超时时间
timeout: 5s
# 失败重试次数
retries: 3
# 启动等待时间(给 MySQL 足够的启动时间)
start_period: 30s
# 数据卷定义
volumes:
# MySQL 数据卷
mysql-data:
driver: local
# 日志数据卷
mysql-logs:
driver: local
[mysqld]
# 字符集配置
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
default-time-zone='+08:00'
# 连接配置
max_connections=1000
max_allowed_packet=64M
# InnoDB 性能优化
innodb_buffer_pool_size=256M
innodb_log_file_size=64M
innodb_flush_log_at_trx_commit=2
innodb_flush_method=O_DIRECT
# 查询缓存(MySQL 8.0 已移除,但保留兼容性)
# query_cache_type=0
# query_cache_size=0
# 日志配置
# 慢查询日志
slow_query_log=1
slow_query_log_file=/var/log/mysql/slow.log
long_query_time=2
# 错误日志
log_error=/var/log/mysql/error.log
# 二进制日志(可选,用于主从复制和数据恢复)
# log_bin=/var/log/mysql/mysql-bin
# binlog_format=ROW
# expire_logs_days=7
# SQL 模式设置
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
# 表名大小写敏感性(0=敏感,1=不敏感,2=创建时大写,查询时小写)
# Windows 下建议设置为 1
lower_case_table_names=1
[client]
# 客户端默认字符集
default-character-set=utf8mb4
port=3306
[mysql]
# MySQL 命令行工具配置
default-character-set=utf8mb4
#!/bin/bash
################################################################################
# MySQL Docker 自动化部署脚本
# 功能: 自动检查环境、部署 MySQL 容器、执行验证测试
# 使用: ./mysql-deploy.sh
################################################################################
set -e # 遇到错误立即退出
# 切换到脚本所在目录
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$SCRIPT_DIR"
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 配置信息
COMPOSE_FILE="docker-compose-mysql.yml"
CONTAINER_NAME="mysql8.0"
MYSQL_PORT="13306"
MYSQL_ROOT_PASSWORD="root"
# Docker Compose 命令(将自动检测)
DOCKER_COMPOSE_CMD=""
# 打印带颜色的消息
print_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
print_step() {
echo ""
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}$1${NC}"
echo -e "${BLUE}========================================${NC}"
}
# 执行 Docker Compose 命令
run_compose() {
$DOCKER_COMPOSE_CMD -f "$COMPOSE_FILE" "$@"
}
# 检查命令是否存在
check_command() {
if ! command -v $1 &> /dev/null; then
print_error "$1 未安装"
return 1
else
print_success "$1 已安装"
return 0
fi
}
# 检查端口是否被占用
check_port() {
if netstat -tlnp 2>/dev/null | grep -q ":$1 "; then
print_error "端口 $1 已被占用"
netstat -tlnp | grep ":$1 "
return 1
else
print_success "端口 $1 可用"
return 0
fi
}
# 检测 Docker Compose 命令
detect_docker_compose() {
print_info "检测 Docker Compose..."
if docker compose version &> /dev/null; then
DOCKER_COMPOSE_CMD="docker compose"
print_success "使用: docker compose (V2)"
docker compose version
return 0
elif command -v docker-compose &> /dev/null; then
if docker-compose version &> /dev/null; then
DOCKER_COMPOSE_CMD="docker-compose"
print_success "使用: docker-compose (V1)"
docker-compose version
return 0
else
print_error "docker-compose 存在版本兼容性问题"
return 1
fi
else
print_error "未找到 Docker Compose"
return 1
fi
}
# 主程序
main() {
print_step "MySQL Docker 自动化部署脚本"
echo "工作目录: $SCRIPT_DIR"
echo "配置文件: $COMPOSE_FILE"
echo "容器名称: $CONTAINER_NAME"
echo "MySQL 端口: $MYSQL_PORT"
echo "部署时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo ""
# 步骤 1: 检查系统环境
print_step "步骤 1/6: 检查系统环境"
print_info "检查操作系统..."
if [ -f /etc/os-release ]; then
. /etc/os-release
print_success "操作系统: $NAME $VERSION"
else
print_warning "无法识别操作系统"
fi
print_info "检查系统架构..."
print_success "系统架构: $(uname -m)"
print_info "检查可用磁盘空间..."
DISK_AVAIL=$(df -h . | awk 'NR==2 {print $4}')
print_success "可用磁盘空间: $DISK_AVAIL"
# 步骤 2: 检查 Docker 环境
print_step "步骤 2/6: 检查 Docker 环境"
print_info "检查 Docker..."
if ! check_command docker; then
print_error "请先安装 Docker"
print_info "安装命令: curl -fsSL https://get.docker.com | bash"
exit 1
fi
docker --version
print_info "检查 Docker 服务状态..."
if ! systemctl is-active --quiet docker 2>/dev/null && ! docker info &> /dev/null; then
print_error "Docker 服务未运行"
print_info "启动命令: systemctl start docker"
exit 1
fi
print_success "Docker 服务运行正常"
if ! detect_docker_compose; then
exit 1
fi
# 步骤 3: 检查部署文件
print_step "步骤 3/6: 检查部署文件"
print_info "检查当前目录..."
pwd
ls -la
print_info "检查 Docker Compose 配置文件..."
if [ ! -f "$COMPOSE_FILE" ]; then
print_error "找不到 $COMPOSE_FILE 文件"
exit 1
fi
print_success "找到 $COMPOSE_FILE"
print_info "检查 MySQL 配置文件..."
if [ ! -f "conf/my.cnf" ]; then
print_warning "找不到配置文件 conf/my.cnf(将使用默认配置)"
else
print_success "找到配置文件 conf/my.cnf"
fi
print_info "验证 Docker Compose 配置..."
if run_compose config > /dev/null 2>&1; then
print_success "配置文件语法正确"
else
print_error "配置文件语法错误"
run_compose config
exit 1
fi
# 步骤 4: 检查端口和容器状态
print_step "步骤 4/6: 检查端口和容器状态"
print_info "检查端口 $MYSQL_PORT 是否被占用..."
if command -v netstat &> /dev/null; then
check_port $MYSQL_PORT || print_warning "端口 $MYSQL_PORT 已被占用,继续可能会失败"
elif command -v ss &> /dev/null; then
if ss -tlnp | grep -q ":$MYSQL_PORT "; then
print_warning "端口 $MYSQL_PORT 已被占用"
else
print_success "端口 $MYSQL_PORT 可用"
fi
else
print_warning "netstat/ss 未安装,跳过端口检查"
fi
print_info "检查是否存在同名容器..."
if docker ps -a | grep -q "$CONTAINER_NAME"; then
print_warning "容器 $CONTAINER_NAME 已存在"
read -p "是否删除并重新创建?[y/N] " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
print_info "停止并删除现有容器..."
run_compose down -v
print_success "已删除现有容器"
else
print_info "保留现有容器,尝试启动..."
fi
fi
# 步骤 5: 拉取镜像并启动
print_step "步骤 5/6: 拉取镜像并启动容器"
print_info "拉取 MySQL 8.0 镜像..."
print_warning "首次拉取可能需要几分钟,请耐心等待..."
if run_compose pull; then
print_success "镜像拉取成功"
else
print_error "镜像拉取失败"
exit 1
fi
print_info "启动容器(后台运行)..."
if run_compose up -d; then
print_success "容器启动命令执行成功"
else
print_error "容器启动失败"
print_info "查看日志: run_compose logs"
exit 1
fi
print_info "等待 MySQL 服务就绪(最多等待 90 秒)..."
WAIT_TIME=0
MAX_WAIT=90
while [ $WAIT_TIME -lt $MAX_WAIT ]; do
if docker exec $CONTAINER_NAME mysqladmin ping -h localhost --silent 2>/dev/null; then
echo ""
print_success "MySQL 服务已就绪"
break
fi
echo -n "."
sleep 3
WAIT_TIME=$((WAIT_TIME + 3))
done
if [ $WAIT_TIME -ge $MAX_WAIT ]; then
echo ""
print_error "MySQL 服务启动超时"
print_info "查看日志:"
run_compose logs --tail=50
exit 1
fi
# 步骤 6: 验证部署
print_step "步骤 6/6: 验证部署"
print_info "检查容器状态..."
run_compose ps
print_info "检查 MySQL 版本..."
docker exec $CONTAINER_NAME mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e "SELECT VERSION();" 2>/dev/null || print_warning "无法获取版本信息"
print_info "检查数据库列表..."
docker exec $CONTAINER_NAME mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e "SHOW DATABASES;" 2>/dev/null || print_warning "无法获取数据库列表"
# 部署完成
print_step "部署完成!"
echo ""
echo -e "${GREEN}✓ MySQL 容器已成功部署并运行${NC}"
echo ""
echo "============================================"
echo "容器信息:"
echo " - 容器名称: $CONTAINER_NAME"
echo " - MySQL 端口: $MYSQL_PORT"
echo " - Root 密码: $MYSQL_ROOT_PASSWORD"
echo ""
echo "连接方式:"
echo " mysql -h 127.0.0.1 -P $MYSQL_PORT -uroot -p'$MYSQL_ROOT_PASSWORD'"
echo ""
echo "JDBC URL:"
echo " jdbc:mysql://localhost:$MYSQL_PORT/your_database?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai"
echo ""
echo "常用命令:"
echo " - 查看日志: $DOCKER_COMPOSE_CMD -f $COMPOSE_FILE logs -f"
echo " - 停止容器: $DOCKER_COMPOSE_CMD -f $COMPOSE_FILE stop"
echo " - 启动容器: $DOCKER_COMPOSE_CMD -f $COMPOSE_FILE start"
echo " - 重启容器: $DOCKER_COMPOSE_CMD -f $COMPOSE_FILE restart"
echo " - 删除容器: $DOCKER_COMPOSE_CMD -f $COMPOSE_FILE down"
echo " - 进入容器: docker exec -it $CONTAINER_NAME bash"
echo " - 进入MySQL: docker exec -it $CONTAINER_NAME mysql -uroot -p'$MYSQL_ROOT_PASSWORD'"
echo "============================================"
echo ""
print_success "部署脚本执行完毕!"
}
# 捕获错误
trap 'print_error "部署过程中发生错误,请检查日志"; exit 1' ERR
# 执行主程序
main "$@"
以上三个文件都创建好之后,在mysql目录下执行下方代码
# 授权
chmod +x mysql-deploy.sh
# 执行
./mysql-deploy.sh
Redis安装
# Docker Compose 文件 - Redis 配置
# 定义服务列表
services:
# 服务名称
redis:
# 使用的 Docker 镜像
image: redis:7.4
# 容器名称,启动后的容器会叫这个名字
container_name: redis7.4
# 容器重启策略
# always: 无论容器因何种原因停止,都会自动重启
restart: always
# 环境变量配置
environment:
# 设置容器时区为上海时区(东八区)
TZ: Asia/Shanghai
# 端口映射配置
# 格式: "宿主机端口:容器端口"
ports:
- "16379:6379"
# - 宿主机端口: 16379
# - 容器端口: 6379
# - 外部需要通过 localhost:16379 来访问 Redis
# - 容器内部 Redis 仍然运行在 6379 端口
# 数据卷挂载配置
volumes:
# 持久化数据存储
# redis-data 是命名卷,存储 Redis 的 RDB/AOF 持久化文件
# 即使容器删除,数据也不会丢失
- ./redis-data:/data
# 自定义配置文件
# 宿主机的 ./conf/redis.conf 映射到容器的 /etc/redis/redis.conf
- ./conf/redis.conf:/etc/redis/redis.conf
# Redis 启动命令
# 使用自定义配置文件启动 Redis
command: redis-server /etc/redis/redis.conf
# 健康检查配置
healthcheck:
test: ["CMD", "redis-cli", "-a", "A9@mK2", "ping"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10s
# 定义数据卷
volumes:
# 命名数据卷,用于持久化 Redis 数据
redis-data:
# 使用本地存储驱动
# 数据实际存储在 Docker 的数据目录中
driver: local
# Redis 配置文件
# ================================ 网络配置 ================================
# 绑定地址,0.0.0.0 表示接受所有网络接口的连接
bind 0.0.0.0
# 端口号
port 6379
# 关闭保护模式(配合密码使用)
protected-mode no
# TCP 连接队列长度
tcp-backlog 511
# 客户端空闲超时时间(0 表示不超时)
timeout 0
# TCP keepalive 心跳间隔
tcp-keepalive 300
# ================================ 通用配置 ================================
# 以守护进程方式运行(Docker 中设为 no)
daemonize no
# 日志级别: debug, verbose, notice, warning
loglevel notice
# 日志文件路径(空字符串表示输出到标准输出)
logfile ""
# 数据库数量
databases 16
# ================================ 安全配置 ================================
# 设置密码(重要!生产环境必须设置)
requirepass A9@mK2
# ================================ 内存管理 ================================
# 最大内存限制(根据服务器配置调整)
# maxmemory 256mb
# 内存淘汰策略
# volatile-lru: 从设置了过期时间的 key 中使用 LRU 算法淘汰
# allkeys-lru: 从所有 key 中使用 LRU 算法淘汰
# volatile-random: 从设置了过期时间的 key 中随机淘汰
# allkeys-random: 从所有 key 中随机淘汰
# volatile-ttl: 从设置了过期时间的 key 中淘汰 TTL 最小的
# noeviction: 不淘汰,内存满时返回错误
maxmemory-policy allkeys-lru
# ================================ 持久化配置 - RDB ================================
# RDB 快照保存规则
# save <seconds> <changes>
# 900 秒内至少 1 个 key 变化则保存
save 900 1
# 300 秒内至少 10 个 key 变化则保存
save 300 10
# 60 秒内至少 10000 个 key 变化则保存
save 60 10000
# RDB 文件名
dbfilename dump.rdb
# 数据目录
dir /data
# RDB 保存失败时是否停止写入
stop-writes-on-bgsave-error yes
# RDB 文件是否压缩
rdbcompression yes
# RDB 文件是否校验
rdbchecksum yes
# ================================ 持久化配置 - AOF ================================
# 是否开启 AOF 持久化
appendonly yes
# AOF 文件名
appendfilename "appendonly.aof"
# AOF 同步策略
# always: 每次写入都同步(最安全,最慢)
# everysec: 每秒同步一次(推荐)
# no: 由操作系统决定何时同步(最快,最不安全)
appendfsync everysec
# AOF 重写期间是否暂停同步
no-appendfsync-on-rewrite no
# AOF 文件增长比例触发重写
auto-aof-rewrite-percentage 100
# AOF 文件最小重写大小
auto-aof-rewrite-min-size 64mb
# ================================ 慢查询日志 ================================
# 慢查询时间阈值(微秒),超过此时间的命令会被记录
slowlog-log-slower-than 10000
# 慢查询日志最大长度
slowlog-max-len 128
# ================================ 客户端配置 ================================
# 最大客户端连接数
maxclients 10000
#!/bin/bash
################################################################################
# Redis Docker 自动化部署脚本
# 功能: 自动检查环境、部署 Redis 容器、执行验证测试
# 使用: ./deploy-redis.sh
################################################################################
set -e # 遇到错误立即退出
# 切换到脚本所在目录
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$SCRIPT_DIR"
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 配置信息
COMPOSE_FILE="docker-compose-redis.yml"
CONTAINER_NAME="redis7.4"
REDIS_PORT="16379"
REDIS_PASSWORD="A9@mK2"
# Docker Compose 命令(将自动检测)
DOCKER_COMPOSE_CMD=""
# 打印带颜色的消息
print_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
print_step() {
echo ""
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}$1${NC}"
echo -e "${BLUE}========================================${NC}"
}
# 执行 Docker Compose 命令
run_compose() {
$DOCKER_COMPOSE_CMD -f "$COMPOSE_FILE" "$@"
}
# 检查命令是否存在
check_command() {
if ! command -v $1 &> /dev/null; then
print_error "$1 未安装"
return 1
else
print_success "$1 已安装"
return 0
fi
}
# 检查端口是否被占用
check_port() {
if netstat -tlnp 2>/dev/null | grep -q ":$1 "; then
print_error "端口 $1 已被占用"
netstat -tlnp | grep ":$1 "
return 1
elif ss -tlnp 2>/dev/null | grep -q ":$1 "; then
print_error "端口 $1 已被占用"
ss -tlnp | grep ":$1 "
return 1
else
print_success "端口 $1 可用"
return 0
fi
}
# 检测 Docker Compose 命令
detect_docker_compose() {
print_info "检测 Docker Compose..."
if docker compose version &> /dev/null; then
DOCKER_COMPOSE_CMD="docker compose"
print_success "使用: docker compose (V2)"
docker compose version
return 0
elif command -v docker-compose &> /dev/null; then
if docker-compose version &> /dev/null; then
DOCKER_COMPOSE_CMD="docker-compose"
print_success "使用: docker-compose (V1)"
docker-compose version
return 0
else
print_error "docker-compose 存在版本兼容性问题"
return 1
fi
else
print_error "未找到 Docker Compose"
return 1
fi
}
# 主程序
main() {
print_step "Redis Docker 自动化部署脚本"
echo "工作目录: $SCRIPT_DIR"
echo "配置文件: $COMPOSE_FILE"
echo "容器名称: $CONTAINER_NAME"
echo "Redis 端口: $REDIS_PORT"
echo "部署时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo ""
# 步骤 1: 检查系统环境
print_step "步骤 1/6: 检查系统环境"
print_info "检查操作系统..."
if [ -f /etc/os-release ]; then
. /etc/os-release
print_success "操作系统: $NAME $VERSION"
else
print_warning "无法识别操作系统"
fi
print_info "检查系统架构..."
print_success "系统架构: $(uname -m)"
print_info "检查可用磁盘空间..."
DISK_AVAIL=$(df -h . | awk 'NR==2 {print $4}')
print_success "可用磁盘空间: $DISK_AVAIL"
# 步骤 2: 检查 Docker 环境
print_step "步骤 2/6: 检查 Docker 环境"
print_info "检查 Docker..."
if ! check_command docker; then
print_error "请先安装 Docker"
print_info "安装命令: curl -fsSL https://get.docker.com | bash"
exit 1
fi
docker --version
print_info "检查 Docker 服务状态..."
if ! systemctl is-active --quiet docker 2>/dev/null && ! docker info &> /dev/null; then
print_error "Docker 服务未运行"
print_info "启动命令: systemctl start docker"
exit 1
fi
print_success "Docker 服务运行正常"
if ! detect_docker_compose; then
exit 1
fi
# 步骤 3: 检查部署文件
print_step "步骤 3/6: 检查部署文件"
print_info "检查当前目录..."
pwd
ls -la
print_info "检查 Docker Compose 配置文件..."
if [ ! -f "$COMPOSE_FILE" ]; then
print_error "找不到 $COMPOSE_FILE 文件"
exit 1
fi
print_success "找到 $COMPOSE_FILE"
print_info "检查 Redis 配置文件..."
if [ ! -f "conf/redis.conf" ]; then
print_warning "找不到配置文件 conf/redis.conf"
print_info "将创建默认配置文件..."
mkdir -p conf
create_default_config
print_success "已创建默认配置文件"
else
print_success "找到配置文件 conf/redis.conf"
fi
print_info "验证 Docker Compose 配置..."
if run_compose config > /dev/null 2>&1; then
print_success "配置文件语法正确"
else
print_error "配置文件语法错误"
run_compose config
exit 1
fi
# 步骤 4: 检查端口和容器状态
print_step "步骤 4/6: 检查端口和容器状态"
print_info "检查端口 $REDIS_PORT 是否被占用..."
check_port $REDIS_PORT || print_warning "端口可能被占用,继续部署可能会失败"
print_info "检查是否存在同名容器..."
if docker ps -a | grep -q "$CONTAINER_NAME"; then
print_warning "容器 $CONTAINER_NAME 已存在"
read -p "是否删除并重新创建?[y/N] " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
print_info "停止并删除现有容器..."
run_compose down -v
print_success "已删除现有容器"
else
print_info "保留现有容器,尝试启动..."
fi
fi
# 步骤 5: 拉取镜像并启动
print_step "步骤 5/6: 拉取镜像并启动容器"
print_info "拉取 Redis 镜像..."
print_warning "首次拉取可能需要几分钟,请耐心等待..."
if run_compose pull; then
print_success "镜像拉取成功"
else
print_error "镜像拉取失败"
exit 1
fi
print_info "启动容器(后台运行)..."
if run_compose up -d; then
print_success "容器启动命令执行成功"
else
print_error "容器启动失败"
print_info "查看日志: run_compose logs"
exit 1
fi
print_info "等待 Redis 服务就绪(最多等待 30 秒)..."
WAIT_TIME=0
MAX_WAIT=30
while [ $WAIT_TIME -lt $MAX_WAIT ]; do
if docker exec $CONTAINER_NAME redis-cli -a "$REDIS_PASSWORD" ping 2>/dev/null | grep -q "PONG"; then
echo ""
print_success "Redis 服务已就绪"
break
fi
echo -n "."
sleep 2
WAIT_TIME=$((WAIT_TIME + 2))
done
if [ $WAIT_TIME -ge $MAX_WAIT ]; then
echo ""
print_error "Redis 服务启动超时"
print_info "查看日志:"
run_compose logs --tail=50
exit 1
fi
# 步骤 6: 验证部署
print_step "步骤 6/6: 验证部署"
print_info "检查容器状态..."
run_compose ps
print_info "检查 Redis 版本..."
docker exec $CONTAINER_NAME redis-cli -a "$REDIS_PASSWORD" INFO server 2>/dev/null | grep redis_version || print_warning "无法获取版本信息"
print_info "测试 Redis 读写..."
docker exec $CONTAINER_NAME redis-cli -a "$REDIS_PASSWORD" SET test_key "Hello Redis" 2>/dev/null
TEST_VALUE=$(docker exec $CONTAINER_NAME redis-cli -a "$REDIS_PASSWORD" GET test_key 2>/dev/null)
if [ "$TEST_VALUE" = "Hello Redis" ]; then
print_success "Redis 读写测试通过"
docker exec $CONTAINER_NAME redis-cli -a "$REDIS_PASSWORD" DEL test_key 2>/dev/null
else
print_warning "Redis 读写测试失败"
fi
print_info "检查 Redis 内存使用..."
docker exec $CONTAINER_NAME redis-cli -a "$REDIS_PASSWORD" INFO memory 2>/dev/null | grep used_memory_human || true
# 部署完成
print_step "部署完成!"
echo ""
echo -e "${GREEN}✓ Redis 容器已成功部署并运行${NC}"
echo ""
echo "============================================"
echo "容器信息:"
echo " - 容器名称: $CONTAINER_NAME"
echo " - Redis 端口: $REDIS_PORT"
echo " - 密码: $REDIS_PASSWORD"
echo ""
echo "连接方式:"
echo " redis-cli -h 127.0.0.1 -p $REDIS_PORT -a '$REDIS_PASSWORD'"
echo ""
echo "Docker 连接:"
echo " docker exec -it $CONTAINER_NAME redis-cli -a '$REDIS_PASSWORD'"
echo ""
echo "Spring Boot 配置:"
echo " spring:"
echo " redis:"
echo " host: localhost"
echo " port: $REDIS_PORT"
echo " password: $REDIS_PASSWORD"
echo " database: 0"
echo ""
echo "常用命令:"
echo " - 查看日志: $DOCKER_COMPOSE_CMD -f $COMPOSE_FILE logs -f"
echo " - 停止容器: $DOCKER_COMPOSE_CMD -f $COMPOSE_FILE stop"
echo " - 启动容器: $DOCKER_COMPOSE_CMD -f $COMPOSE_FILE start"
echo " - 重启容器: $DOCKER_COMPOSE_CMD -f $COMPOSE_FILE restart"
echo " - 删除容器: $DOCKER_COMPOSE_CMD -f $COMPOSE_FILE down"
echo " - 进入容器: docker exec -it $CONTAINER_NAME bash"
echo " - 进入Redis: docker exec -it $CONTAINER_NAME redis-cli -a '$REDIS_PASSWORD'"
echo "============================================"
echo ""
print_success "部署脚本执行完毕!"
}
# 捕获错误
trap 'print_error "部署过程中发生错误,请检查日志"; exit 1' ERR
# 执行主程序
main "$@"
以上三个文件都创建好之后,在redis目录下执行下方代码
# 授权
chmod +x redis-deploy.sh
# 执行
./redis-deploy.sh
Nginx安装
# Docker Compose 文件版本
version: '3.8'
# ============================================================
# 服务定义
# ============================================================
services:
# ----------------------------------------------------------
# Nginx 服务
# ----------------------------------------------------------
nginx:
# 使用 Nginx 官方稳定版镜像
image: nginx:1.24
# 容器名称
container_name: nginx1.24
# 重启策略
# - no: 不自动重启(默认)
# - always: 总是自动重启
# - on-failure: 仅在异常退出时重启
# - unless-stopped: 除非手动停止,否则自动重启
restart: always
# ----------------------------------------------------------
# 环境变量
# ----------------------------------------------------------
environment:
TZ: Asia/Shanghai
# 容器内访问宿主机
extra_hosts:
- "host.docker.internal:host-gateway"
# ----------------------------------------------------------
# 端口映射
# 格式: "宿主机端口:容器内端口"
# ----------------------------------------------------------
ports:
# ========== 项目端口配置 ==========
# 项目1: notify(前端 7777)
#- "7777:7777"
# 项目2: xxx(前端 80)
- "80:80"
# ----------------------------------------------------------
# 数据卷挂载
# ----------------------------------------------------------
volumes:
# Nginx 配置目录
- ./conf.d:/etc/nginx/conf.d:ro
# ========== 项目前端目录 ==========
# 项目1: notify
- ./html-notify:/usr/share/nginx/html-notify:ro
# 项目2: xxx
# - ./html-project2:/usr/share/nginx/html-project2:ro
# 日志目录
- ./logs:/var/log/nginx
# ----------------------------------------------------------
# 健康检查
# ----------------------------------------------------------
healthcheck:
test: ["CMD-SHELL", "nginx -t || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
# ============================================================
# 数据卷定义
# ============================================================
volumes:
nginx-logs:
driver: local
# ============================================================
# 项目1: notify
# 前端端口: 7777
# 后端端口: 7878
# ============================================================
server {
listen 7777;
listen [::]:7777;
server_name localhost;
charset utf-8;
# 网站根目录
root /usr/share/nginx/html-notify;
# Gzip 压缩配置
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml
application/rss+xml application/atom+xml image/svg+xml;
# 静态资源(直接返回文件)
location /static/ {
expires 7d;
add_header Cache-Control "public, immutable";
}
# 前端路由(SPA 支持)
location / {
try_files $uri $uri/ /index.html;
index index.html index.htm;
# 添加这几行,防止 HTML 被缓存
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
# 后端 API 代理
location /prod-api/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://host.docker.internal:7878/;
}
# SpringDoc API 文档代理
location ~ ^/v3/api-docs/(.*) {
proxy_pass http://host.docker.internal:7878/v3/api-docs/$1;
}
# 错误页面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html-notify;
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
}
}
#!/bin/bash
################################################################################
# Nginx Docker 自动化部署脚本
# 功能: 自动检查环境、部署 Nginx 容器、执行验证测试
# 使用: ./nginx-deploy.sh
################################################################################
set -e # 遇到错误立即退出
# 切换到脚本所在目录
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$SCRIPT_DIR"
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# ============================================================
# 配置信息(根据需要修改)
# ============================================================
COMPOSE_FILE="docker-compose-nginx.yml"
CONTAINER_NAME="nginx1.24"
# 项目端口配置(添加新项目时在这里添加端口)
FRONTEND_PORTS=(80) # 前端端口列表
PROJECT_NAMES=("wms") # 项目名称列表
PROJECT_DIRS=("html-wms") # 前端目录列表
# Docker Compose 命令(将自动检测)
DOCKER_COMPOSE_CMD=""
# ============================================================
# 工具函数
# ============================================================
# 打印带颜色的消息
print_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
print_step() {
echo ""
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}$1${NC}"
echo -e "${BLUE}========================================${NC}"
}
# 执行 Docker Compose 命令
run_compose() {
$DOCKER_COMPOSE_CMD -f "$COMPOSE_FILE" "$@"
}
# 检查命令是否存在
check_command() {
if ! command -v $1 &> /dev/null; then
print_error "$1 未安装"
return 1
else
print_success "$1 已安装"
return 0
fi
}
# 检查端口是否被占用
check_port() {
local port=$1
if command -v netstat &> /dev/null; then
if netstat -tlnp 2>/dev/null | grep -q ":$port "; then
return 1
fi
elif command -v ss &> /dev/null; then
if ss -tlnp 2>/dev/null | grep -q ":$port "; then
return 1
fi
fi
return 0
}
# 检测 Docker Compose 命令
detect_docker_compose() {
print_info "检测 Docker Compose..."
if docker compose version &> /dev/null; then
DOCKER_COMPOSE_CMD="docker compose"
print_success "使用: docker compose (V2)"
docker compose version
return 0
elif command -v docker-compose &> /dev/null; then
if docker-compose version &> /dev/null; then
DOCKER_COMPOSE_CMD="docker-compose"
print_success "使用: docker-compose (V1)"
docker-compose version
return 0
else
print_error "docker-compose 存在版本兼容性问题"
return 1
fi
else
print_error "未找到 Docker Compose"
return 1
fi
}
# 创建目录结构
create_directories() {
print_info "检查并创建目录结构..."
# 创建配置目录
if [ ! -d "conf.d" ]; then
mkdir -p conf.d
print_success "创建目录: conf.d"
else
print_info "目录已存在: conf.d"
fi
# 创建日志目录
if [ ! -d "logs" ]; then
mkdir -p logs
chmod 777 logs
print_success "创建目录: logs"
else
print_info "目录已存在: logs"
fi
# 创建各项目前端目录
for dir in "${PROJECT_DIRS[@]}"; do
if [ ! -d "$dir" ]; then
mkdir -p "$dir"
print_success "创建目录: $dir"
else
print_info "目录已存在: $dir"
fi
done
}
# 检查配置文件
check_config_files() {
print_info "检查 Nginx 配置文件..."
local missing_configs=()
for i in "${!PROJECT_NAMES[@]}"; do
local config_file="conf.d/${PROJECT_NAMES[$i]}.conf"
if [ ! -f "$config_file" ]; then
missing_configs+=("$config_file")
print_warning "缺少配置文件: $config_file"
else
print_success "找到配置文件: $config_file"
fi
done
if [ ${#missing_configs[@]} -gt 0 ]; then
print_warning "部分配置文件缺失,请确保已创建所需的 .conf 文件"
read -p "是否继续部署?[y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_info "部署已取消"
exit 0
fi
fi
}
# 检查前端文件
check_frontend_files() {
print_info "检查前端静态文件..."
for i in "${!PROJECT_DIRS[@]}"; do
local dir="${PROJECT_DIRS[$i]}"
local project="${PROJECT_NAMES[$i]}"
if [ -f "$dir/index.html" ]; then
print_success "项目 $project: 找到 index.html"
else
print_warning "项目 $project: 未找到 index.html(目录 $dir 为空或缺少文件)"
fi
done
}
# ============================================================
# 主程序
# ============================================================
main() {
print_step "Nginx Docker 自动化部署脚本"
echo "工作目录: $SCRIPT_DIR"
echo "配置文件: $COMPOSE_FILE"
echo "容器名称: $CONTAINER_NAME"
echo "部署时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo ""
echo "项目列表:"
for i in "${!PROJECT_NAMES[@]}"; do
echo " - ${PROJECT_NAMES[$i]}: 前端端口 ${FRONTEND_PORTS[$i]}, 目录 ${PROJECT_DIRS[$i]}"
done
echo ""
# ========================================
# 步骤 1: 检查系统环境
# ========================================
print_step "步骤 1/7: 检查系统环境"
print_info "检查操作系统..."
if [ -f /etc/os-release ]; then
. /etc/os-release
print_success "操作系统: $NAME $VERSION"
else
print_warning "无法识别操作系统"
fi
print_info "检查系统架构..."
print_success "系统架构: $(uname -m)"
print_info "检查可用磁盘空间..."
DISK_AVAIL=$(df -h . | awk 'NR==2 {print $4}')
print_success "可用磁盘空间: $DISK_AVAIL"
# ========================================
# 步骤 2: 检查 Docker 环境
# ========================================
print_step "步骤 2/7: 检查 Docker 环境"
print_info "检查 Docker..."
if ! check_command docker; then
print_error "请先安装 Docker"
print_info "安装命令: curl -fsSL https://get.docker.com | bash"
exit 1
fi
docker --version
print_info "检查 Docker 服务状态..."
if ! systemctl is-active --quiet docker 2>/dev/null && ! docker info &> /dev/null; then
print_error "Docker 服务未运行"
print_info "启动命令: systemctl start docker"
exit 1
fi
print_success "Docker 服务运行正常"
if ! detect_docker_compose; then
exit 1
fi
# ========================================
# 步骤 3: 创建目录结构
# ========================================
print_step "步骤 3/7: 创建目录结构"
create_directories
print_info "当前目录结构:"
ls -la
# ========================================
# 步骤 4: 检查部署文件
# ========================================
print_step "步骤 4/7: 检查部署文件"
print_info "检查 Docker Compose 配置文件..."
if [ ! -f "$COMPOSE_FILE" ]; then
print_error "找不到 $COMPOSE_FILE 文件"
exit 1
fi
print_success "找到 $COMPOSE_FILE"
check_config_files
check_frontend_files
print_info "验证 Docker Compose 配置..."
if run_compose config > /dev/null 2>&1; then
print_success "配置文件语法正确"
else
print_error "配置文件语法错误"
run_compose config
exit 1
fi
# ========================================
# 步骤 5: 检查端口和容器状态
# ========================================
print_step "步骤 5/7: 检查端口和容器状态"
print_info "检查端口占用情况..."
PORT_CONFLICT=false
for port in "${FRONTEND_PORTS[@]}"; do
if check_port $port; then
print_success "端口 $port 可用"
else
print_warning "端口 $port 已被占用"
PORT_CONFLICT=true
fi
done
if [ "$PORT_CONFLICT" = true ]; then
print_warning "存在端口冲突,继续部署可能会失败"
read -p "是否继续?[y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_info "部署已取消"
exit 0
fi
fi
print_info "检查是否存在同名容器..."
if docker ps -a | grep -q "$CONTAINER_NAME"; then
print_warning "容器 $CONTAINER_NAME 已存在"
read -p "是否停止并重新创建?[y/N] " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
print_info "停止并删除现有容器..."
run_compose down
print_success "已删除现有容器"
else
print_info "保留现有容器,尝试启动..."
fi
fi
# ========================================
# 步骤 6: 拉取镜像并启动
# ========================================
print_step "步骤 6/7: 拉取镜像并启动容器"
print_info "拉取 Nginx 镜像..."
if run_compose pull; then
print_success "镜像拉取成功"
else
print_error "镜像拉取失败"
exit 1
fi
print_info "启动容器(后台运行)..."
if run_compose up -d; then
print_success "容器启动命令执行成功"
else
print_error "容器启动失败"
print_info "查看日志: run_compose logs"
exit 1
fi
print_info "等待 Nginx 服务就绪(最多等待 30 秒)..."
WAIT_TIME=0
MAX_WAIT=30
while [ $WAIT_TIME -lt $MAX_WAIT ]; do
if docker exec $CONTAINER_NAME nginx -t &> /dev/null; then
echo ""
print_success "Nginx 服务已就绪"
break
fi
echo -n "."
sleep 2
WAIT_TIME=$((WAIT_TIME + 2))
done
if [ $WAIT_TIME -ge $MAX_WAIT ]; then
echo ""
print_error "Nginx 服务启动超时"
print_info "查看日志:"
run_compose logs --tail=50
exit 1
fi
# ========================================
# 步骤 7: 验证部署
# ========================================
print_step "步骤 7/7: 验证部署"
print_info "检查容器状态..."
run_compose ps
print_info "检查 Nginx 版本..."
docker exec $CONTAINER_NAME nginx -v
print_info "验证 Nginx 配置..."
docker exec $CONTAINER_NAME nginx -t
print_info "测试各项目访问..."
for i in "${!PROJECT_NAMES[@]}"; do
local port="${FRONTEND_PORTS[$i]}"
local project="${PROJECT_NAMES[$i]}"
if curl -s -o /dev/null -w "%{http_code}" "http://localhost:$port" | grep -q "200\|304"; then
print_success "项目 $project (端口 $port): 访问正常"
else
print_warning "项目 $project (端口 $port): 无法访问(可能缺少前端文件)"
fi
done
# ========================================
# 部署完成
# ========================================
print_step "部署完成!"
echo ""
echo -e "${GREEN}✓ Nginx 容器已成功部署并运行${NC}"
echo ""
echo "============================================"
echo "容器信息:"
echo " - 容器名称: $CONTAINER_NAME"
echo " - 镜像版本: nginx:1.24"
echo ""
echo "项目访问地址:"
for i in "${!PROJECT_NAMES[@]}"; do
echo " - ${PROJECT_NAMES[$i]}: http://localhost:${FRONTEND_PORTS[$i]}"
done
echo ""
echo "常用命令:"
echo " - 查看日志: $DOCKER_COMPOSE_CMD -f $COMPOSE_FILE logs -f"
echo " - 重载配置: docker exec $CONTAINER_NAME nginx -s reload"
echo " - 测试配置: docker exec $CONTAINER_NAME nginx -t"
echo " - 停止容器: $DOCKER_COMPOSE_CMD -f $COMPOSE_FILE stop"
echo " - 启动容器: $DOCKER_COMPOSE_CMD -f $COMPOSE_FILE start"
echo " - 重启容器: $DOCKER_COMPOSE_CMD -f $COMPOSE_FILE restart"
echo " - 删除容器: $DOCKER_COMPOSE_CMD -f $COMPOSE_FILE down"
echo " - 进入容器: docker exec -it $CONTAINER_NAME bash"
echo ""
echo "新增项目步骤:"
echo " 1. 在 conf.d/ 下新增 xxx.conf 配置文件"
echo " 2. 在 docker-compose-nginx.yml 中添加端口和目录挂载"
echo " 3. 创建前端目录并放入打包文件"
echo " 4. 执行: docker exec $CONTAINER_NAME nginx -s reload"
echo "============================================"
echo ""
print_success "部署脚本执行完毕!"
}
# 捕获错误
trap 'print_error "部署过程中发生错误,请检查日志"; exit 1' ERR
# 执行主程序
main "$@"
以上三个文件都创建好之后,在redis目录下执行下方代码
# 授权
chmod +x nginx-deploy.sh
# 执行
./nginx-deploy.sh
JDK安装
# 下载 Java8 rpm 包
wget https://corretto.aws/downloads/latest/amazon-corretto-8-x64-linux-jdk.rpm
# 安装
rpm -ivh amazon-corretto-8-x64-linux-jdk.rpm
# 检查是否安装成功
rpm -qa | grep corretto
# 查看安装目录
ls /usr/lib/jvm/ | grep corretto
# 切换系统默认 Java 版本(选择 corretto8 对应的编号)
alternatives --config java
# 验证 Java 版本
java -version
Powered by Waline v2.15.8
