Docker 容器化项目标准部署指南

文档版本: v1.0
适用场景: 后端服务容器化部署
演示项目: Galaxy-API (虚拟示例项目)
开发环境: macOS (Apple Silicon M4 Pro - ARM64架构)
生产环境: Linux Server (Ubuntu - AMD64/x86_64架构)

1. 核心概念回顾

在进入部署流程前,我们需要统一对 Docker 核心资产的理解。

核心概念 类比说明 技术定义
镜像 (Image) 软件安装包 一个只读的模板,包含代码、运行时环境、系统库和配置。一旦构建,内容不可变。
容器 (Container) 运行中的软件进程 镜像运行时的实例。它是隔离的、可写的、临时的。删除容器后,容器内产生的数据会丢失(除非使用了挂载卷)。
仓库 (Registry) 应用商店 存放镜像的地方,如 Docker Hub、阿里云镜像服务 (ACR)、Harbor 等。

2. 部署方案一:离线镜像传输 (Offline Transfer)

适用场景:服务器无法连接外网、私有化部署、或没有搭建私有镜像仓库的小型项目。 特点:操作简单,无需依赖第三方仓库,但文件传输耗时较长(每次都是全量传输)。

2.1 跨平台构建 (关键步骤)

由于开发机是 Mac (ARM64),而服务器是 Linux (AMD64),必须使用 buildx 进行交叉编译。如果直接构建,服务器上运行时会报错 exec format error

# 在本地 Mac 终端执行
# -t 指定镜像名称和标签
# --platform 强制指定目标平台为 linux/amd64
docker buildx build --platform linux/amd64 -t galaxy-api:v1.0 .

2.2 导出镜像

将构建好的镜像保存为 tar 归档文件。

# -o 指定输出文件名
docker save -o galaxy-api.tar galaxy-api:v1.0

2.3 传输文件

使用 scp 或 SFTP 工具将镜像包和编排文件上传到服务器。

# 上传镜像包
scp galaxy-api.tar root@your-server-ip:/opt/galaxy/
# 上传编排文件
scp docker-compose.yml root@your-server-ip:/opt/galaxy/

2.4 服务器端加载

登录服务器,解压并加载镜像。

# 加载镜像到服务器的 Docker 引擎
docker load -i /opt/galaxy/galaxy-api.tar

# 验证镜像是否加载成功
docker images | grep galaxy-api

3. 部署方案二:镜像仓库分发 (Registry Distribution) —— 推荐

适用场景:正规互联网项目、需要频繁更新迭代、团队协作开发。 特点:利用 Docker 的分层存储特性,更新时只需下载变动的数据层(增量下载),速度快,且具备版本管理能力。

3.1 准备工作

你需要一个镜像仓库。可以使用:

  • Docker Hub (公有,免费版有拉取次数限制)
  • 云厂商镜像服务 (如阿里云 ACR、腾讯云 TCR,推荐国内使用,速度快且私有)
  • Harbor (自建私有仓库)

3.2 登录仓库

# 在本地 Mac 和 远程服务器上都需要登录
docker login registry.example.com --username=yourname

3.3 构建并推送 (Build & Push)

直接将构建好的镜像推送到云端。

# 1. 标记镜像 (Tag),将其指向远程仓库地址
# 格式: docker tag [本地镜像名]:[版本] [仓库地址]/[命名空间]/[镜像名]:[版本]
docker tag galaxy-api:v1.0 [registry.example.com/myteam/galaxy-api:v1.0](https://registry.example.com/myteam/galaxy-api:v1.0)

# 2. 推送镜像 (会自动处理跨平台问题,前提是 build 时指定了 platform 或使用了 buildx push)
# 推荐使用 buildx 直接推送多架构镜像:
docker buildx build --platform linux/amd64 -t [registry.example.com/myteam/galaxy-api:v1.0](https://registry.example.com/myteam/galaxy-api:v1.0) --push .

3.4 服务器端拉取 (Pull)

在服务器的 docker-compose.yml 中,将 image 字段修改为远程仓库地址,然后直接启动。

# Docker 会自动检测本地是否有该镜像,如果没有或版本不同,会自动去仓库拉取
docker compose up -d

4. 生产环境运行配置 (Orchestration)

无论使用哪种方案,在服务器上运行容器时,建议使用 docker-compose.yml 进行管理。

4.1 配置文件示例

假设我们要部署 galaxy-api,并且它需要连接宿主机的 MySQL 数据库。

version: '3.8'

services:
  galaxy-service:
    # 如果是方案一,直接写镜像名:galaxy-api:v1.0
    # 如果是方案二,写完整仓库地址:[registry.example.com/myteam/galaxy-api:v1.0](https://registry.example.com/myteam/galaxy-api:v1.0)
    image: galaxy-api:v1.0 
    container_name: galaxy-prod
    restart: always
    
    # --- 网络模式选择 (二选一) ---
    
    # 选项 A: Host 模式 (推荐用于需要高性能或直连宿主机DB的场景)
    # 容器共享宿主机 IP,端口直接暴露,无需映射
    network_mode: "host"
    
    # 选项 B: Bridge 模式 (默认模式,隔离性更好)
    # ports:
    #   - "8080:8080"
    # extra_hosts:
    #   - "host.docker.internal:host-gateway" # 允许通过 host.docker.internal 访问宿主机
    
    volumes:
      - ./config/prod.yaml:/app/config.yaml  # 挂载配置文件
      - ./logs:/app/logs                     # 挂载日志目录
    
    environment:
      - TZ=Asia/Shanghai                     # 设置时区
      - APP_ENV=production

4.2 服务管理命令

# 启动服务 (后台运行)
docker compose up -d

# 查看实时日志
docker compose logs -f

# 停止服务
docker compose down

# 更新镜像后重启 (无缝更新)
docker compose down && docker compose up -d

5. 常见问题排查 (Troubleshooting)

5.1 架构不兼容 (Exec format error)

  • 现象:容器状态为 Exited,日志显示 exec format error
  • 原因:你在 Mac (ARM64) 上使用了默认构建命令 docker build .,导致生成的镜像只能在 ARM 芯片上跑,在 Intel/AMD 服务器上跑不起来。
  • 解决:务必使用 docker buildx build --platform linux/amd64

5.2 数据库连接失败 (Connection Refused)

  • 场景:代码配置写的是 127.0.0.1:3306,但在容器里连不上宿主机的 MySQL。
  • 原因
    • 在默认 Bridge 模式下,容器的 localhost 是容器自己,不是宿主机。
    • 宿主机的 MySQL 可能绑定了 bind-address = 127.0.0.1,拒绝外部(容器IP)连接。
  • 解决
    • 方法 1 (最简单):使用 network_mode: "host"
    • 方法 2 (更安全):使用 extra_hosts 映射,代码连接地址改为 host.docker.internal,并确保 MySQL 允许非本地连接。

5.3 端口冲突 (Address already in use)

  • 现象:启动失败,提示端口被占用。
  • 解决
    • 检查服务器上是否已经有其他进程(如 Nginx 或旧的 Java 程序)占用了该端口:netstat -tulpn | grep 8080
    • 检查是否没有删除旧的容器:docker ps -a

6. 两种方案对比总结

特性 方案一:离线传输 (Docker Save/Load) 方案二:仓库分发 (Registry/Hub)
依赖环境 无需外网,仅需 SSH 服务器需能访问镜像仓库
传输效率 低 (每次传输整个文件包,约几百MB) 高 (仅下载变更的层,通常几十MB)
版本管理 困难 (依赖手动文件命名) 优秀 (Tag 管理,可回滚)
安全性 高 (完全物理隔离) 依赖仓库权限管理
自动化支持 较难集成 CI/CD 天然支持 CI/CD 流水线
推荐指数 ⭐⭐⭐ (适合私有化/单机交付) ⭐⭐⭐⭐⭐ (适合互联网/团队开发)