4. 服务器环境搭建与 Docker 安装

在部署代码之前,先让服务器"准备好"。本章从环境检查开始,覆盖 Docker 安装的三种方案(标准/镜像/插件)以及常见的卷权限问题。


4.1 服务器环境"大体检"

在安装任何软件前,先摸清服务器的底细:

体检命令

# 1. 查看操作系统版本
cat /etc/os-release

# 2. 检查是否已有旧版 Docker
docker -v
docker-compose -v

# 3. 网络连通性测试(是否能连外部仓库)
ping -c 3 google.com

原理说明

系统检查清单

检查项 命令 预期结果
系统版本 cat /etc/os-release OpenCloudOS 9 / Ubuntu 22.04 等
CPU nproc >= 2 核
内存 free -h >= 4GB
磁盘 df -h >= 20GB 可用
网络 ping -c 3 google.com 有响应或明确超时

4.2 Docker 引擎安装(三种方案)

根据服务器网络状况选择最适合的方案。

方案 A:标准安装(网络畅通时)

这是 Ubuntu 系统的标准安装流程:

# 1. 更新软件源
sudo apt-get update

# 2. 安装依赖工具
sudo apt-get install -y ca-certificates curl gnupg

# 3. 安装 Docker
sudo apt-get install -y docker.io docker-compose

# 4. 启动 Docker 并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker

# 5. 验证
docker -v
docker-compose -v

原理说明

方案 B:使用阿里云镜像源(网络受阻时)

当官方源连接超时(Connection reset by peer),切换至国内镜像仓库:

# 1. 安装依赖工具(CentOS/OpenCloudOS 用 dnf)
sudo dnf install -y dnf-utils

# 2. 使用阿里云镜像源添加 Docker 仓库
sudo dnf config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 3. 安装 Docker
sudo dnf install -y docker-ce docker-ce-cli containerd.io

# 4. 启动
sudo systemctl start docker
sudo systemctl enable docker

原理说明

Docker Compose 独立版安装

# 官方链接(网络好时)
sudo curl -L "https://github.com/docker/compose/releases/download/v2.24.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 国内加速(使用 DaoCloud 镜像)
sudo curl -L "https://get.daocloud.io/docker/compose/releases/download/v2.24.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 赋予执行权限
sudo chmod +x /usr/local/bin/docker-compose

# 验证
docker-compose -v

方案 C:Docker Compose 插件化安装(最推荐)

如果独立版二进制文件持续下载失败,推荐使用插件模式——这是最稳定、维护成本最低的方式:

# 1. 直接安装插件(从配置好的镜像源下载)
sudo dnf install -y docker-compose-plugin

# 2. 验证(注意:插件版是空格,不是连字符)
docker compose version

原理说明


4.3 配置 Docker 镜像加速器

当你执行 docker compose up 时,报错 i/o timeout 是因为 Docker 默认去美国官方仓库下载镜像。

# 1. 创建 Docker 配置目录
sudo mkdir -p /etc/docker

# 2. 编辑加速器配置
sudo vi /etc/docker/daemon.json

写入以下内容:

{
  "registry-mirrors": [
    "https://mirror.ccs.tencentyun.com",
    "https://2a0tua90.mirror.aliyuncs.com"
  ]
}
# 3. 重启 Docker 服务(激活配置)
sudo systemctl daemon-reload
sudo systemctl restart docker

原理说明


4.4 Docker 卷挂载权限问题完全指南

问题现象

在容器化 Web 应用中,文件上传后经常遇到"权限拒绝"(Permission Denied):

典型场景:
1. 本地开发:文件上传功能正常
2. Docker 环境:上传后无法立即访问
3. 重启容器后:文件又能正常显示

根本原因

flowchart LR
    subgraph 宿主机
        A[Docker 卷目录
所有者: root] end subgraph 容器内 B[应用进程
用户: appuser:1001] end A -.->|权限冲突| B

原理说明

权限继承链的断裂

本地文件 → 容器构建 → 卷挂载 → 运行时写入 → 其他进程读取
   755        755     可能变root    644         可能无权限

解决方案对比

方案 复杂度 适用场景 说明
方案1:entrypoint 脚本修复 ⭐ 低 当前项目正使用 容器启动时 chown 修复权限
方案2:固定 UID/GID ⭐⭐ 中 生产环境 容器内外使用一致的 UID
方案3:绑定挂载 ⭐ 低 开发环境 目录直接映射到宿主机

方案 1:entrypoint 脚本修复(推荐,当前项目使用)

#!/bin/sh
# frontend/entrypoint.sh
set -e

# 在容器启动时强制修复权限
chown -R appuser:appgroup /app/uploads
chmod -R 755 /app/uploads

# 执行数据库迁移
npx prisma migrate deploy

# 启动应用
exec node server.js

原理说明

方案 2:Dockerfile 预配置权限

# 在构建时创建具有正确权限的目录
RUN mkdir -p /app/uploads && \
    chown -R appuser:appgroup /app/uploads && \
    chmod -R 755 /app/uploads

# entrypoint 以 root 运行初始设置后切换到应用用户
USER root
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

USER appuser

方案 3:docker-compose 中指定用户 ID

services:
  frontend:
    user: "1001:1001"  # 显式指定容器运行时用户
    volumes:
      - uploads_data:/app/public/uploads
    # user: "${UID:-1000}:${GID:-1000}"  # 或与宿主机同步

最佳实践建议

设计阶段的权限规划

/app/uploads/
├── avatars/     # 755, appuser:appgroup
├── covers/      # 755, appuser:appgroup
├── temp/        # 777, 临时文件
└── processed/   # 750, 处理后的文件

核心原则

  1. 最小权限:只给应用所需的最小权限
  2. 明确所有权:固定 UID/GID,避免跨环境冲突
  3. 自动化修复:entrypoint 脚本作为最后一道防线
  4. 设计优于修复:提前规划权限策略,避免后期打补丁

返回知识库 | 下一篇:部署实战