2G 小机器上的 Docker Compose:我踩过的几个坑

2026-10-05

我在一台 2C2G 的国内 ECS(Ubuntu 24.04)上跑自己写的几个小服务,前面挂一层 nginx,同机还有别的自用服务;小机器上编排全用 Docker Compose。 这篇把实测踩过、并且写进配置注释里的东西整理一下。

一、compose 命令本身要先探测

if docker compose version >/dev/null 2>&1; then      DC="docker compose"
elif command -v docker-compose >/dev/null 2>&1; then DC="docker-compose"
fi

插件版和旧版 v1 写法不通用,脚本里别硬写;装 docker 我用官方那行 curl -fsSL https://get.docker.com | sh,装完 systemctl enable --now docker。

二、内存上限:不能没有,也不能太小气

mem_limit: 1024m
memswap_limit: 1536m

三、cpus 在这台机器上根本写不了

Error response from daemon: NanoCPUs can not be set, as your kernel
does not support CPU CFS scheduler or the cgroup is not mounted

原因是云盾(aegis)把 cgroup v1 的 cpu 控制器独占挂走了,cgroup v2 的控制器列表里就没有 cpu(一查便知:cat /sys/fs/cgroup/cgroup.controllers);内存控制器还在,所以 mem_limit 仍然有效。

四、restart: unless-stopped 的语义正好是我要的

开机自启、崩了自动拉起,但被我手动 stop 过的服务保持停止,重启服务器后"只有该回来的回来"。重启单个服务一定带 --no-deps:

docker compose up -d --no-deps --force-recreate <服务名>

不带的话 compose 会顺手把 depends_on 的依赖服务一起处理,那个服务被重建之后要重新初始化,我的服务就中断几分钟。这条是真踩过才记住的。

五、卷:具名卷和绑定挂载的属主不一样

六、镜像拉不下来就走本地自建 + 国内源

bash <构建目录>/fetch-artifacts.sh
docker build -t <镜像名>:latest <构建目录>/

国内服务器上 registry-1.docker.io 会被 DNS 污染,公共镜像站只能取 manifest、拉不到实际的层。所以我把上游 Dockerfile 等价复刻一份放本地,素材源全挑国内可达的,镜像里装系统包走 mirrors.aliyun.com;代码打进镜像又没有绑定挂载时,改完必须 build 再 up -d。

七、另外三处小配置

八、配套脚本要幂等,还有换行符那个坑

常用动作我封成几个脚本,反复跑结果一样:体检模式只查不动东西(bash deploy.sh --check 会看内存、swap、配置、容器状态); 同步类脚本发现"已经是目标状态"就直接退出,改配置前先备份、nginx -t 不过就自动回滚。

长驻的小助手做成 systemd 服务(Restart=always + RestartSec=5,依赖 docker 先起来),日志进 journal,出问题用 journalctl -u <单元名> -n 20 看。

换行符单独记一笔:从 Windows 提交脚本时 git 的 core.autocrlf 会把文本存成 CRLF,scp 到 Linux 上就报 bash: ./xxx.sh: /bin/bash^M: bad interpreter。治法是在 .gitattributes 里强制:

*.sh   text eol=lf
*.conf text eol=lf

返回首页