当前位置:首页>Linux>第34讲:在Linux服务器上部署完整项目

第34讲:在Linux服务器上部署完整项目

  • 2026-09-02 15:45:45
第34讲:在Linux服务器上部署完整项目
前面 33 讲都在为这一刻做准备。

现在我们有版本化镜像、生产 Compose 配置、数据卷、健康检查和备份方案,可以把订单项目部署到一台 Linux 服务器。

这一讲以单机 Compose 为边界,重点是可重复、可验证、能回退。它不是多机高可用方案。


上线前必须准备什么

服务器

  • 受支持的 64 位 Linux 发行版
  • 已按第 6 讲安装 Docker Engine、Buildx 和 Compose 插件
  • 磁盘、内存和 CPU 满足应用及中间件需求
  • 时间同步正常
  • 防火墙和云安全组按最小范围开放

发布物

  • compose.yaml
  • compose.production.yaml
  • .env.production
  • 明确版本的 PHP 应用镜像
  • 同版本 Nginx 镜像
  • 数据库迁移说明
  • 当前备份和回滚版本

外部条件

  • 域名解析
  • HTTPS 终止方案
  • 镜像仓库只读凭据
  • 备份存储
  • 日志、监控和告警入口

如果容器 Nginx 只绑定 127.0.0.1:8080,还需要宿主机反向代理或外部负载均衡器把 HTTPS 流量转发进来。


先检查服务器状态

uname -adocker versiondocker compose versiondf -hfree -htimedatectl status

重点确认:

  • Docker Client 和 Server 都正常
  • Compose 插件可用
  • Docker 数据目录所在磁盘空间充足
  • 内存和 Swap 策略符合数据库要求
  • 系统时间和时区正确

数据库和 RabbitMQ 对磁盘空间非常敏感。磁盘已经接近满载时,不应该继续发布新镜像和创建日志。


使用独立部署用户和目录

示例目录:

sudo install -d \  -o deploy \  -g deploy \  -m 750 \  /opt/order-app

进入目录:

cd /opt/order-app

将两个 Compose 文件通过受控发布流程放到这里,并确认所有者和权限。

能够访问 Docker Socket 的用户通常拥有接近宿主机管理员的能力。deploy 用户是否加入 Docker 组必须经过权限评估,不能因为方便就给所有开发者开放。

生产 SSH、sudo 和 Docker 权限应使用个人账号、最小授权和审计记录。


安全准备生产变量

install -m 600 /dev/null .env.production

使用受控方式写入真实配置:

APP_IMAGE=registry.example.com/phper/order-api:1.4.0NGINX_IMAGE=registry.example.com/phper/order-nginx:1.4.0APP_ENV=productionAPP_DEBUG=falseDB_DATABASE=order_appDB_USERNAME=order_appDB_PASSWORD=生产数据库密码MYSQL_ROOT_PASSWORD=生产root密码REDIS_PASSWORD=生产Redis密码RABBITMQ_USER=order_appRABBITMQ_PASSWORD=生产RabbitMQ密码RABBITMQ_VHOST=order_app

输入过程中避免终端录屏、Shell 历史和工单日志泄露。

更成熟的环境应由秘密管理系统在部署时提供,而不是长期依赖人工编辑文件。


登录镜像仓库

生产服务器使用只读拉取令牌:

printf '%s' ”$REGISTRY_PULL_TOKEN” \  | docker login \      --username ”$REGISTRY_PULL_USER” \      --password-stdin \      registry.example.com

令牌变量应由安全会话或秘密系统提供,不要把真实值写入发布脚本。

生产服务器没有必要拥有推送、删除或覆盖镜像的权限。


先验证最终Compose配置

docker compose \  --env-file .env.production \  -f compose.yaml \  -f compose.production.yaml \  config --quiet

查看服务和镜像:

docker compose \  --env-file .env.production \  -f compose.yaml \  -f compose.production.yaml \  config --servicesdocker compose \  --env-file .env.production \  -f compose.yaml \  -f compose.production.yaml \  config --images

确认:

  • 镜像是发布清单中的 1.4.0
  • 没有 latest
  • 没有宿主机源码挂载
  • Debug 已关闭
  • 中间件业务端口没有公开
  • 数据卷名称和挂载目录正确

完整 config 输出可能包含秘密,不能直接上传到日志平台。


拉取全部镜像

docker compose \  --env-file .env.production \  -f compose.yaml \  -f compose.production.yaml \  pull

拉取后核对:

docker image inspect \  registry.example.com/phper/order-api:1.4.0

应与发布清单中的 digest 一致。

拉取成功只证明仓库、权限和镜像存在,不代表应用已经部署。


第一次部署先启动数据服务

docker compose \  --env-file .env.production \  -f compose.yaml \  -f compose.production.yaml \  up -d mysql redis rabbitmq

查看健康状态:

docker compose \  --env-file .env.production \  -f compose.yaml \  -f compose.production.yaml \  ps

查看首次初始化日志:

docker compose \  --env-file .env.production \  -f compose.yaml \  -f compose.production.yaml \  logs --tail 200 mysql redis rabbitmq

等待服务 healthy,再执行数据库迁移。

如果使用云数据库、云 Redis 或独立 RabbitMQ,Compose 不应再启动对应本地服务,应用配置改为受控内部地址。


执行数据库迁移

发布前先完成备份。第一次空库也应确认目标地址,避免迁移连到错误环境。

Laravel 示例:

docker compose \  --env-file .env.production \  -f compose.yaml \  -f compose.production.yaml \  run --rm php \  php artisan migrate --force

迁移是一次性受控任务,不放进 PHP-FPM 入口脚本。

检查迁移输出和退出码。失败时不要继续启动 Web 服务,先确认数据库连接、权限、SQL 和版本兼容性。

涉及大表 DDL 时,还要提前评估锁表、复制延迟、磁盘空间和执行时间,不能因为命令在容器里运行就忽略数据库风险。


启动完整应用

docker compose \  --env-file .env.production \  -f compose.yaml \  -f compose.production.yaml \  up -d --remove-orphans

--remove-orphans 会删除当前项目中不再由配置定义的服务容器。使用前必须确认项目名和最终配置,避免误删仍在使用但遗漏在文件中的容器。

查看:

docker compose \  --env-file .env.production \  -f compose.yaml \  -f compose.production.yaml \  ps

分层验证

容器与健康状态

所有预期服务存在,关键服务为 healthy,没有反复重启。

最近日志

docker compose \  --env-file .env.production \  -f compose.yaml \  -f compose.production.yaml \  logs --tail 200

检查数据库认证、Redis 连接、RabbitMQ vhost、文件权限和 PHP-FPM 错误。

服务器本机HTTP

curl -fsS http://127.0.0.1:8080/health

健康端点应轻量,不返回密码、内部堆栈和敏感版本信息。

外部HTTPS

curl -fsS https://api.example.com/health

再验证证书、域名、反向代理和外部网络路径。

业务冒烟测试

  • 登录测试账号
  • 查询商品
  • 创建一笔可清理的测试订单
  • 验证 MySQL 记录
  • 验证 Redis 缓存
  • 验证 RabbitMQ 消息被正确消费
  • 清理测试数据

冒烟测试必须使用可识别、可回收的数据,不能污染真实用户和财务数据。


重启服务器后服务会恢复吗

确认 Docker 服务开机启动:

sudo systemctl is-enabled docker

Compose 服务配置了合适的 restart: unless-stopped 后,Docker Daemon 恢复时会尝试启动已有容器。

但仍要验证:

  • 数据卷是否挂载成功
  • 外部磁盘或网络存储是否先就绪
  • 容器是否健康
  • 反向代理是否恢复
  • DNS 和证书是否正常

不要第一次在生产重启时才检验恢复流程。应在预发布或维护窗口演练。


上线后立即记录什么

发布时间执行人Git提交镜像标签和digestCompose文件版本数据库迁移备份位置和校验结果健康检查结果冒烟测试结果上一稳定版本

同时观察一段时间的:

  • HTTP 错误率和响应时间
  • PHP-FPM Worker 状态
  • MySQL 连接和慢查询
  • Redis 内存和命中率
  • RabbitMQ 队列堆积与消费者
  • 容器 CPU、内存和重启次数
  • 主机磁盘使用

小结

单机 Compose 上线不是一句 up -d,而是一套受控流程:检查服务器、准备生产变量、拉取并核对镜像、启动数据服务、备份、执行迁移、启动应用、分层验证并记录发布结果。

本机健康和外部 HTTPS 都要验证,最终还要完成真实业务冒烟测试。

下一讲,我们处理更常见的日常操作:发布新版本、控制更新范围,以及新镜像或数据库变更失败后怎样回滚。


本篇是《Docker 40讲:从项目容器化到线上部署》第34讲。

下一讲:线上版本应该怎样更新和回滚

更多内容将持续更新。

最新文章

随机文章