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 都已经准备好,下次再遇到这种紧急情况,你可以迅速解决问题,继续享受你的美梦。

相关推荐
石小石Orz2 小时前
星云SDK + 油猴:给LLM塑造肉身,陪伴你在每个网页
前端·人工智能
2601_963771372 小时前
10 Best PHP Media CMS and Scripts for Web Creators in 2026
开发语言·前端·php
VaJoy2 小时前
全面革新⚡️ Vue 3.6 项目工程的基础实现
前端·vue.js
苍何3 小时前
耗时 7 天,我们开源了腾讯 WorkBuddy 实战蓝皮书(建议收藏)
前端·后端
大家的林语冰3 小时前
😭 Electron 麻了,Deno 直接支持二进制应用,无需第三方桌面应用框架!
前端·javascript·node.js
Damai3 小时前
DOMPurify 完整介绍
前端·面试
随风一样自由3 小时前
【前端+跨域】跨域问题全面解析与解决方案指南
前端·跨域
小帅不太帅4 小时前
我随手发了几张截图,白拿了一个月 AI 顶配会员
前端·github
36岁的我开始学习打篮球4 小时前
外规内化技术架构
前端