长安的Docker教程长安的Docker教程
首页
快速开始
编程指南
首页
快速开始
编程指南
  • 🎯 Docker入门篇

    • 快速开始
    • Docker是什么?
    • 为什么要用Docker?
    • 安装Docker
    • 第一个容器
  • 📦 Docker基础篇

    • Docker镜像详解
    • 容器操作详解
    • 编写Dockerfile
    • 数据卷(Volumes)
    • Docker网络
  • ⚡ Docker进阶篇

    • Docker Compose
    • 多阶段构建
    • Docker性能优化
    • Docker最佳实践
  • 🚀 实战项目

    • 实战:部署Node.js应用
    • 实战:搭建数据库环境
    • 实战:微服务架构
  • 💡 常见问题

    • 常见问题排查
    • 实用技巧

实战:搭建数据库环境

嘿!长安来教你用Docker搭建各种数据库!再也不用在本地装一堆数据库了!🗄️

🎯 为什么用Docker跑数据库?

优点

✅ 快速部署:一行命令,数据库就起来了
✅ 版本隔离:可以同时跑MySQL 5.7和8.0
✅ 环境一致:开发、测试、生产用同样的配置
✅ 易于清理:不要了就删,干干净净

注意事项

⚠️ 生产环境请谨慎:数据库对性能要求高,生产环境建议用专用服务器
⚠️ 数据备份很重要:一定要做好数据备份!

📦 MySQL

基本使用

# 运行MySQL 8.0
docker run -d \
  --name mysql \
  -e MYSQL_ROOT_PASSWORD=root123 \
  -e MYSQL_DATABASE=mydb \
  -e MYSQL_USER=user \
  -e MYSQL_PASSWORD=pass123 \
  -p 3306:3306 \
  -v mysql-data:/var/lib/mysql \
  mysql:8.0

# 连接MySQL
docker exec -it mysql mysql -uroot -proot123

# 或使用MySQL客户端
mysql -h 127.0.0.1 -P 3306 -uuser -ppass123

完整的docker-compose配置

version: '3.8'

services:
  mysql:
    image: mysql:8.0
    container_name: mysql
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root123}
      MYSQL_DATABASE: ${MYSQL_DATABASE:-mydb}
      MYSQL_USER: ${MYSQL_USER:-user}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD:-pass123}
    ports:
      - "3306:3306"
    volumes:
      # 数据持久化
      - mysql-data:/var/lib/mysql
      # 自定义配置
      - ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
      # 初始化脚本
      - ./mysql/init:/docker-entrypoint-initdb.d
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
      - --default-authentication-plugin=mysql_native_password
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  mysql-data:

自定义配置:mysql/my.cnf

[mysqld]
# 字符集
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci

# 性能优化
max_connections=200
innodb_buffer_pool_size=256M
innodb_log_file_size=64M

# 慢查询日志
slow_query_log=1
slow_query_log_file=/var/log/mysql/slow.log
long_query_time=2

# 二进制日志
log_bin=/var/log/mysql/mysql-bin.log
binlog_format=ROW
expire_logs_days=7

初始化脚本:mysql/init/init.sql

-- 创建表
CREATE TABLE IF NOT EXISTS users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 插入测试数据
INSERT INTO users (name, email) VALUES
    ('长安', 'changan@example.com'),
    ('用户1', 'user1@example.com'),
    ('用户2', 'user2@example.com');

-- 创建索引
CREATE INDEX idx_email ON users(email);

备份和恢复

# 备份
docker exec mysql mysqldump -uroot -proot123 mydb > backup.sql

# 或备份所有数据库
docker exec mysql mysqldump -uroot -proot123 --all-databases > all_databases.sql

# 恢复
docker exec -i mysql mysql -uroot -proot123 mydb < backup.sql

🐘 PostgreSQL

基本使用

# 运行PostgreSQL
docker run -d \
  --name postgres \
  -e POSTGRES_PASSWORD=postgres123 \
  -e POSTGRES_USER=user \
  -e POSTGRES_DB=mydb \
  -p 5432:5432 \
  -v postgres-data:/var/lib/postgresql/data \
  postgres:15

# 连接PostgreSQL
docker exec -it postgres psql -U user -d mydb

Docker Compose配置

version: '3.8'

services:
  postgres:
    image: postgres:15-alpine
    container_name: postgres
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${POSTGRES_USER:-user}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres123}
      POSTGRES_DB: ${POSTGRES_DB:-mydb}
      PGDATA: /var/lib/postgresql/data/pgdata
    ports:
      - "5432:5432"
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./postgres/init:/docker-entrypoint-initdb.d
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5

  # pgAdmin - PostgreSQL管理工具
  pgadmin:
    image: dpage/pgadmin4
    container_name: pgadmin
    restart: unless-stopped
    environment:
      PGADMIN_DEFAULT_EMAIL: admin@example.com
      PGADMIN_DEFAULT_PASSWORD: admin123
    ports:
      - "5050:80"
    volumes:
      - pgadmin-data:/var/lib/pgadmin
    depends_on:
      - postgres

volumes:
  postgres-data:
  pgadmin-data:

初始化脚本:postgres/init/init.sql

-- 创建表
CREATE TABLE IF NOT EXISTS users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 插入测试数据
INSERT INTO users (name, email) VALUES
    ('长安', 'changan@example.com'),
    ('用户1', 'user1@example.com');

-- 创建索引
CREATE INDEX idx_email ON users(email);

🍃 MongoDB

基本使用

# 运行MongoDB
docker run -d \
  --name mongo \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=admin123 \
  -e MONGO_INITDB_DATABASE=mydb \
  -p 27017:27017 \
  -v mongo-data:/data/db \
  mongo:6

# 连接MongoDB
docker exec -it mongo mongosh -u admin -p admin123

Docker Compose配置

version: '3.8'

services:
  mongo:
    image: mongo:6
    container_name: mongo
    restart: unless-stopped
    environment:
      MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USER:-admin}
      MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASSWORD:-admin123}
      MONGO_INITDB_DATABASE: ${MONGO_DATABASE:-mydb}
    ports:
      - "27017:27017"
    volumes:
      - mongo-data:/data/db
      - mongo-config:/data/configdb
      - ./mongo/init:/docker-entrypoint-initdb.d
    healthcheck:
      test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Mongo Express - MongoDB管理工具
  mongo-express:
    image: mongo-express:latest
    container_name: mongo-express
    restart: unless-stopped
    ports:
      - "8081:8081"
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: ${MONGO_ROOT_USER:-admin}
      ME_CONFIG_MONGODB_ADMINPASSWORD: ${MONGO_ROOT_PASSWORD:-admin123}
      ME_CONFIG_MONGODB_URL: mongodb://${MONGO_ROOT_USER:-admin}:${MONGO_ROOT_PASSWORD:-admin123}@mongo:27017/
    depends_on:
      - mongo

volumes:
  mongo-data:
  mongo-config:

初始化脚本:mongo/init/init.js

// 切换到mydb数据库
db = db.getSiblingDB('mydb');

// 创建集合
db.createCollection('users');

// 插入数据
db.users.insertMany([
    {
        name: '长安',
        email: 'changan@example.com',
        createdAt: new Date()
    },
    {
        name: '用户1',
        email: 'user1@example.com',
        createdAt: new Date()
    }
]);

// 创建索引
db.users.createIndex({ email: 1 }, { unique: true });

print('✅ 初始化完成!');

🔴 Redis

基本使用

# 运行Redis
docker run -d \
  --name redis \
  -p 6379:6379 \
  -v redis-data:/data \
  redis:7-alpine \
  redis-server --appendonly yes

# 连接Redis
docker exec -it redis redis-cli

Docker Compose配置

version: '3.8'

services:
  redis:
    image: redis:7-alpine
    container_name: redis
    restart: unless-stopped
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-redis123}
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
      - ./redis/redis.conf:/usr/local/etc/redis/redis.conf
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 5

  # RedisInsight - Redis管理工具
  redis-insight:
    image: redislabs/redisinsight:latest
    container_name: redis-insight
    restart: unless-stopped
    ports:
      - "8001:8001"
    volumes:
      - redis-insight-data:/db

volumes:
  redis-data:
  redis-insight-data:

Redis配置:redis/redis.conf

# 密码
requirepass redis123

# 持久化
appendonly yes
appendfsync everysec

# 最大内存
maxmemory 256mb
maxmemory-policy allkeys-lru

# 慢查询日志
slowlog-log-slower-than 10000
slowlog-max-len 128

🎯 完整的数据库栈

把所有数据库组合在一起:

docker-compose.yml

version: '3.8'

services:
  # MySQL
  mysql:
    image: mysql:8.0
    container_name: db-mysql
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: root123
      MYSQL_DATABASE: mydb
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - db-network

  # PostgreSQL
  postgres:
    image: postgres:15-alpine
    container_name: db-postgres
    restart: unless-stopped
    environment:
      POSTGRES_PASSWORD: postgres123
      POSTGRES_DB: mydb
    ports:
      - "5432:5432"
    volumes:
      - postgres-data:/var/lib/postgresql/data
    networks:
      - db-network

  # MongoDB
  mongo:
    image: mongo:6
    container_name: db-mongo
    restart: unless-stopped
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: admin123
    ports:
      - "27017:27017"
    volumes:
      - mongo-data:/data/db
    networks:
      - db-network

  # Redis
  redis:
    image: redis:7-alpine
    container_name: db-redis
    restart: unless-stopped
    command: redis-server --appendonly yes
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    networks:
      - db-network

  # Adminer - 数据库管理工具(支持MySQL、PostgreSQL等)
  adminer:
    image: adminer:latest
    container_name: db-adminer
    restart: unless-stopped
    ports:
      - "8080:8080"
    networks:
      - db-network

networks:
  db-network:
    driver: bridge

volumes:
  mysql-data:
  postgres-data:
  mongo-data:
  redis-data:

启动和使用

# 启动所有数据库
docker-compose up -d

# 查看状态
docker-compose ps

# 查看日志
docker-compose logs -f

# 访问Adminer管理工具
# 打开浏览器:http://localhost:8080

🔧 实用脚本

备份脚本:backup.sh

#!/bin/bash

BACKUP_DIR="./backups/$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"

echo "开始备份数据库..."

# 备份MySQL
echo "备份MySQL..."
docker exec db-mysql mysqldump -uroot -proot123 --all-databases > "$BACKUP_DIR/mysql.sql"

# 备份PostgreSQL
echo "备份PostgreSQL..."
docker exec db-postgres pg_dumpall -U postgres > "$BACKUP_DIR/postgres.sql"

# 备份MongoDB
echo "备份MongoDB..."
docker exec db-mongo mongodump --out=/tmp/backup
docker cp db-mongo:/tmp/backup "$BACKUP_DIR/mongo"

# 备份Redis
echo "备份Redis..."
docker exec db-redis redis-cli SAVE
docker cp db-redis:/data/dump.rdb "$BACKUP_DIR/redis.rdb"

echo "✅ 备份完成!保存在 $BACKUP_DIR"

监控脚本:monitor.sh

#!/bin/bash

echo "====== 数据库监控 ======"
echo

# MySQL状态
echo "MySQL:"
docker exec db-mysql mysqladmin -uroot -proot123 status 2>/dev/null || echo "  ❌ 未运行"
echo

# PostgreSQL状态
echo "PostgreSQL:"
docker exec db-postgres pg_isready -U postgres 2>/dev/null || echo "  ❌ 未运行"
echo

# MongoDB状态
echo "MongoDB:"
docker exec db-mongo mongosh --eval "db.adminCommand('ping')" 2>/dev/null || echo "  ❌ 未运行"
echo

# Redis状态
echo "Redis:"
docker exec db-redis redis-cli ping 2>/dev/null || echo "  ❌ 未运行"
echo

# 资源使用
echo "====== 资源使用 ======"
docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}"

💡 最佳实践

1. 数据持久化

✅ 总是使用数据卷

volumes:
  - mysql-data:/var/lib/mysql  # ✅ 好
  # 而不是
  # - ./data:/var/lib/mysql    # ❌ 不推荐(bind mount性能差)

2. 定期备份

# 添加到crontab
0 2 * * * /path/to/backup.sh

3. 资源限制

services:
  mysql:
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 2G

4. 健康检查

healthcheck:
  test: ["CMD", "mysqladmin", "ping"]
  interval: 10s
  timeout: 5s
  retries: 5

5. 不要暴露到公网

# ❌ 不好
ports:
  - "0.0.0.0:3306:3306"

# ✅ 好(只监听本地)
ports:
  - "127.0.0.1:3306:3306"

💡 小结

今天长安教你搭建数据库环境:

学到的数据库

✅ MySQL
✅ PostgreSQL
✅ MongoDB
✅ Redis

学到的技能

  1. 快速部署数据库
  2. 数据持久化
  3. 初始化脚本
  4. 备份恢复
  5. 管理工具使用

🚀 下一步

数据库环境搭建完了!下一章长安教你 微服务架构!


💬 长安的数据库经验:

Docker跑数据库真的太方便了!

以前本地装了MySQL、PostgreSQL、MongoDB、Redis... 系统慢得要死,还经常端口冲突😂

现在全用Docker,需要什么启动什么,不用了就删掉。

但是记住:生产环境的数据库要慎重!

  • 数据一定要备份
  • 资源一定要够
  • 监控一定要做好

开发测试用Docker,爽!
生产环境看情况,谨慎!

下一章见!💪

在 GitHub 上编辑此页
Prev
实战:部署Node.js应用
Next
实战:微服务架构