🚀 Ubuntu 部署 MySQL + Redis + Nginx + 自动备份 全流程指南

本指南专为 Ubuntu 系统设计,已整合所有环境配置、网络加速修复及错误处理方案。
操作方式:直接复制代码块中的命令到终端执行即可。


📋 阶段一:环境准备与 Docker 安装

此步骤确保系统拥有最新版的 Docker 和 Docker Compose。

1.1 更新系统并安装依赖

sudo apt update && sudo apt upgrade -y
sudo apt install -y curl gnupg lsb-release software-properties-common

1.2 安装 Docker (官方源)

# 添加 Docker 官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# 添加 Docker 稳定版仓库
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装 Docker Engine 和 Compose 插件
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

1.3 启动 Docker 并配置开机自启

sudo systemctl enable docker
sudo systemctl start docker
# 验证安装
docker --version && docker compose version

⚠️ 分支处理:如果提示权限不足
如果运行 docker 命令提示 permission denied,请将当前用户加入 docker 组:

sudo usermod -aG docker $USER
newgrp docker  # 立即生效,无需重启

🌐 阶段二:配置 Docker 镜像加速 (关键步骤)

解决国内服务器拉取镜像超时 (Client.Timeout) 的核心步骤。

2.1 配置加速器地址

注:此处使用通用公共加速地址。若失效,请替换为您阿里云/腾讯云的专属地址。

# 创建配置目录
sudo mkdir -p /etc/docker

# 写入加速器配置
sudo tee /etc/docker/daemon.json << 'EOF'
{
  "registry-mirrors": [
    "https://docker.m.daocloud.io",
    "https://huecker.io",
    "https://dockerhub.timeweb.cloud",
    "https://noohub.ru"
  ],
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  }
}
EOF

2.2 重启 Docker 服务

sudo systemctl daemon-reload
sudo systemctl restart docker

2.3 验证配置

docker info | grep -A 5 "Registry Mirrors"

✅ 成功标志:输出中包含上述配置的镜像地址。

⚠️ 分支处理:如果依然拉取失败

  1. 检查 DNS:编辑 /etc/resolv.conf,添加 nameserver 8.8.8.8
  2. 手动测试:运行 docker pull alpine:latest。如果这个都失败,说明服务器网络完全不通外网,需检查防火墙或安全组(放行 TCP 443)。
  3. 更换地址:登录阿里云控制台获取专属加速地址,替换步骤 2.1 中的 URL。

📂 阶段三:项目目录与文件构建

创建完整的目录结构、配置文件和脚本。

root/
└──database_nginx/
    ├── docker-compose.yaml
    ├── scripts/
    │   └── backuper.sh
    └── data/ (自动创建)
    └── backups/ (自动创建)

3.1 创建工作目录

mkdir -p ~/database_nginx && cd ~/database_nginx
mkdir -p scripts data/mysql data/redis data/nginx/html data/nginx/conf.d data/nginx/logs backups/mysql backups/redis

3.2 生成 docker-compose.yaml

密码已设定为 &pdnbplus.2002,格式已优化以防解析错误。

cat > docker-compose.yaml << 'EOF'
version: '3.8'

services:
  mysql:
    image: mysql:8.0
    container_name: mysql_8
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: '&pdnbplus.2002'
    ports:
      - "10082:3306"
    volumes:
      - ./data/mysql:/var/lib/mysql
      - ./backups/mysql:/backup
    command: --default-authentication-plugin=mysql_native_password
    networks:
      - app_net
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-p&pdnbplus.2002"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:8.0
    container_name: redis_8
    restart: always
    command: ["redis-server", "--requirepass", "&pdnbplus.2002", "--appendonly", "yes"]
    ports:
      - "10083:6379"
    volumes:
      - ./data/redis:/data
      - ./backups/redis:/backup
    networks:
      - app_net
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "&pdnbplus.2002", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  nginx:
    image: nginx:latest
    container_name: nginx_web
    restart: always
    ports:
      - "80:80"
    volumes:
      - ./data/nginx/html:/usr/share/nginx/html:ro
      - ./data/nginx/conf.d:/etc/nginx/conf.d:ro
      - ./data/nginx/logs:/var/log/nginx
    depends_on:
      - mysql
      - redis
    networks:
      - app_net

  backup-service:
    image: alpine:latest
    container_name: auto_backup
    restart: always
    entrypoint: ["/bin/sh", "-c"]
    command:
      - |
        apk add --no-cache mysql-client redis-tools bash cronie tar gzip
        echo '0 */4 * * * /usr/bin/backuper.sh' > /etc/crontabs/root
        crond -f -l 2
    volumes:
      - ./backups:/backups
      - ./scripts/backuper.sh:/usr/bin/backuper.sh:ro
      - ./data/mysql:/mysql_data:ro
      - ./data/redis:/redis_data:ro
    environment:
      MYSQL_HOST: mysql
      MYSQL_PORT: "3306"
      MYSQL_USER: root
      MYSQL_PASS: '&pdnbplus.2002'
      REDIS_HOST: redis
      REDIS_PORT: "6379"
      REDIS_PASS: '&pdnbplus.2002'
    networks:
      - app_net
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy

networks:
  app_net:
    driver: bridge
EOF

3.3 生成自动备份脚本

定时备份 (每4小时):

cat > scripts/backuper.sh << 'EOF'
#!/bin/bash
BACKUP_DIR="/backups"
DATE_STR=$(date +"%Y%m%d_%H%M%S")

echo "[$(date)] Starting MySQL Backup..."
if mysqldump -h"${MYSQL_HOST}" -P"${MYSQL_PORT}" -u"${MYSQL_USER}" -p"${MYSQL_PASS}" --all-databases | gzip > "${BACKUP_DIR}/mysql/full_backup_${DATE_STR}.sql.gz"; then
    echo "MySQL backup success."
    # 保留最近 5 个备份
    ls -t ${BACKUP_DIR}/mysql/*.sql.gz 2>/dev/null | tail -n +6 | xargs -r rm
else
    echo "MySQL backup failed."
fi

echo "[$(date)] Starting Redis File Backup..."
if [ -d "/redis_data" ] && [ "$(ls -A /redis_data 2>/dev/null)" ]; then
    if tar -czf "${BACKUP_DIR}/redis/redis_files_${DATE_STR}.tar.gz" -C /redis_data .; then
        echo "Redis backup success."
        ls -t ${BACKUP_DIR}/redis/*.tar.gz 2>/dev/null | tail -n +6 | xargs -r rm
    else
        echo "Redis backup failed."
    fi
else
    echo "Redis data directory empty or not found."
fi
EOF
chmod +x scripts/backuper.sh

⚠️ 分支处理:文件创建失败
如果提示 No such file,请检查是否执行了 3.1 中的 mkdir 命令,确保当前目录在 ~/database_nginx 下。


🏁 阶段四:启动与验证

最后一步,拉起所有服务。

4.1 启动服务

cd ~/database_nginx
docker compose up -d

4.2 查看运行状态

docker compose ps

✅ 成功标志:所有服务的 STATE 列显示 Up (healthy)Up

4.3 验证服务连通性

# 测试 MySQL (密码: &pdnbplus.2002)
docker exec mysql_8 mysqladmin ping -h localhost -u root -p'&pdnbplus.2002'

# 测试 Redis (密码: &pdnbplus.2002)
docker exec redis_8 redis-cli -a '&pdnbplus.2002' ping

# 测试 Nginx
curl -I http://localhost

⚠️ 分支处理:启动报错

  1. 端口冲突:如果提示 port already allocated,说明 80, 10082 或 10083 被占用。
    • 解决:sudo netstat -tulpn | grep <端口号> 找到占用进程并停止,或修改 docker-compose.yaml 中的端口映射。
  2. 健康检查失败:如果 MySQL/Redis 一直 restarting。
    • 查看日志:docker compose logs mysqldocker compose logs redis
    • 常见原因:磁盘空间不足 (df -h) 或 内存不足。

🛠️ 常用运维命令速查

操作 命令
查看实时日志 docker compose logs -f
查看特定服务日志 docker compose logs -f mysql
重启所有服务 docker compose restart
停止并删除容器 docker compose down
停止并删除容器+数据卷 docker compose down -v (危险操作,会删库)
进入 MySQL 命令行 docker exec -it mysql_8 mysql -u root -p'&pdnbplus.2002'
进入 Redis 命令行 docker exec -it redis_8 redis-cli -a '&pdnbplus.2002'
手动触发一次备份 docker exec auto_backup /usr/bin/backuper.sh

🎉 恭喜!您的数据库与 Web 服务集群已在 Ubuntu 上成功运行。
数据持久化在 ~/database_nginx/data,备份文件将自动生成在 ~/database_nginx/backups

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐