跳转到内容

Docker 宿主虚拟机 ​

Docker 能跑在 PVE 的虚拟机里,也能跑在 LXC 容器里。这篇只讲虚拟机方案怎么规划——它是官方支持、兼容性最好的做法,也是大多数人应该默认选择的方案。

适合谁 ​

你的情况适不适合
要跑一堆 Compose 编排的服务,不想为每个服务单独建 LXC适合,这是虚拟机方案最大的优势
已经很熟悉 LXC,愿意折腾 nesting/keyctl 和 UID 映射排查权限问题可以考虑 LXC 方案,但本文不展开,见下文
容器需要用到内核特性、iptables、或者不确定的第三方镜像用虚拟机更省心,隔离更彻底

为什么优先推荐虚拟机而不是 LXC

虚拟机有自己独立的内核,Docker 依赖的 overlay 文件系统、cgroups、命名空间都在一个完整内核里工作,不存在兼容性问题。LXC 里跑 Docker需要手动开启 nesting 和 keyctl 两个选项,而且非特权容器的 UID 映射可能和 Docker 自己的用户命名空间冲突,导致数据卷权限报错——这类问题排查起来比直接开一台虚拟机费时得多。

选型的通用判断标准见容器还是虚拟机:Docker 场景下「不确定内核特性是否兼容」这一条,虚拟机赢面更大。

资源规划 ​

项建议起点说明
vCPU2–4按容器数量和负载调整
内存4 GB 起每个容器的实际占用差异很大,先观察 docker stats 再加
系统盘32 GB只放操作系统,不放容器数据
数据盘单独一块,按需见下文,这是本文最重要的一条建议
气球驱动可以开Docker 宿主对内存动态回收不算敏感,和数据库/NAS 虚拟机不同

把容器数据单独分盘的理由

Docker 的镜像、容器可写层和数据卷默认都存在 /var/lib/docker 下,在系统盘所在的根分区里。容器数据涨起来没有上限——一次日志失控或者一个下载类容器的卷写满磁盘,会连累根分区,导致系统本身也出问题(无法写日志、无法登录)。

单独给一块虚拟磁盘、挂载到 /var/lib/docker(或者用 Docker 的 data-root 配置指过去),写满的是数据盘而不是系统盘,出问题时恢复也更简单:只需要处理这块盘,不影响系统。

创建与安装 ​

按创建第一个虚拟机的通用建议创建一台 Debian 或 Ubuntu(也可以用Debian / Ubuntu 云镜像模板十秒钟开一台)。System 页不需要 TPM,Machine 用默认的 q35 或 i440fx 均可。

装完系统后,在客户机内部加一块数据盘并挂载:

sh
# 在虚拟机内部执行,<数据盘设备> 用 lsblk 确认,通常是新加的那块(例如 /dev/sdb)
lsblk
mkfs.ext4 /dev/sdb
mkdir -p /var/lib/docker
mount /dev/sdb /var/lib/docker
echo '/dev/sdb /var/lib/docker ext4 defaults,noatime 0 2' >> /etc/fstab

先挂载再装 Docker,顺序不能反

如果 Docker 已经在 /var/lib/docker 里写了数据再挂载新盘,旧数据会被新盘的空目录「盖住」(挂载点覆盖)。先建好挂载点、挂好盘,再装 Docker,或者用 data-root 配置项指向一个还没使用过的新路径,避免手工搬迁数据。

安装 Docker Engine 按照 Docker 官方为你的发行版提供的安装脚本或仓库配置进行,具体命令随发行版版本变化,以 Docker 官网当前文档为准。

第一次启动之后 ​

安装 guest agent(做法和其他 Linux 客户机一样,见 VirtIO 驱动与 QEMU Guest Agent):

sh
# 在虚拟机内部执行
apt update && apt install -y qemu-guest-agent
systemctl enable --now qemu-guest-agent

确认 Docker 使用的存储驱动和数据目录符合预期:

sh
# 在虚拟机内部执行
docker info | grep -E "Storage Driver|Docker Root Dir"

Storage Driver 应该是 overlay2(默认且推荐),Docker Root Dir 应该指向你挂载的数据盘路径。

ZFS 存储上的虚拟机磁盘怎么选文件系统

宿主机用 ZFS 存放虚拟机磁盘(zvol 或数据集)不影响这一步——虚拟机看到的仍然是一块普通磁盘,客户机内部照常格式化成 ext4 即可。overlay2 需要的是客户机内部文件系统的支持,和宿主机存储类型无关。不建议让 overlay2 直接跑在宿主机透传进来的 ZFS 数据集上,会有性能损失。

检查结果 ​

  1. docker run hello-world 能正常拉取镜像并运行成功,说明网络和存储驱动都工作正常。
  2. docker info | grep "Storage Driver" 显示 overlay2。
  3. df -h /var/lib/docker 指向的是数据盘而不是根分区。
  4. 起一个真实的 Compose 服务,重启虚拟机(PVE 里 Shutdown 再 Start),确认容器随 docker 服务自动拉起、数据卷内容还在。
  5. PVE 的 虚拟机 → Summary 能看到 IP,说明 guest agent 正常。

备份与维护 ​

把这台虚拟机纳入常规的 vzdump 备份任务,方法见配置备份任务与保留策略。由于数据盘和系统盘是分开的虚拟磁盘,vzdump 默认会把两块都备份进去——检查一下虚拟机的备份任务没有把数据盘排除在外。

大容量数据卷会拖慢整机备份

如果某个容器的数据卷体积很大(比如媒体库、数据库文件),每次全量备份这块数据盘会很慢、很占空间。可以考虑:数据库类应用用它自己的导出/物理备份工具做增量备份,vzdump 只负责保底的整机快照式备份。具体策略取舍见家庭实验室的最小可用备份方案。

升级 ​

Docker Engine 和宿主发行版的升级按各自的常规流程(apt full-upgrade、Docker 官方的升级说明)进行。升级前,尤其是发行版大版本升级前,在 PVE 里打一个快照,出问题可以回滚,做法见快照、克隆与模板。

常见问题 ​

容器能起,但拿不到网络。 先排查客户机自身的网络(网关、DNS)是否正常,再检查 Docker 的网桥(docker network ls)和宿主机防火墙规则;和 PVE 层面的网络配置通常无关。

磁盘满了,但 /var/lib/docker 明明挂在单独的盘上。 检查是不是 Docker 的日志驱动没有限制大小(docker logs 默认可能无限增长),或者镜像/悬空容器层没有清理,用 docker system df 看占用分布,docker system prune 清理前先确认不会删掉还需要的数据。

想在 LXC 里跑 Docker,而不是虚拟机。 需要给容器开 nesting: 1(部分场景还要 keyctl: 1),并接受非特权容器可能遇到的 UID 映射和存储驱动兼容性问题。PVE 9 配合较新的 ZFS 版本时 overlay2 在 LXC 里能正常工作,但整体排查成本比虚拟机高,本站不展开具体配置步骤。

参考资料 ​

Proxmox VE 非官方中文使用指南,与 Proxmox Server Solutions GmbH 无隶属关系。