4.1 生产环境部署考量


4.1 生产环境部署考量

本节摘要:生产环境部署考量是一组决定"Compose 能不能上、上了怎么不出事"的决策。核心是两件事:第一,认清 Compose 的定位边界——它是单机编排工具,适合小型应用与单节点部署;第二,把开发模板升级成生产配置——固定镜像版本、设置时区、配置重启策略、加资源限制与健康检查。本节给出完整的生产版 compose 示例、就绪检查清单,并讨论配置漂移与部署自动化。

读前必看(上)

  • 能说清 Compose 的定位边界,判断一个业务是否适合用 Compose 上生产
  • 能写出固定镜像版本、时区、重启策略、资源限制、健康检查齐备的生产配置
  • 能解释配置漂移是怎么产生的,并用版本控制与覆盖文件机制消除它
  • 能描述部署自动化与高可用思路,知道 Compose 的能力边界在哪里

一、先认清边界:Compose 适合什么样的生产

我们得先泼一盆冷水:Compose 最初的设计目标是简化单机或小型集群的应用部署,它不是万能的编排系统。在开发环境里 docker compose up -d 一行命令拉起五个服务很痛快,但把同样的操作搬到生产,要面对的是完全不同的追问——挂了怎么办、流量涨了怎么办、发布怎么不中断。

Compose 的局限是明摆着的。它主要针对单机环境,虽然可以配合 Docker Swarm 做集群部署,但 Swarm 的功能相对简单,缺乏高级的调度与管理能力。它本身不具备自动伸缩功能,副本数要手动调整;滚动更新能力有限,docker compose up -d 虽然能更新服务,但过程相对粗糙,容易造成服务中断;资源管理能力也不足,无法对容器资源使用做细粒度控制。

那什么时候仍然值得用 Compose?我们给出三条判断标准。第一,小型应用:规模小、复杂度不高,Compose 能把部署和管理成本压到最低。第二,单节点部署:业务只需要跑在一台机器上,没有跨主机需求。第三,过渡阶段:把 Compose 当作从开发环境走向生产环境的桥梁,等规模上来再逐步迁移到更专业的编排工具。换句话说,Compose 生产化的前提是"单机能扛住",判断依据不是情怀,而是流量、可用性 SLA 和团队运维能力。

二、生产配置基线:七件事一件都不能省

确定可以用 Compose 之后,就要把第三章的模板逐项升级。下面是我们认为生产环境必须补上的七件事,每件都对应一段配置。

固定镜像版本。 开发环境用 nginx:latest 无所谓,生产环境这是事故源。镜像仓库里的 latest 标签会漂移,今天拉的和上周拉的可能差好几个版本,线上行为无法复现。更稳妥的做法是固定到具体版本号,比如 nginx:1.25.3,甚至固定到镜像摘要 digest。

设置时区。 容器默认 UTC 时区,日志时间戳和业务时间会差八个小时,排查问题时先对不上表。通过环境变量 TZ: Asia/Shanghai 统一设置,日志、定时任务、数据库会话的时区就都一致了。

重启策略。 容器异常退出后要不要自动拉起,由 restart 决定。开发环境默认 no 就行,生产环境我们习惯用 unless-stopped——它会在容器退出后自动重启,但明确 stop 的容器不会被拉起来,比 always 更符合运维直觉。

资源限制。 不设限制的容器会无限占用 CPU 和内存,把同机的其他服务拖垮。详见 4.3,但配置基线上至少要有 CPU 与内存的 limits。

健康检查。 让 Docker 能感知容器是否真的活着,而不是只看进程在不在。定义 healthcheck 后,配合依赖关系可以实现"数据库就绪再启动应用"。

日志轮转。 默认 json-file 驱动会把日志无限写进宿主磁盘,必须配置 max-size 与 max-file,详见 4.4。

数据持久化与环境变量注入。 数据挂 named volume,敏感参数一律走环境变量或 secrets(详见 4.2),绝不硬编码进文件。

下面是一张生产配置基线的速查表:

配置项 推荐写法 防的是什么
镜像 tag nginx:1.25.3 而非 latest 镜像漂移、不可复现
时区 environment 中设置 TZ 日志与业务时间错位
重启策略 restart: unless-stopped 异常退出后服务不恢复
CPU 限额 deploy.resources.limits.cpus 单容器占满整机 CPU
内存限额 deploy.resources.limits.memory OOM 拖垮同机服务
健康检查 healthcheck 定义存活探针 假活、依赖未就绪
日志轮转 max-size 与 max-file 日志撑爆磁盘
数据卷 named volume 持久化 容器重建丢数据

三、完整示例:一份能上生产的 compose 文件

把上面的基线合起来,就是一份可以直接抄的生产版 compose。示例是一个 Web 服务加一个 PostgreSQL 数据库,所有配置项都有实际含义:

version: "3.9" services: web: image: nginx:1.25.3 restart: unless-stopped environment: TZ: Asia/Shanghai deploy: resources: limits: cpus: "0.5" memory: 512M logging: driver: json-file options: max-size: "10m" max-file: "3" healthcheck: test: ["CMD", "curl", "-f", "http://localhost"] interval: 30s timeout: 10s retries: 3 networks: - my-network db: image: postgres:13.4 restart: unless-stopped environment: TZ: Asia/Shanghai POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - db_data:/var/lib/postgresql/data networks: - my-network networks: my-network: driver: bridge volumes: db_data:

逐行解读关键配置。image: nginx:1.25.3 固定了镜像版本,拉取行为可复现;restart: unless-stopped 让崩溃的容器自动恢复;cpus: "0.5" 限制 Web 最多用半个 CPU 核,memory: 512M 封顶内存,防止它失控;logging 段把单个日志文件限制在 10MB 以内并只保留 3 个文件;healthcheck 每 30 秒用 curl 探一次本机,连续 3 次失败就判定不健康,配合 interval: 30stimeout: 10sretries: 3 三个参数,Docker 会在容器假死时触发重启逻辑。数据库密码通过 ${POSTGRES_PASSWORD} 从环境变量注入,实际值放在 .env 文件里,compose 文件本身不含任何敏感信息。db_data 是 named volume,容器重建后数据还在。

这里有个细节值得说:新版 Docker Compose 已经不强制要求 version 字段,但我们保留 version: "3.9" 是为了和 Swarm 的 stack 文件兼容——如果哪天要用 docker stack deploy,这个字段还在,转换成本为零。

四、配置漂移与一致性

生产环境最隐蔽的敌人是配置漂移:每台机器、每次发布之间的配置悄悄出现差异,最终在某个凌晨以诡异故障的形式爆发。漂移通常来自三个源头。

第一是镜像漂移,即上一节说的 latest 标签问题。第二是参数漂移:有人在服务器上手改了一个容器的环境变量,没有同步回配置文件,下次重建容器配置就"回到解放前"。第三是环境差异:开发、测试、生产各有一套 .env,字段对不上,行为自然对不上。

我们的对策有两条。第一条,把 compose 文件、.env 模板(注意是模板,真实密钥走 secrets)纳入版本控制,任何改动都要经过提交记录,杜绝"手改服务器";第二条,用覆盖文件机制管理环境差异——基础文件 docker-compose.yml 存放所有环境共通的定义,开发覆盖文件 docker-compose.override.yml 在本地自动生效,生产环境用显式组合 docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d 加载生产覆盖。这样"一份基础定义加按环境覆盖"的结构,本身就是对漂移的结构性防御,4.6 节会展开讲。

五、部署自动化与高可用思路

配置稳定之后,部署过程也要自动化。手动部署容易出错、效率低下,靠人肉 SSH 上去敲命令,早晚要出一次"少打了一个参数"的事故。自动化有两条线:持续集成与持续部署(CI/CD),用 Jenkins、GitLab CI、GitHub Actions 这类工具把构建、测试、部署串成流水线,代码一提交就自动走到生产;基础设施即代码(IaC),用 Terraform、Ansible 管理服务器与中间件,让"机器长什么样"也进入版本控制。两条线在本章 4.6 有详细方案,这里先记住结论:凡是重复两次以上的部署动作,都应该变成脚本或流水线。

高可用方面要诚实:Compose 本身不提供高可用。它没有故障转移、没有跨主机调度。单机场景下我们能做的是"单机内的高可用"——部署多个容器副本,用 Nginx 或 HAProxy 做负载均衡,把流量分发给多个副本,一个容器挂了其他副本继续服务;再配合健康检查,让 Docker 尽早发现故障容器。但这套方案的边界是宿主机本身,机器宕了就是宕了。跨节点的故障转移,属于 4.7 节编排选型的范畴。

生产环境的部署决策可以画成一张流程图,帮团队快速对齐方案:

六、生产上线前的常见坑

把前五节的内容收拢成一份踩坑清单,这几条是我们上线时反复撞过的。

端口与资源冲突。 多个项目共用一个 Docker 主机时,忘了端口已被占用是常态。docker compose up 报 bind 失败时先 docker ps 看谁占了端口;更省心的做法是给每个项目划独立的端口段,写进项目文档,新服务上线前先查一遍分配表。

.env 缺失。 生产机上没有 .env 文件,compose 里的 ${POSTGRES_PASSWORD} 会被解析成空字符串,数据库用空密码启动。上线流程里必须包含"校验 .env 存在且字段齐全"这一步,部署脚本里加检查,空值直接 fail,别让服务带着空配置悄悄跑起来。

depends_on 不等健康检查。 depends_on 默认只等容器启动,不等服务就绪。数据库容器起来了但还在初始化,应用已经连上来,连接失败就退出。解法是给依赖服务配 healthcheck,并让应用容器带重启策略——先启动失败,等数据库就绪后自动拉起,这是最简单也最可靠的就绪编排。

时区不统一。 部分容器设了 TZ,部分没设,日志时间差八小时,排查跨容器问题时先对不上时间线。把"所有服务都带 TZ"写进模板检查项,比事后逐个补漏省事得多。

手改服务器。 上线后图省事直接在服务器上改配置、改文件,改完不回流版本库。两周后这台机器就成了"独一无二"的机器,重建等于重新配置。规则只有一条:服务器上的任何变更都要能通过重新部署复现,否则就写进版本库再执行。

⚠️ 不要在生产上用 latest 标签。我们见过不止一次:某天镜像仓库更新了 latest,线上容器重建后行为大变,回滚时却找不到"之前那个镜像"到底长什么样。固定版本号是最便宜的保险。

💡 健康检查的探针要探业务本身。curl 一下首页比检查进程存活靠谱得多,数据库没就绪时进程照样活着,但业务已经不可用了——healthcheck 就是为这种"假活"准备的。

本章回顾

  • Compose 是单机编排工具:定位在小型应用与单节点部署,不具备自动伸缩与滚动更新能力。
  • 生产配置基线有七项:固定镜像版本、时区、重启策略、资源限制、健康检查、日志轮转、数据持久化。
  • 固定镜像 tag 是底线:latest 会漂移,固定到具体版本号才能保证可复现。
  • restart: unless-stopped 更合适:自动恢复崩溃容器,同时尊重显式停止。
  • 健康检查要探业务:interval、timeout、retries 三个参数配合,识别假活容器。
  • 配置漂移有三个来源:镜像漂移、手改参数、环境差异,对策是版本控制加覆盖文件。
  • 部署自动化有两条线:CI/CD 自动化流水线,IaC 管基础设施。
  • 高可用要诚实:Compose 只能做单机内多副本加负载均衡,跨节点故障转移要交给编排工具。

下一节我们进入安全加固——基线只是"配置正确",密钥和权限才是生产环境真正的攻防战场。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U