尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Docker Compose部署实战:从环境规划到服务编排与故障排查
网上讲 Docker 部署的教程一抓一大把但多数都只讲到“能装上、能启动”就没了。真正到了自己要部署项目的时候才发现环境判断、目录规划、Compose 编排、报错排查这些环节全是坑。这套 Docker Docker Compose 部署教程是我前后在几台机器上反复验证过的从 Linux 服务器到 Windows 开发机都跑通了今天完整整理出来适合刚接触容器化的新手也适合已经会 docker run 但还没系统用过 Compose 的朋友。1. 部署前的判断题这台机器适不适合跑 Docker我不太建议拿到机器就急着敲安装命令。先花十分钟搞清楚三件事能帮你后面少折腾两个小时。1.1 先确认操作系统与内核要求Docker Engine 对 Linux 内核版本有硬性要求64 位系统、内核版本不低于 3.10但这是很早以前的门槛了现在主流发行版基本都远超这个标准。真正要注意的是系统是 systemd 还是 SysV init虽然 Docker 官方安装脚本能自动处理但如果你在旧系统上手动安装init 系统的差异会让你多踩很多坑。我在部署前通常用这几条命令快速摸底cat /etc/os-release # 查看发行版 uname -r # 查看内核版本 systemctl --version # 确认 systemd 可用Ubuntu 22.04、Debian 12、Rocky Linux 9 这几代系统我都实测过按官方源安装基本不会出问题。如果拿到的是 CentOS 7 这种比较老的系统建议先确认内核在 3.10 以上再继续同时注意旧版本 Docker 和容器运行时之间的兼容性。1.2 端口与目录规划最容易返工的一步很多新手部署失败不是 Docker 没装好而是没想清楚服务和宿主机的端口映射、数据目录映射关系。我建议在装 Docker 之前就把两个问题写下来这个项目要暴露哪些端口哪些数据必须持久化规划项建议做法原因端口避开 80/443 之外的常见占用统一规划端口段MySQL、Redis、Nginx 等默认端口极易冲突数据目录统一放到 /opt/apps 或 /data 下按项目名分目录备份、迁移、排查都方便日志容器日志重定向或配置 log rotation不限制的话日志能占满磁盘举个例子我习惯把所有 Compose 项目放在/opt/apps/项目名下面每个项目内部再分data、conf、logs三个子目录。这样整个机器的容器数据一目了然出问题也能快速定位。1.3 版本锁定思路不要盲目追最新Docker 的版本节奏其实不算激进但 Docker Compose 插件的版本和 Docker Engine 之间偶尔会有兼容性问题。我的建议是服务器上用稳定版不要碰 nightly 或 rc 版本。生产环境锁定大版本比如 Docker 24.x 或 25.x 系列等当前版本运行稳定后再考虑升级。通过 apt 或 dnf 安装时可以显式指定版本号避免自动拉取到预期之外的版本。这样做的深层原因是容器部署本来就强调“环境一致”如果 Docker 本身经常变那“我的环境和生产一致”这个目标就很难保证。2. Docker 与 Compose 安装两条路线实测Linux 服务器和 Windows 开发机走的是完全不同的安装路线我都实测过分开说。2.1 Linux 服务器用官方源装 Engine 和 Compose 插件这里以 Ubuntu/Debian 和 Rocky/CentOS 为例。Ubuntu 系先装依赖并添加 Docker 官方 GPG 密钥和 apt 源sudo apt update sudo apt install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod ar /etc/apt/keyrings/docker.gpg echo \ deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release echo $VERSION_CODENAME) stable | \ sudo tee /etc/apt/sources.list.d/docker.list /dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginRocky / CentOS 用 yum 源sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin注意这里安装的是docker-compose-plugin安装后命令是docker compose带空格不是老的docker-compose带连字符。很多人在这里迷糊其实新版 Docker 已经内置了 Compose v2直接用docker compose就好。装完先启动并验证sudo systemctl enable docker --now docker --version docker compose version2.2 配置镜像加速器让拉取速度恢复正常这一步虽然不是必需的但在国内服务器上不配的话拉官方镜像经常慢到怀疑人生。Docker 的镜像加速本质上是通过配置registry-mirrors让守护进程从公共镜像站拉取。修改/etc/docker/daemon.json{ registry-mirrors: [ https://docker.m.daocloud.io, https://docker.1panel.live, https://hub.rat.dev ] }保存后重启 Dockersudo systemctl restart docker这类公共加速地址存在不定期变动的可能失效了换一个即可。如果你有阿里云或腾讯云账号到容器镜像服务控制台拿到专属加速地址稳定性更好。配置完可以用docker info查看 Registry Mirrors 是否生效。2.3 Windows 环境Docker Desktop 的虚拟化前提Windows 上通常通过 Docker Desktop 使用 Docker但它依赖 WSL2 或 Hyper-V。安装前先确认两件事BIOS 里虚拟化有没有开启Windows 功能里“虚拟机平台”和“适用于 Linux 的 Windows 子系统”有没有启用。如果安装后启动报 “Docker Desktop failed to start because virtualisation support wasnt detected”十有八九是虚拟化没开全。此时需要进入 BIOS开启 Intel VT-x 或 AMD-V。以管理员身份运行 PowerShell启用 WSL2 相关功能后重启dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart重启后运行wsl --set-default-version 2。Docker Desktop 启动成功后Settings → Docker Engine 里同样可以配置镜像加速地址JSON 格式和 Linux 上一样。Windows 版最大的优势是可以直接映射本机端口访问容器服务对本地开发很友好。3. 一个能直接照抄的 docker-compose.yml前后端 数据库 缓存这一节我带你完整跑通一个典型服务栈包含一个简单的后端 API、Nginx 反向代理、MySQL 8.0 和 Redis 7。这套结构基本涵盖了大多数中小型项目的部署形态。3.1 为什么用 Compose 而不是一长串 docker run直接用docker run部署多个容器最直观的问题是命令太长、依赖关系靠脑子记。比如你要先启动 MySQL等它初始化完再启动 API还要把网络打通、数据卷挂载对上这些全靠手工操作非常容易出错。Compose 的价值在于把“我要跑哪几个服务、它们之间怎么连接、数据放哪里、挂了怎么重启”这些声明式地写在一个 YAML 文件里。一条docker compose up -d就能拉起整个服务栈一条docker compose down就能清理干净。它把部署变成了可版本化的配置团队协作时 git 里放一个 compose 文件任何人拉下来都能复现环境。3.2 先写一个最简单的后端镜像为了让教程完整我先准备一个极简 Node.js API 的DockerfileFROM node:20-alpine AS build WORKDIR /app COPY package*.json ./ RUN npm install --registryhttps://registry.npmmirror.com COPY . . FROM node:20-alpine WORKDIR /app ENV NODE_ENVproduction COPY --frombuild /app ./ EXPOSE 3000 CMD [node, index.js]这个 Dockerfile 用了多阶段构建第一阶段装依赖第二阶段只拷贝产物镜像体积会小很多。实际项目中你可能还需要非 root 用户运行和 HEALTHCHECK这里为了篇幅先简化。package.json里指定express依赖index.js写一个返回当前时间的接口这部分我就不贴全了大家都会写。3.3 compose 文件逐段拆解下面是完整的docker-compose.yml以myapp项目为例services: mysql: image: mysql:8.0 container_name: myapp-mysql restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: root_pass_123 MYSQL_DATABASE: myapp MYSQL_USER: myapp_user MYSQL_PASSWORD: user_pass_123 volumes: - ./data/mysql:/var/lib/mysql ports: - 3306:3306 healthcheck: test: [CMD, mysqladmin, ping, -h, localhost, -uroot, -proot_pass_123] interval: 10s timeout: 3s retries: 5 redis: image: redis:7-alpine container_name: myapp-redis restart: unless-stopped volumes: - ./data/redis:/data ports: - 6379:6379 command: redis-server --appendonly yes api: build: ./api container_name: myapp-api restart: unless-stopped environment: DB_HOST: mysql DB_PORT: 3306 DB_NAME: myapp DB_USER: myapp_user DB_PASSWORD: user_pass_123 REDIS_HOST: redis REDIS_PORT: 6379 ports: - 3000:3000 depends_on: mysql: condition: service_healthy redis: condition: service_started nginx: image: nginx:1.27-alpine container_name: myapp-nginx restart: unless-stopped ports: - 8080:80 volumes: - ./conf/nginx.conf:/etc/nginx/conf.d/default.conf:ro depends_on: - api几个关键点值得展开解释services 下的每个服务名本身就是容器网络内的 DNS 名称。API 容器里连接数据库时DB_HOST填mysql就行不需要填 localhost 或 IP。这是 Compose 默认创建的网络自动提供的各服务通过服务名互相访问和宿主机网络隔离但互通映射端口。depends_on配合condition: service_healthy是我强烈推荐的做法。单纯用depends_on只能保证 MySQL 容器先启动但 MySQL 容器启动过程有初始化阶段如果 API 在数据库就绪前就开始连接会报连接失败然后退出。加上 healthcheck 之后Compose 会等 MySQL 健康检查通过才启动 API从机制上解决启动顺序问题。./data/mysql:/var/lib/mysql这种相对路径挂载很直观。宿主机上的data/mysql目录会存数据库文件删掉容器数据还在。这是容器部署和传统部署最大的思维差异容器是“有状态进程的宿主”数据必须外置。3.4 启动、验证、滚动更新的完整命令流在/opt/apps/myapp目录下执行docker compose up -d docker compose ps第一次启动会自动拉取镜像、构建 api 镜像然后把四个服务按依赖顺序带起来。docker compose ps能看到每个服务是否 healthyNAME IMAGE STATUS myapp-mysql mysql:8.0 Up (healthy) myapp-redis redis:7-alpine Up myapp-api myapp-api:latest Up myapp-nginx nginx:1.27-alpine Up验证接口curl http://localhost:8080/api/ping日常更新代码后只需要重新构建并滚动替换 API 容器docker compose build api docker compose up -d apiCompose 会对配置和镜像做 diff只重建变化的部分不会把数据库和 Redis 容器一起重启这对线上服务非常友好。4. 亲测中踩过的坑从报错到恢复的完整排查链路这一节应该是很多人最需要的。我在不同机器上反复部署踩过的坑五花八门挑几个最有代表性的完整讲一遍排查链路。4.1 Windows 上 Docker Desktop 起不来虚拟化报错这是 Windows 部署最典型的报错现象是启动 Docker Desktop 后弹窗提示 “Virtualisation support wasnt detected” 然后退出。我见过三种原因现象根因处理方法Docker Desktop 启动弹虚拟化错误BIOS 里 VT-x/AMD-V 关闭进 BIOS 开启虚拟化Windows 功能缺“虚拟机平台”WSL2 依赖项未启用dism 命令启用并重启装完 WSL 但仍报错WSL 版本是 1wsl --set-default-version 2一个容易忽略的细节是Windows 的“Hyper-V”和“虚拟机平台”是两个独立功能Docker Desktop 新版对“虚拟机平台”更依赖。如果开了 Hyper-V 但没开虚拟机平台同样可能报错。检查时两条命令都跑一遍别漏。4.2 连不上 Docker APInpipe 报错另一个 Windows 高频报错是Failed to connect to the Docker API at npipe:////./pipe/docker-desktop-linux这个报错字面意思是连不上 Docker Engine 的命名管道。通常不是 Docker Desktop 没装好而是 Engine 没真正起来。我建议按顺序排查看系统托盘里 Docker Desktop 图标如果是红色或黄色等它转完。wsl --list --verbose看 docker-desktop 发行版是不是 Running如果 Stopped 就wsl --shutdown再重开 Docker Desktop。还没有的话以管理员身份运行net stop com.docker.service再启动 Docker Desktop。最坏情况下把 Docker Desktop 退出删掉%LOCALAPPDATA%\Docker下的缓存目录再启动。这个目录是引擎的临时状态删了不影响已有的镜像和容器镜像在docker-desktop-data发行版里。4.3 容器启动后马上退出别猜先看日志我见过最多的情况是docker compose up -d后ps一看容器 Exited。这时候最忌讳盲目重启正确姿势是看日志docker compose logs api日志会直接告诉你真实原因。比如 API 连不上 MySQL日志里会有一堆ECONNREFUSED之类的网络错误也可能是环境变量名拼错导致连接了不存在的数据库名。如果日志显示端口被占用用下面的命令定位sudo lsof -i :3306常见坑是宿主机本来就有 MySQL把 3306 占了。解决方案很简单宿主机 MySQL 换成 3307或者 compose 里把映射端口改成3307:3306。我不建议把宿主机自带的 MySQL 直接停掉除非你确定不再需要它。4.4 数据卷权限与容器内 UID 的错位这个坑非常隐蔽。MySQL 容器里的mysql用户 UID 是999如果你在宿主机上创建了./data/mysql目录但它的 owner 是 rootMySQL 容器首次初始化时会因为无法写目录而失败。更恶心的是这种错误有时不在初次报而是容器重启后才暴露。排查命令是看目录权限ls -ln data/mysql如果属主信息不对直接改成容器内用户的 UIDsudo chown -R 999:999 data/mysql相同的问题在 Redis、GitLab 这些镜像里也可能出现GitLab 镜像内部用户 UID 是1000。遇到容器启动后马上退出先看日志再看挂载目录权限两个方向排查基本能解决 80% 的问题。5. 部署技能如何延伸到更多场景从 Harbor 到 Dify 的思路学 Comple 不只是为了部署自己的小项目。现在大量开源项目都提供官方 compose 文件学会读 compose 文件你会发现部署一个复杂系统从“天方夜谭”变成“照葫芦画瓢”。5.1 通用三步走找文件、改配置、启动不管部署的是 Harbor、Dify、GitLab、Jellyfin 还是青龙面板流程高度统一。以 Dify 为例它是一个比较复杂的 LLM 应用开发平台包含 API server、Worker、Web、PostgreSQL、Redis、Sandbox、Nginx 等多个服务官方已经提供了完整的docker-compose.yaml。第一步把项目代码拉到服务器git clone https://github.com/langgenius/dify.git cd dify/docker cp .env.example .env第二步修改.env里的关键配置。Dify 这类项目把几乎所有可调参数都放进.env文件compose 文件里通过${VARIABLE}方式引用。你需要关注的是端口、密钥、存储路径其他保持默认即可。第三步启动docker compose up -dDify 首次启动会非常久因为要构建多个镜像、下载模型依赖。这时候别慌用docker compose logs -f nginx观察启动进度。5.2 Harbor 的特殊之处证书和 HTTPS 不能跳过Harbor 是另一个典型代表它作为企业级镜像仓库启动前必须配置hostname和 HTTPS 证书。如果你贪图省事直接用 HTTPHarbor 会在客户端配置上给你留个大坑因为 Docker 客户端默认不允许推送到非 HTTPS 的 registry。至少你需要在harbor.yml里正确填写 hostname并生成自签名证书或配置受信证书。之后运行./install.sh安装。Harbor 的核心价值是镜像管理它帮你把仓库、用户、权限、复制规则都集成在一个 Web 界面里内部用起来非常顺手。5.3 常用运维命令速查与 docker 服务自启部署完成只是开始后面维护才是长期工作。我把平时用得最多的命令整理一张速查表场景命令查看所有容器状态docker compose ps看某个服务实时日志docker compose logs -f api进入容器内部调试docker compose exec api sh重启某个服务docker compose restart nginx停掉并删除整个服务栈docker compose down停掉并删除数据卷谨慎docker compose down -v清理悬空镜像和构建缓存docker system prune -a开机自启这块有两个层次。第一层是 Docker 服务本身开机启动安装时systemctl enable docker已经处理了。第二层是容器随 Docker 启动而恢复靠的是 compose 文件里的restart: unless-stopped我强烈建议每个服务都加上这样服务器重启后容器能自动恢复不用手动一个个拉起来。最后再分享一个我个人的习惯每次改动 compose 文件或.env之前先备份一份并把当前的数据卷目录打个快照。比如 MySQL 数据目录直接cp -r data/mysql data/mysql_bak_$(date %F)。容器部署最大的便利就是环境可重建但数据是不可再生资源备份这一步花不了几分钟能在出问题时把你从绝望边缘拉回来。部署这事跑起来不算本事能稳定运行、随时备份、出了问题快速恢复才是真正有用的能力。
RELATED

相关推荐

手写Python滑模控制器:从理论到可调参的工程实现

手写Python滑模控制器:从理论到可调参的工程实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/9/19 6:53:13
uni-app x 蒸汽模式鸿蒙平台性能基准测试深度解读:4050 元素渲染与死亡长列表帧率实测

uni-app x 蒸汽模式鸿蒙平台性能基准测试深度解读:4050 元素渲染与死亡长列表帧率实测

uni-app x 蒸汽模式鸿蒙平台性能基准测试深度解读:4050 元素渲染与死亡长列表帧率实测 【免费下载链接】uni-app A cross-platform framework using Vue.js 项目地址: https://gitcode.com/gh_mirrors/un/uni-app uni-app x 蒸汽模式(vapor&#…

📅 2026/9/19 6:48:12
tsParticles Blend 插件:粒子混合模式(globalCompositeOperation)配置与实现原理全解析

tsParticles Blend 插件:粒子混合模式(globalCompositeOperation)配置与实现原理全解析

tsParticles Blend 插件:粒子混合模式(globalCompositeOperation)配置与实现原理全解析 【免费下载链接】tsparticles tsParticles - Easily create highly customizable JavaScript particles effects, confetti explosions and fireworks a…

📅 2026/9/19 6:48:12
MORE NEWS

更多资讯

📰

详解半导体集成电路QML认证:从MIL-PRF-38535到全流程落地

简介:一份关于半导体集成电路QML认证要求的研究文献,基于GJB 7400—2011《合格制造厂认证用半导体集成电路通用规范》展开分析,适合军用电子元器件认证机构、集成电路设计制造单位及质量可靠性工程师参考。内容首先梳理了当前军标实施中的三类…

📰

Chrome插件开发工具选型:同一把 TaoToken Key,从豆包切到 Codex 问

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

StarRocks CREATE ANALYZE 完全指南:自定义 CBO 统计信息自动采集任务

StarRocks CREATE ANALYZE 完全指南:自定义 CBO 统计信息自动采集任务 【免费下载链接】starrocks The worlds fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, St…

📰

当 Cohere 返回 429,TaoToken 侧要改什么

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

FIDIC EPC银皮书英文版.doc条款解析与检索

简介:这份资源是FIDIC设计采购施工(EPC)合同条件银皮书的英文原版文档,面向国际工程项目管理人员、合同工程师、造价与法务人员,以及备考FIDIC相关资格考试或从事海外EPC总承包业务的学习者,用于查阅权威合…

📰

Flutter OHOS 滑动卡顿丢帧时延全链路分析与优化实践

Flutter OHOS 滑动卡顿丢帧与时延问题分析指南去年接手一个在鸿蒙(OHOS)设备上跑 Flutter 的项目,测试同事递过来一台手机,语气平淡地说“你滑一下这个列表”。我滑了一下,心里凉了半截:列表滚动像在放幻灯…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬