Docker Compose 紧急救援:凌晨3点服务器报警的解决方案

Docker Compose 紧急救援:凌晨3点服务器报警的解决方案

凌晨3点,你还躺在床上,手机突然响了。是服务器报警短信,提示网站因 MySQL 服务异常而无法访问。你迅速爬起来,打开笔记本,心想如果能快速恢复服务,该多好。这时,你记起 Docker Compose 是处理这种情况的理想工具,因为可以轻松地重新部署整个应用栈。

想象一下,如果每次服务出现问题,都需要手动启动每个容器,检查日志,处理异常,不仅耗时,还容易出错。Docker Compose 通过一个 docker-compose.yml 文件,可以一口气管理多个 Docker 容器,让应用的部署和恢复变得简单、高效。今天,我们就从这个深夜报警的场景开始,一起看看如何使用 Docker Compose 解决问题。

场景设定

你的网站由两个主要部分组成:一个基于 Node.js 的 Web 应用,和一个 MySQL 数据库。两个部分分别运行在不同的 Docker 容器中。在 docker-compose.yml 文件的帮助下,可以快速启动、停止和重启整个应用栈,而无需分别管理每个容器。

准备 docker-compose.yml 文件

在一个平静的白天,你需要先准备好 docker-compose.yml 文件,确保在紧急情况时可以立即使用。假设你的项目目录结构如下:

csharp 复制代码
myapp/
├── docker-compose.yml
├── web/
│   └── Dockerfile
└── db/
    └── init.sql

docker-compose.yml 文件内容如下:

yaml 复制代码
version: '3.8'  # 指定 compose 文件版本
services:       # 定义服务
  web:          # Web 应用服务
    build: ./web  # 指定构建目录
    ports:      # 映射端口
      - "4000:3000"  # 将主机的 4000 端口映射到容器的 3000 端口
    depends_on:  # 依赖的服务
      - db       # 依赖 db 服务
    environment:  # 环境变量
      MYSQL_HOST: db  # 指定 MySQL 主机名
      MYSQL_USER: root
      MYSQL_PASSWORD: example
      MYSQL_DATABASE: appdb
  db:           # 数据库服务
    image: mysql:5.7  # 使用官方的 MySQL 镜像
    volumes:     # 挂载卷
      - db_data:/var/lib/mysql  # 持久化数据
      - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql  # 初始化数据库脚本
    environment:  # 环境变量
      MYSQL_ROOT_PASSWORD: example  # 设置 root 用户的密码
      MYSQL_DATABASE: appdb        # 创建数据库

volumes:  # 定义卷
  db_data:  # 数据卷名称

构建和启动应用

在白天,你可以构建和启动你的应用,确保一切正常。打开终端,进入项目目录,运行以下命令:

bash 复制代码
docker-compose up --build  # 构建并启动所有服务

这条命令会先构建 web 服务的 Docker 镜像,然后启动 webdb 服务。--build 选项表示强制重新构建镜像,确保最新代码被使用。

检查服务状态

启动服务后,可以使用以下命令检查服务状态:

bash 复制代码
docker-compose ps  # 查看所有服务的运行状态

如果一切正常,你会看到 webdb 服务都在运行中。如果有问题,可以通过 docker-compose logs 查看日志,定位问题:

bash 复制代码
docker-compose logs  # 查看所有服务的日志
docker-compose logs web  # 仅查看 web 服务的日志

服务异常处理

回到那个不眠之夜,你发现 MySQL 服务崩溃了。这个问题可能是因为磁盘空间不足、配置错误或其他原因。使用 Docker Compose,你可以迅速停止并重启数据库服务,而无需重新启动整个应用:

bash 复制代码
docker-compose stop db  # 停止 db 服务
docker-compose start db  # 启动 db 服务

如果重启服务后问题依然存在,可以尝试重新构建数据库服务:

bash 复制代码
docker-compose up --build db  # 重新构建并启动 db 服务

数据库初始化

假设你新添加了一张表,需要重新初始化数据库。你可以通过修改 init.sql 文件,然后重新启动数据库服务来实现:

sql 复制代码
-- db/init.sql
CREATE DATABASE appdb;
USE appdb;

CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  email VARCHAR(255) NOT NULL UNIQUE
);

INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');
INSERT INTO users (name, email) VALUES ('Bob', 'bob@example.com');

保存文件后,重新启动数据库服务:

bash 复制代码
docker-compose up --build db  # 重新构建并启动 db 服务

这次启动时,Docker 会执行 init.sql 文件中的 SQL 命令,完成数据库的初始化。

持久化数据

为了避免数据库数据丢失,Docker Compose 使用卷来持久化数据。在 docker-compose.yml 文件中,我们定义了一个名为 db_data 的卷,并将其挂载到 MySQL 容器的数据目录。这样,即使容器被删除,数据依然保留。

环境变量管理

docker-compose.yml 文件中,我们通过 environment 部分设置了环境变量。这些环境变量可以在应用中使用,例如在 Node.js 应用中,可以通过 process.env.MYSQL_HOST 获取 MySQL 服务的主机名。

网络配置

默认情况下,Docker Compose 会为每个项目创建一个默认网络,所有服务都在这个网络中通信。你也可以自定义网络,例如:

yaml 复制代码
version: '3.8'
services:
  web:
    build: ./web
    ports:
      - "4000:3000"
    depends_on:
      - db
    environment:
      MYSQL_HOST: db
      MYSQL_USER: root
      MYSQL_PASSWORD: example
      MYSQL_DATABASE: appdb
    networks:  # 指定网络
      - appnet  # 使用 appnet 网络

  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
      - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
    environment:
      MYSQL_ROOT_PASSWORD: example
      MYSQL_DATABASE: appdb
    networks:
      - appnet

networks:
  appnet:  # 定义 appnet 网络

通过自定义网络,你可以更好地控制服务之间的通信。

高级用法:服务扩展

假设你的 Web 应用需要扩展,以应对突然增加的流量。Docker Compose 支持服务扩展,你只需要在 docker-compose.yml 文件中添加 deploy 部分:

yaml 复制代码
version: '3.8'
services:
  web:
    build: ./web
    ports:
      - "4000:3000"
    depends_on:
      - db
    environment:
      MYSQL_HOST: db
      MYSQL_USER: root
      MYSQL_PASSWORD: example
      MYSQL_DATABASE: appdb
    networks:
      - appnet
    deploy:  # 部署配置
      replicas: 3  # 设置副本数量
      restart_policy:  # 重启策略
        condition: on-failure  # 只在失败时重启

  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
      - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
    environment:
      MYSQL_ROOT_PASSWORD: example
      MYSQL_DATABASE: appdb
    networks:
      - appnet

networks:
  appnet:

volumes:
  db_data:

使用 docker-compose up --scale web=3 命令可以启动 3 个 web 服务的副本,实现负载均衡。

服务配置更新

假设你发现 Web 应用的端口需要从 3000 改为 8080。只需修改 docker-compose.yml 文件中的 ports 部分,然后重启服务:

yaml 复制代码
version: '3.8'
services:
  web:
    build: ./web
    ports:
      - "4000:8080"  # 修改端口映射
    depends_on:
      - db
    environment:
      MYSQL_HOST: db
      MYSQL_USER: root
      MYSQL_PASSWORD: example
      MYSQL_DATABASE: appdb
    networks:
      - appnet

  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
      - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
    environment:
      MYSQL_ROOT_PASSWORD: example
      MYSQL_DATABASE: appdb
    networks:
      - appnet

networks:
  appnet:

volumes:
  db_data:

保存文件后,运行以下命令更新服务配置:

bash 复制代码
docker-compose up --force-recreate  # 强制重新创建并启动所有服务

定时任务

有时候,你可能需要定期执行一些维护任务,例如备份数据库。Docker Compose 本身不提供定时任务功能,但你可以使用一个定时任务容器来实现。创建一个新的 backup 服务,并使用 Cron 表达式来定义任务调度:

yaml 复制代码
version: '3.8'
services:
  web:
    build: ./web
    ports:
      - "4000:8080"
    depends_on:
      - db
    environment:
      MYSQL_HOST: db
      MYSQL_USER: root
      MYSQL_PASSWORD: example
      MYSQL_DATABASE: appdb
    networks:
      - appnet

  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
      - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
    environment:
      MYSQL_ROOT_PASSWORD: example
      MYSQL_DATABASE: appdb
    networks:
      - appnet

  backup:
    image: alpine:latest
    volumes:
      - ./backup:/backup  # 挂载备份脚本
    command: sh -c "crond && tail -f /dev/null"  # 启动 Cron 守护进程
    environment:
      CRON_SCHEDULE: "0 2 * * *"  # 每天凌晨2点执行
      BACKUP_COMMAND: "mysqldump -h db -u root -pexample appdb > /backup/appdb.sql"  # 备份命令
    networks:
      - appnet

networks:
  appnet:

volumes:
  db_data:

在这个例子中,backup 服务使用 Alpine 镜像,挂载了一个备份脚本目录,并通过环境变量 CRON_SCHEDULEBACKUP_COMMAND 来定义定时任务和备份命令。你可以在 ./backup 目录中创建一个 crontab 文件来配置定时任务:

bash 复制代码
# ./backup/crontab
0 2 * * * mysqldump -h db -u root -pexample appdb > /backup/appdb.sql  # 每天凌晨2点备份数据库

然后运行以下命令启动所有服务:

bash 复制代码
docker-compose up --build  # 构建并启动所有服务

常用命令汇总

为了方便你在紧急情况下快速操作,这里列出一些常用的 Docker Compose 命令:

  • docker-compose up --build:构建并启动所有服务
  • docker-compose ps:查看服务状态
  • docker-compose logs [service]:查看服务日志
  • docker-compose stop [service]:停止指定服务
  • docker-compose start [service]:启动指定服务
  • docker-compose up --force-recreate:强制重新创建并启动所有服务
  • docker-compose down:停止并删除所有服务及其网络和卷

自然推荐 Hey Cron

在处理定时任务时,如果你不熟悉 Cron 表达式或者需要生成复杂的定时任务,可以考虑使用 Hey Cron。Hey Cron 是一个免费在线工具网站,提供中文描述秒转 Cron 的功能,让你轻松生成 Cron 表达式。它还支持正则表达式生成器、中英互译、JSON 格式化、Base64 编码解码、时间戳转换和 JWT 解析等多种实用工具,非常适合开发者的日常使用。

现在,你可以回到床上,安心睡觉了。Docker Compose 和 Hey Cron 都已经准备好,下次再遇到这种紧急情况,你可以迅速解决问题,继续享受你的美梦。

相关推荐
weixin_382395239 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__9 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.10 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~11 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华11 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子14 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅14 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni14 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学15 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端