十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

docker-compose实战指南:从安装到部署vLLM容器编排全解析

docker-compose实战指南:从安装到部署vLLM容器编排全解析 先聊个场景你在一台刚装好的服务器上手动敲了七八条docker run把数据库、缓存、业务后端、前端容器一个个拉起来。启动顺序还不能乱环境变量不能漏端口映射不能错。好不容易全起来了过两天要更新版本又得先停这个、再改那个、最后重启稍不留神就把容器名写错直接起冲突。这时候你会发现真正缺的不是 Docker而是一个能把“整套服务”当成一个整体来管理的东西。这就是 docker-compose。网上搜 docker-compose能搜出一堆安装教程和踩坑记录但很多文章只讲“怎么装”不讲“装完怎么用”“生产环境怎么落地”。今天这篇我把从安装到实战部署 vLLM 的完整链路拆开讲重点覆盖 Debian 12、WSL 1、麒麟系统离线部署这几个典型场景顺便把配置文件和常见坑一次说透。无论是刚接触容器编排的开发者还是准备在生产环境用 compose 管理 AI 推理服务的运维这篇文章都值得你花十分钟读完。1. 先说结论docker-compose 到底解决了什么问题1.1 一个命令拉起整套服务告别到处找启动命令我见过不少团队服务部署文档写了几十页里面全是复制粘贴的docker run命令。新人接手时光是搞清楚哪个容器依赖哪个就要翻半天聊天记录。docker-compose 的核心价值就是把“多个容器的启动方式”固化成一份 YAML 文件你只需要执行docker-compose up -d就能按照你定义好的依赖关系、网络配置、卷挂载把整套服务一次性拉起来。停服务也简单docker-compose down一键清理。更重要的是这份 YAML 文件本身就是“可执行的部署文档”发版、扩容、迁移环境都围绕这一份文件来操作比零散的 shell 命令可维护太多了。1.2 compose 和 docker run 的核心差异docker run是“单容器”视角你每次操作都只针对一个容器。而 docker-compose 是“服务编排”视角它关注的是多个容器如何协同工作。举个例子一个 Web 应用可能需要一个 Nginx 容器做反向代理一个后端应用容器一个 PostgreSQL 数据库容器一个 Redis 缓存容器用docker run启动这四个容器你得分别处理网络自定义 bridge 网络、依赖关系等数据库就绪再启动后端、数据持久化每个容器都要挂卷。用 docker-compose这些全部可以在docker-compose.yml里声明式地定义而且默认就会帮你创建一个专属于这个项目的 bridge 网络容器之间可以用服务名直接互相访问不用再手动--link或者查 IP。注意docker-compose 适合“单机多容器”场景。如果你要管理多台服务器上的容器那应该考虑 Docker Swarm 或 Kubernetes那是另一个量级的编排工具。2. 安装 docker-compose 前必读版本选择与运行机制2.1 独立二进制、pip 安装还是 docker compose 插件怎么选我在不同环境里试过三种安装方式分别适用不同场景安装方式优点缺点适用场景独立二进制/usr/local/bin/docker-compose简单直接一个文件搞定不依赖 Python 环境需要手动下载和给执行权限绝大多数 Linux 服务器最通用pip 安装pip install docker-compose与 Python 生态集成版本管理方便依赖 Python 及 pip可能污染系统 Python 环境开发机或 Python 环境干净的机器Docker 插件docker compose无横线与 Docker CLI 深度集成未来主流较新版本 Docker 才支持老版本需要手动启用Docker Engine 20.10 的较新环境这里有个容易混淆的点docker-compose带横线是独立的二进制工具docker compose带空格作为 Docker 的插件是官方后来主推的方式。很多教程不会强调这两者的区别导致你在新版 Docker 环境里执行docker-compose却提示找不到命令。我个人的建议是如果是 CentOS 7、Ubuntu 18.04 这种老系统直接用独立二进制最省心如果是 Debian 12、Ubuntu 22.04 这类较新系统优先考虑用插件模式也就是docker compose。2.2 下载前先确认架构x86_64、aarch64 还是国产化平台去 GitHub Releases 页面下载 docker-compose 二进制时你会看到一堆文件什么docker-compose-linux-x86_64、docker-compose-linux-aarch64新手很容易下错。先确认服务器架构uname -m输出x86_64选linux-x86_64输出aarch64选linux-aarch64输出armv7l选linux-armv7选错架构的后果就是下载下来无法执行报Exec format error。这个错误特别坑因为它不会告诉你“文件下错了”而是让你以为系统缺了什么依赖。我踩过两次这个坑所以现在每次下载前都会先跑一遍uname -m。下载时如果服务器访问外网慢可以直接用国内的镜像加速地址把下载链接里的github.com替换成mirror.ghproxy.com之类的代理前缀。比如curl -L https://mirror.ghproxy.com/https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose2.3 离线环境安装麒麟系统的处理思路这两年国产化替代推进不少项目的生产环境用的是麒麟Kylin系统。这类环境通常无法直接访问外网下载二进制不方便。处理思路和普通 Linux 离线安装一样核心是先在一台能联网的机器上下好对应文件再拷贝到目标机器。具体的操作路径在联网机器上下载docker-compose-linux-x86_64麒麟 x86 版或docker-compose-linux-aarch64麒麟飞腾版。通过 U 盘、内网传输工具等把文件拷贝到目标机器。放到/usr/local/bin/目录重命名并赋权mv docker-compose-linux-x86_64 /usr/local/bin/docker-compose chmod x /usr/local/bin/docker-compose如果目标是 ARM 架构的麒麟系统比如飞腾处理器记得下载 aarch64 版本。我帮朋友处理过一次飞腾平台的离线部署最开始下错了 x86_64 版本一执行就报错所以架构确认这一步千万别省。注意麒麟系统上如果 Docker 是离线安装的compose 的安装路径最好和 Docker CLI 保持一致。可以用which docker先确认 Docker 装在哪里再把 compose 放在同一个 bin 目录下避免 PATH 搜索不到。3. Debian 12 安装 docker-compose 的完整过程3.1 标准安装流程二进制方式Debian 12 自带的 Docker 版本通常比较新安装 docker-compose 最稳妥的方式还是独立二进制。完整流程如下# 1. 更新系统可选但建议 sudo apt update # 2. 确认安装了 curl sudo apt install -y curl # 3. 下载 docker-compose 二进制 sudo curl -L https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose # 4. 赋予执行权限 sudo chmod x /usr/local/bin/docker-compose # 5. 验证安装 docker-compose --version如果输出类似Docker Compose version v2.23.0说明安装成功。如果你用的是较新版本的 Docker也可以直接用插件模式安装无需额外下载 compose 二进制因为新版 Docker 已经内置了 compose 插件只需要把docker-compose命令软链到 Docker 插件目录sudo mkdir -p /usr/local/lib/docker/cli-plugins sudo ln -s /usr/local/bin/docker-compose /usr/local/lib/docker/cli-plugins/docker-compose这样既可以用docker-compose命令也可以用docker compose命令两全其美。3.2 权限与路径问题处理下载完二进制最常见的报错是Permission denied。这是因为/usr/local/bin/目录默认是 root 所有普通用户没有写权限。如果下载时没用sudo后续 chmod 和执行都会遇到权限问题。我的建议是下载、赋权都用sudo一步到位然后验证。另外要注意 PATH 环境变量。有些系统的/usr/local/bin不在 PATH 里虽然少见会导致命令找不到。执行echo $PATH确认/usr/local/bin在其中。如果不在可以用软链接把 compose 接到/usr/bin/下sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose3.3 验证安装version 命令到底看什么docker-compose --version输出的是 compose 自身的版本号不代表 Docker 引擎的版本。要同时确认 Docker 引擎正常需要另外执行docker version和docker compose version。我习惯这样一次验证docker version --format {{.Server.Version}} docker-compose version两个命令都能正常输出说明 Docker 服务运行正常compose 工具可用。如果docker version提示无法连接到 Docker daemon那问题在 Docker 服务本身不在 compose。4. WSL 1 下 command not found 的排查与解决4.1 为什么 WSL 1 下会报这个错很多 Windows 用户在 WSL 里执行docker-compose时会遇到这样一条报错The command docker-compose could not be found in this WSL 1 distro. We recommend the Docker Desktop experience for Windows.这条信息的核心指向是当前发行版运行在 WSL 1 模式下而 Docker 的某些特性尤其是 Docker Desktop 集成在 WSL 1 下支持不完整。WSL 1 使用的是系统调用翻译层对 Linux 内核功能的支持不如 WSL 2 完整Docker 官方推荐的方案是在 WSL 2 模式下用 Docker Desktop或者在 WSL 2 发行版内部安装原生的 Docker Engine。如果你的项目必须在 WSL 1 下工作比如公司电脑的组策略禁用了 WSL 2那也不是完全没有办法。你可以像在普通 Linux 上一样安装 Docker Engine 和 docker-compose 独立二进制绕开 Docker Desktop 集成。但需要注意的是WSL 1 下有些容器网络功能可能表现异常尤其是涉及自定义 iptables 规则或特定端口转发时。4.2 在 WSL 2 和 WSL 1 下的安装差异WSL 2 是一个轻量级虚拟机内核完整Docker 可以正常使用 Linux 内核特性。WSL 1 则是一个兼容层。两者在安装 docker-compose 时的主要差异是WSL 2可以直接安装 Docker Desktop 并启用 WSL 2 集成也可以安装 Docker Engine再用独立二进制安装 compose基本和 Debian 服务器一致。WSL 1Docker Desktop 的 WSL 集成对 WSL 1 支持有限通常需要你自己在 WSL 1 发行版里安装 Docker Engine。安装 Docker Engine 本身有些系统服务如 systemd在 WSL 1 下无法正常启动需要手动启动 dockerd。如果只是开发环境最简单的方案是升级到 WSL 2wsl --set-version 发行版名称 2如果公司电脑无法升级那就在 WSL 1 里手动启动 Dockersudo service docker start然后再用独立二进制方式安装 docker-compose这样可以临时绕过报错。4.3 已安装却找不到命令的常见原因还有一种情况你明明下载了 docker-compose也赋了执行权限但执行时还是提示command not found。我归纳了三个高频原因PATH 不包含安装目录如果你把 compose 下载到家目录比如~/docker-compose那执行时要用./docker-compose或~/docker-compose。要全局使用必须放到/usr/local/bin或用sudo mv移动过去。文件名不是docker-compose下载时如果链接跳转后保存成了docker-compose-linux-x86_64没有重命名执行docker-compose自然找不到。bash 缓存某些 shell 会话会缓存命令路径刚把二进制放进去后可能在当前会话中找不到。执行hash -r刷新缓存或者重新打开终端。这些情况在 WSL 里尤其常见因为 WSL 的 PATH 继承自 Windows可能对 Linux 路径的支持顺序有影响。可以在~/.bashrc或~/.zshrc里显式追加export PATH$PATH:/usr/local/bin然后source ~/.bashrc生效。5. docker-compose 核心配置拆解从入门到实战5.1 compose 文件结构services、networks、volumes一份标准的docker-compose.yml顶层由三个核心部分组成version: 3.8 services: app: image: nginx:latest ports: - 8080:80 networks: default: driver: bridge volumes: app-data:其中version是 compose 文件格式版本通常用3.8或3.9新版本 Docker 也支持不带version字段。services是核心定义每个容器的配置。networks和volumes分别是自定义网络和数据卷如果使用默认值也可以省略。我见过很多初学者把version当成 Docker 版本写成version: 19.03这是不对的。compose 文件里的version指的是 compose 规范版本不是 Docker 引擎版本。5.2 常用指令逐字段解析services下每个服务可以配置很多指令我挑几个生产环境高频使用且容易出错的字段来说image指定镜像名和标签。生产环境建议写固定版本比如postgres:15.4不要写latest否则更新时容易引入不兼容变更。container_name指定容器名不写的话 compose 会用“项目名_服务名_序号”的格式自动命名。build如果服务需要本地构建镜像比如build: ./myappcompose 会先构建再启动。生产环境通常用image因为镜像应该由 CI 系统构建好再推送。ports端口映射格式是宿主机端口:容器端口。注意如果宿主机端口冲突compose 启动会失败。environment环境变量可以直接写键值也可以引用.env文件。volumes卷挂载格式是宿主机路径:容器路径。生产环境数据持久化必须用卷否则容器删除数据就没了。depends_on声明依赖关系比如app依赖dbcompose 会先启动db。不过要注意depends_on只控制启动顺序不等待服务真正就绪这是很多人踩坑的地方。restart定义容器退出后的重启策略。networks把服务加入指定网络。healthcheck定义健康检查命令生产环境强烈建议配置。5.3 环境变量与 .env 文件的使用很多配置项不想写在 YAML 里尤其是密码、端口这类环境相关的参数。compose 支持在项目目录下放一个.env文件里面用KEYVALUE格式定义变量然后在docker-compose.yml里用${KEY}引用。比如.env文件POSTGRES_PASSWORDmysecretpassword POSTGRES_PORT5432docker-compose.yml里services: db: image: postgres:15.4 environment: POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} ports: - ${POSTGRES_PORT}:5432这样做的好处是不同环境开发、测试、生产只需要维护不同的.env文件docker-compose.yml保持一致避免在多个 YAML 文件之间反复复制粘贴。注意.env文件不要提交到 Git 仓库尤其是包含密码的文件。建议在.gitignore里添加.env并提供一个.env.example作为模板。6. 生产环境部署实战用 docker-compose 拉起 vLLM 服务6.1 为什么要用 compose 部署 vLLMvLLM 是当前比较热门的 LLM 推理加速框架很多项目用它部署大模型推理服务。vLLM 本身是 Python 服务通常用vllm/vllm-openai镜像运行。生产环境部署 vLLM 时往往不是只跑一个 vLLM 容器还可能需要一个模型下载预热容器或脚本一个 Nginx 反向代理做 API 网关一个 Prometheus 抓取推理指标一套日志收集组件把这些组件全部用docker run管理会非常痛苦。用 docker-compose可以把 vLLM 核心服务、网络、日志、健康检查一次性声明好后续更新镜像版本、修改模型参数只需要编辑 YAML 文件再执行一条命令。6.2 编写 vLLM 的 compose 文件下面是一份我在生产环境用过的 vLLM compose 配置已经做了脱敏和简化version: 3.8 services: vllm: image: vllm/vllm-openai:v0.4.2 container_name: vllm-server command: - --model - /models/llama-2-7b-chat-hf - --served-model-name - llama2-7b - --host - 0.0.0.0 - --port - 8000 - --tensor-parallel-size - 2 - --gpu-memory-utilization - 0.9 ports: - 8000:8000 volumes: - /data/models:/models - /data/vllm-cache:/root/.cache environment: - HF_HOME/root/.cache - NCCL_DEBUGINFO deploy: resources: reservations: devices: - driver: nvidia count: 2 capabilities: [gpu] restart: unless-stopped healthcheck: test: [CMD-SHELL, curl -f http://localhost:8000/health || exit 1] interval: 30s timeout: 10s retries: 5 start_period: 300s关键点拆解一下command用列表形式传参避免 shell 转义问题。tensor-parallel-size: 2表示用 2 块 GPU 做张量并行。这个参数要根据 GPU 显存和模型大小调整。如果只有 1 块 GPU改成 1 或者删除。gpu-memory-utilization: 0.9表示允许 vLLM 占用单卡 90% 的显存。显存紧张时可以调低比如 0.7。--served-model-name是暴露给客户端访问的名字可以不和物理模型名称一致。healthcheck很重要生产环境如果没有健康检查负载均衡器就无法自动摘除异常节点。deploy.resources声明需要 2 块 NVIDIA GPUCompose 会调用 Docker 的 GPU 调度能力。6.3 启动、扩缩容与更新流程启动服务docker-compose up -d查看状态docker-compose ps查看日志docker-compose logs -f vllm生产环境最常用的两个操作是“更新镜像”和“扩容”。更新镜像版本docker-compose pull vllm docker-compose up -d vllm如果修改了command参数比如换模型、调整并行度只需要修改 YAML然后重新应用docker-compose up -dCompose 会检测到配置有变化自动重建对应容器。如果单机只有一台 GPU 服务器扩缩容主要靠调整tensor-parallel-size或者增加副本数。但要注意vLLM 是 GPU 密集型服务单机横向扩展replicas意义不大因为多副本会争抢 GPU 显存。真正需要横向扩展时应该用多机部署加负载均衡那就不是单机 compose 能解决的问题了。7. 常见问题与排查技巧实录7.1 command not found 速查遇到 command not found按照下面顺序排查执行which docker-compose确认是不是有同名命令冲突。执行echo $PATH确认安装目录在不在 PATH 中。执行ls -l /usr/local/bin/docker-compose确认文件存在且有x执行权限。执行file /usr/local/bin/docker-compose确认文件架构正确。如果以上都被排除还有一个冷门原因文件下载不完整被截断了。表现为文件大小异常或者执行时提示binary file exec format error。解决方法是删掉重新下载。7.2 镜像拉取缓慢或超时生产环境拉镜像经常遇到超时尤其是大模型镜像动辄几个 GB。这里的坑往往不在 compose 本身而在 Docker daemon 的镜像源配置。国内服务器可以配置镜像加速器修改/etc/docker/daemon.json{ registry-mirrors: [ https://docker.mirrors.ustc.edu.cn, https://hub-mirror.c.163.com ] }修改后重启 Dockersudo systemctl restart docker注意有些镜像比如 vLLM可能带 GPU 相关的 CUDA 层体积更大。如果拉取总是超时可以试着在 Dockerfile 或镜像仓库中寻找体积更小的变体比如基于slim或cuda-base的版本。注意修改镜像加速器可能有兼容性问题配置前先确认加速器可用避免拉取失败影响生产部署。7.3 容器启动失败与日志排查compose 启动容器失败时第一时间不要反复up -d先查日志docker-compose logs --tail100 服务名日志能直接告诉你大部分原因。常见几类端口被占用报错信息里有address already in use去查宿主机端口占用。挂载目录不存在vLLM 模型的路径如果不存在容器会启动后退出。权限不足挂载目录需要容器内进程有读权限检查目录权限。GPU 相关如果机器没有 NVIDIA GPU却配置了 GPU 资源Docker 会报错要么装好 nvidia-container-toolkit要么去掉 GPU 配置先用 CPU 模式测试。7.4 热更新与数据持久化注意点docker-compose up -d时如果镜像没变化、配置没变化容器不会被重建。只有你改了镜像标签、环境变量或挂载它才会重建对应服务。这有时候会带来困惑比如你改了.env文件的端口但docker-compose up -d没有生效。这时候可以显式加参数强制重建docker-compose up -d --force-recreate数据持久化方面volumes声明的作用是把数据放在 Docker 管理的卷或宿主机目录里。如果使用具名卷数据在容器删除后仍然存在但要注意卷目录里的数据不容易直接找到生产环境建议直接挂载宿主机路径比如/data/models:/models这样备份和排查更直观。最后再分享一个小技巧升级 docker-compose 到新版本前先去官方 Release 页面看一下 Changelog别盲目更新。有些大版本会废弃旧字段比如version字段在新版 compose 规范中已经变成可选项你如果保留也没问题但哪天升级后发现某些配置不识别先去查版本兼容性再检查 YAML 里的字段是否过时。我在一次升级中遇到过docker-compose up直接提示某个指令不支持回退到旧版本才恢复。生产环境的工具链稳定比新重要更新前一定要在测试环境验证一遍。
返回列表