适用场景:在 Linux 服务器(或 Windows + WSL2)上通过 Docker 部署 Web 项目
涵盖两种数据层方案:内置 MySQL/Redis vs 使用外部 MySQL/Redis


目录

  1. 前置准备
  2. 拉取项目代码
  3. 方案一:一切都在 Docker 中(内置 MySQL + Redis)
  4. 方案二:使用外部 MySQL + Redis
  5. 配置参数详解
  6. 常见问题与排错
  7. 总结

前置准备

安装 Docker 和 Docker Compose

# 检查是否已安装
docker --version
docker compose version

# Ubuntu / Debian 快速安装
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER
newgrp docker

安装 Git

git --version   # 确认版本,如果没有则:
sudo apt install git -y

国内网络环境:配置 Docker 镜像加速(可选但推荐)

Docker Hub 在国内访问不稳定,建议配置镜像加速器:

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://docker.m.daocloud.io"]
}
EOF
sudo systemctl daemon-reexec
sudo systemctl restart docker

如果使用 Docker Desktop(Windows/Mac),则在 Settings → Docker Engine 中编辑 daemon.json,添加同样的 registry-mirrors 配置后重启。


拉取项目代码

# 1. 创建项目目录(推荐放到用户家目录下)
mkdir -p ~/projects
cd ~/projects

# 2. 克隆代码
git clone https://github.com/your-org/your-project.git
cd your-project

注意:项目不宜放在 /mnt/ 挂载的 Windows 盘符下(如 /mnt/d/),建议放在 Linux 原生文件系统中。原因是跨文件系统(9p 协议)会产生 3~5 倍的 IO 性能损失,影响 gitnpmdocker build 等操作的速度。


方案一:一切都在 Docker 中

此方案中 MySQL 数据库Redis 缓存 都作为 Docker 容器运行,适合快速搭建开发环境。

docker-compose.yml 完整配置

version: '3.8'

services:
  app:
    image: your-org/your-app:latest
    container_name: your-app
    restart: always
    command: --log-dir /app/logs
    ports:
      - "3000:3000"
    volumes:
      - ./data:/data
      - ./logs:/app/logs
    environment:
      - SQL_DSN=root:your_mysql_password@tcp(mysql:3306)/your_database
      - REDIS_CONN_STRING=redis://:your_redis_password@redis:6379
      - TZ=Asia/Shanghai
      - ERROR_LOG_ENABLED=true
      - BATCH_UPDATE_ENABLED=true
    depends_on:
      - redis
      - mysql
    networks:
      - app-network

  redis:
    image: redis:7
    container_name: redis
    restart: always
    command: ["redis-server", "--requirepass", "your_redis_password"]
    networks:
      - app-network

  mysql:
    image: mysql:8.0
    container_name: mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: your_mysql_password
      MYSQL_DATABASE: your_database
    volumes:
      - mysql_data:/var/lib/mysql
    networks:
      - app-network
    ports:
      - "3306:3306"  # 可选:宿主机也能直连 MySQL

volumes:
  mysql_data:

networks:
  app-network:
    driver: bridge

启动

docker compose up -d

验证

# 查看容器状态
docker compose ps

# 查看日志
docker logs your-app --tail 30

# 检查 API 是否响应
curl http://localhost:3000/api/status

方案二:使用外部 MySQL + Redis

此方案适用于:

  • 已有现成的 MySQL 和 Redis 服务(如公司测试环境)
  • 想把数据库持久化到宿主机本地或独立数据库服务器
  • 本地 Windows 安装的 MySQL/Redis + Docker(WSL2 后端) 的场景

原理

Docker 容器通过网络连接到「外部」的 MySQL 和 Redis,而非在容器内运行。这里的「外部」可以是:

场景 连接地址
同一台 Linux 服务器 127.0.0.1
其他服务器 192.168.x.x 或域名
Windows 宿主机(Docker Desktop + WSL2) host.docker.internal

host.docker.internal 是 Docker Desktop 提供的特殊 DNS 名称,在容器内部自动解析为宿主机(即 Windows 或 macOS 本机)的 IP 地址。
在纯 Linux 环境中此名称不可用,需替换为实际 IP。

docker-compose.yml 配置

services:
  app:
    image: your-org/your-app:latest
    container_name: your-app
    restart: always
    command: --log-dir /app/logs
    ports:
      - "3000:3000"
    volumes:
      - ./data:/data
      - ./logs:/app/logs
    environment:
      # 关键:连接地址改成外部 MySQL/Redis
      - SQL_DSN=root:your_mysql_password@tcp(host.docker.internal:3306)/your_database
      - REDIS_CONN_STRING=redis://:your_redis_password@host.docker.internal:6379
      - TZ=Asia/Shanghai
      - ERROR_LOG_ENABLED=true
      - BATCH_UPDATE_ENABLED=true
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

注意:此配置去掉了 depends_on(因为外部服务不归 Docker 管理)、去掉了 version 字段(Docker Compose v2 已废弃此字段)、以及删除了 mysql 和 redis 服务定义。

纯 Linux 服务器上的配置

如果外部 MySQL/Redis 运行在另一台服务器(IP: 192.168.1.100),只需改连接地址:

environment:
  - SQL_DSN=root:your_mysql_password@tcp(192.168.1.100:3306)/your_database
  - REDIS_CONN_STRING=redis://:your_redis_password@192.168.1.100:6379

启动

docker compose up -d

验证

检查日志确认服务连接成功:

docker logs your-app --tail 20

成功的关键日志行:

Redis is enabled
database migration started ... done
New API v1.0.0-rc.21 started

配置参数详解

数据源(SQL_DSN)

格式: 用户名:密码@协议(主机地址:端口)/数据库名?参数
范例: root:MyPass123@tcp(host.docker.internal:3306)/app_db?charset=utf8mb4&parseTime=True&loc=Local
说明
root 数据库用户名
MyPass123 数据库密码
tcp 连接协议,通常用 tcp;也支持 unix(本地 socket)
host.docker.internal:3306 主机地址和端口。容器内连本机其他容器时写服务名(如 mysql:3306);连外部服务时写 IP 或域名
app_db 数据库名,需要提前创建好
charset=utf8mb4 字符集,推荐 utf8mb4 以支持 emoji
parseTime=True 让驱动自动把 MySQL 的 DATETIME/TIMESTAMP 转为 Go 的 time.Time
loc=Local 时区,与程序所在时区对齐

Redis 连接串(REDIS_CONN_STRING)

格式: redis://[:密码@]主机地址:端口/数据库编号
范例: redis://:YourPass@host.docker.internal:6379/0
说明
:YourPass Redis 认证密码。冒号前的密码字段为空表示前面加冒号占位
host.docker.internal:6379 连接地址和端口。同上,容器内用服务名,外部用 IP/域名
/0 Redis 数据库编号(0~15)。不填默认 0

其他关键环境变量

变量 默认值 说明
TZ UTC 容器时区。设为 Asia/Shanghai 使用东八区
ERROR_LOG_ENABLED false 是否启用错误日志记录到数据库
BATCH_UPDATE_ENABLED false 是否启用批量更新(提高频繁更新场景的性能)
NODE_NAME 随机字符串 节点名称,多容器部署时用于区分节点
STREAMING_TIMEOUT 120 流模式无响应超时(秒),出现空补全时可调大
SYNC_FREQUENCY 60 数据库同步间隔(秒),定期从数据库刷新配置
SESSION_SECRET 随机 Session 加密密钥,多机部署时务必改为固定随机字符串

Docker Compose 配置项说明

配置项 说明
image 使用的 Docker 镜像,格式 仓库/名称:标签
container_name 容器名称,用于 docker logsdocker exec
restart: always 容器异常退出后自动重启
ports: "3000:3000" 宿主机端口:容器端口映射
volumes: ./data:/data 挂载宿主目录到容器内,数据持久化
depends_on 定义服务依赖关系,控制启动顺序
networks 容器加入的网络,同一网络的服务可通过服务名互相访问

常见问题与排错

1. docker 命令找不到

原因:Docker 未安装或当前用户不在 docker 组。

# 如果是 WSL2,在 Docker Desktop 设置中开启 Integration
# Docker Desktop → Settings → Resources → WSL Integration → 勾选你的发行版

# 如果是 Linux,将用户加入 docker 组
sudo usermod -aG docker $USER
newgrp docker

2. 端口被占用

# 检查端口占用
sudo netstat -tlnp | grep -E '3306|6379|3000'

# 如果本地 MySQL 占用了 3306,两个方案选其一:
# 方案一:停掉本地 MySQL 服务
sudo systemctl stop mysql
sudo systemctl disable mysql

# 方案二:改用外部 MySQL(方案二),容器连本地 MySQL

3. Docker Hub 拉取镜像失败

表现:failed to resolve reference "docker.io/xxx"
原因:Docker Hub 在国内被限速或阻断。

解决方法一:配置镜像加速器(推荐)

{
  "registry-mirrors": ["https://docker.m.daocloud.io"]
}

解决方法二:手动拉取镜像时指定镜像源

docker pull docker.m.daocloud.io/library/mysql:8.0
docker tag docker.m.daocloud.io/library/mysql:8.0 mysql:8.0

解决方法三:在 docker-compose.yml 中直接使用加速镜像前缀

services:
  mysql:
    image: docker.m.daocloud.io/library/mysql:8.0   # 而不是 mysql:8.0

4. 容器启动失败 - MySQL 连接拒绝

# 检查 MySQL 是否正常运行
docker logs mysql --tail 10

# 检查连接地址是否正确
# 同一 Compose 内 → 服务名即可(如 mysql:3306)
# 外部服务器 → 必须是可达的 IP 或域名
# WSL2 环境 → host.docker.internal

5. permission denied while trying to connect to the Docker daemon socket

sudo usermod -aG docker $USER
# 重新登录或执行 newgrp docker 后重试

总结

两种方案对比

对比项 方案一:内置 MySQL+Redis 方案二:外部 MySQL+Redis
启动复杂度 简单,一行命令 需提前准备好外部服务
数据持久化 通过 Docker volume 由外部服务负责
适用场景 快速开发、测试环境 生产环境或已有现成服务
性能 容器内网络,延迟低 取决于网络链路
配置要点 depends_on 控制顺序 连接地址改为 IP/域名

核心知识点

  • SQL_DSNREDIS_CONN_STRING 是连接数据库和缓存的唯一入口,改地址即可切换数据源
  • host.docker.internal 是 Docker Desktop 提供的宿主机访问魔法地址,仅在 Windows/macOS 的 Docker Desktop 环境中可用;纯 Linux 用实际 IP
  • 镜像加速器解决 Docker Hub 访问慢的问题
  • 项目代码建议放在 Linux 原生文件系统(ext4)而非跨文件系统挂载点,避免性能损失

提示:文中所有 your-orgyour-appyour_databaseyour_mysql_passwordyour_redis_password192.168.x.x 均为占位符,请替换为你实际的参数。

更多推荐