Docker 部署指南:从拉取代码到项目正常启动
适用场景:在 Linux 服务器(或 Windows + WSL2)上通过 Docker 部署 Web 项目
涵盖两种数据层方案:内置 MySQL/Redis vs 使用外部 MySQL/Redis
目录
前置准备
安装 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 性能损失,影响git、npm、docker 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 logs 和 docker 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_DSN和REDIS_CONN_STRING是连接数据库和缓存的唯一入口,改地址即可切换数据源host.docker.internal是 Docker Desktop 提供的宿主机访问魔法地址,仅在 Windows/macOS 的 Docker Desktop 环境中可用;纯 Linux 用实际 IP- 镜像加速器解决 Docker Hub 访问慢的问题
- 项目代码建议放在 Linux 原生文件系统(ext4)而非跨文件系统挂载点,避免性能损失
提示:文中所有
your-org、your-app、your_database、your_mysql_password、your_redis_password、192.168.x.x均为占位符,请替换为你实际的参数。
更多推荐
所有评论(0)