Skip to content

懒猫微服进阶心得(三):一台机器跑三套 Docker?深入解析懒猫容器的共存机制(下)

在上一期里,我们剖析了懒猫微服原生的三套 Docker 共存方案,这次我们来看看怎么在懒猫微服上启动新的 dev-docker 引擎,既能拓展使用,但又不与现有环境相互污染。

核心思路

  1. 独立 daemon.json 指定专属数据目录 / Socket
  2. 一个包装脚本 dev-docker 让你照常敲 docker 命令
  3. 需要时随时启用,不用时一条命令即卸载

目录规划

我目前是在 root 目录下新建了一个 dev 目录,新的容器所有数据都在这个目录下。

.
├── dev/
│   ├── data/      # 镜像层、容器元数据
│   ├── exec/      # 运行时文件
│   └── daemon.json
└── dev-docker      # 包装脚本,照样敲 `docker`

提示docker.sockdocker.pid 会在启动时自动生成到 dev/ 里。


生成 daemon.json

这个是主要的文件,定义了 dev-docker 的数据目录,以及命名空间的隔离。

bash
# 先拿到绝对路径,避免 dockerd 报相对路径错误
DDIR=$(realpath ./dev)

cat > $DDIR/daemon.json <<EOF
{
  "data-root": "$DDIR/data",
  "exec-root": "$DDIR/exec",
  "pidfile": "$DDIR/docker.pid",
  "hosts": ["unix://$DDIR/docker.sock"],
  "containerd-namespace": "dev-docker",
  "containerd-plugins-namespace": "dev-docker"
}
EOF

启动 dev-docker 引擎

使用 dockerd 指定配置文件启动 dev-docker,然后放在后台进行。

bash
sudo dockerd --config-file=$DDIR/daemon.json --log-level=info &

执行之后得到如下的结果:

INFO[2025-05-20T12:55:02.072949048Z] detected 127.0.0.53 nameserver, assuming systemd-resolved, so using resolv.conf: /run/systemd/resolve/resolv.conf
INFO[2025-05-20T12:55:02.157745008Z] Loading containers: start.
INFO[2025-05-20T12:55:02.331021502Z] Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred IP address
INFO[2025-05-20T12:55:02.394567874Z] Loading containers: done.
INFO[2025-05-20T12:55:02.413944743Z] Docker daemon                                 commit="26.1.3-0ubuntu1~24.04.1" containerd-snapshotter=false storage-driver=overlay2 version=26.1.3
INFO[2025-05-20T12:55:02.414179613Z] Daemon has completed initialization
INFO[2025-05-20T12:55:02.471933824Z] API listen on /home/ubuntu/ddd/dev/docker.sock

一个 dev-docker 包装脚本

这个脚本就是仿照懒猫微幅其他的 docker 实现:

bash
cat > ./dev-docker <<'EOF'
#!/usr/bin/env bash
export DOCKER_HOST=unix://$(realpath ./dev/docker.sock)
exec docker "$@"
EOF

chmod +x ./dev-docker

设定DOCKER_HOST=unix://$(realpath ./dev/docker.sock),然后用 exec docker "$@" 把收到的全部参数原封不动交给真实的 docker 命令执行。

然后就可以正常使用了:

bash
./dev-docker ps
./dev-docker run -d -p 8080:80 nginx

系统自带的 docker 仍在 /var/run/docker.sock 上工作,互不打扰。


dev-docker 放入全局 PATH

如果想全局生效,运行下方命令。但注意:懒猫微服重启后 /usr/local/bin 会被还原。”

bash
sudo install -m 755 ./dev-docker /usr/local/bin/

一键化脚本

bash
#!/usr/bin/env bash
# init-docker-dev.sh
set -e
mkdir dev
BASE=$(realpath "./dev")
mkdir -p "$BASE"/{data,exec}

cat > "$BASE/daemon.json" <<EOF
{
  "data-root": "$BASE/data",
  "exec-root": "$BASE/exec",
  "pidfile": "$BASE/docker.pid",
  "hosts": ["unix://$BASE/docker.sock"],
  "containerd-namespace": "dev-docker",
  "containerd-plugins-namespace": "dev-docker"
}
EOF

dockerd --config-file="$BASE/daemon.json" --log-level=info &

cat > "./dev-docker" <<EOF
#!/usr/bin/env bash
export DOCKER_HOST=unix://$BASE/docker.sock
exec docker "\$@"
EOF
chmod +x ./dev-docker

echo "🎉 Dev Docker 已就绪,使用 ./dev-docker 访问!"

启动脚本:

bash
chmod +x init-docker-dev.sh   # 赋可执行权限(若脚本是下载的)
./init-docker-dev.sh

运行完脚本后,后续就在当前目录直接敲 ./dev-docker <command> 即可; 如果之前已将 dev-docker 安装到 PATH,全局也可以直接 dev-docker ps

脚本执行记录如下:

🎉 Dev Docker 已就绪,使用 ./dev-docker 访问!
ubuntu@ip-172-31-29-78:~$ INFO[2025-05-20T12:55:02.071795870Z] Starting up
INFO[2025-05-20T12:55:02.072949048Z] detected 127.0.0.53 nameserver, assuming systemd-resolved, so using resolv.conf: /run/systemd/resolve/resolv.conf
INFO[2025-05-20T12:55:02.157745008Z] Loading containers: start.
INFO[2025-05-20T12:55:02.331021502Z] Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred IP address
INFO[2025-05-20T12:55:02.394567874Z] Loading containers: done.
INFO[2025-05-20T12:55:02.413944743Z] Docker daemon                                 commit="26.1.3-0ubuntu1~24.04.1" containerd-snapshotter=false storage-driver=overlay2 version=26.1.3
INFO[2025-05-20T12:55:02.414179613Z] Daemon has completed initialization
INFO[2025-05-20T12:55:02.471933824Z] API listen on /home/ubuntu/ddd/dev/docker.sock

sudo ./dev-docker info查看信息:

sudo ./dev-docker info

Client:
 Version:    26.1.3
 Context:    default
 Debug Mode: false

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 0
 Server Version: 26.1.3
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Using metacopy: false
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version:
 runc version:
 init version:
 Security Options:
  apparmor
  seccomp
   Profile: builtin
  cgroupns
 Kernel Version: 6.8.0-1024-aws
 Operating System: Ubuntu 24.04.2 LTS
 OSType: linux
 Architecture: aarch64
 CPUs: 2
 Total Memory: 1.8GiB
 Name: ip-172-31-29-78
 ID: b6f661de-2099-4b23-aff8-1a55e35833d9
 Docker Root Dir: /home/ubuntu/ddd/dev/data
 Debug Mode: false
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false

./dev-docker pull ubuntu 下载 images:

ubuntu@ip-172-31-29-78:~$ sudo ./dev-docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
2f074dc76c5d: Pull complete
Digest: sha256:6015f66923d7afbc53558d7ccffd325d43b4e249f41a6e93eef074c9505d2233
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest

检查 docker 版本:

bash
ubuntu@ip-172-31-29-78:~$ dev-docker  --version
Docker version 26.1.3, build 26.1.3-0ubuntu1~24.04.1
ubuntu@ip-172-31-29-78:~$ docker --version
Docker version 26.1.3, build 26.1.3-0ubuntu1~24.04.1

不使用的时候如何卸载?

办法 1: ps aux | grep dockerd 查看 docker 进程的 PID 号,然后删除
bash
ps aux | grep dockerd
root         470  0.8  0.3 2653088 100248 ?      Ssl  07:42   0:11 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
root        2226  6.6  0.6 7246472 227108 ?      Ssl  07:42   1:37 /usr/bin/dockerd --config-file /lzcsys/etc/docker/daemon.json
root       27520  0.0  0.2 2874220 90788 ?       Ssl  07:46   0:00 /usr/bin/dockerd --config-file /lzcsys/var/playground/daemon.json
root      127241  0.5  0.2 2636632 92720 pts/1   Sl   07:52   0:04 dockerd --config-file=/root/dev/daemon.json --log-level=info
root      405552  0.0  0.0   3748  2048 pts/1    S+   08:06   0:00 grep --colour=auto dockerd
---
lzcbox-029c588e ~ # kill -15 127241
lzcbox-029c588e ~ # INFO[2025-05-21T08:10:58.184799932+08:00] Processing signal 'terminated'
INFO[2025-05-21T08:10:58.198235413+08:00] stopping event stream following graceful shutdown  error="<nil>" module=libcontainerd namespace=dev-docker
INFO[2025-05-21T08:10:58.203590577+08:00] Daemon shutdown complete
---
lzcbox-029c588e ~ # ps aux | grep dockerd
root         470  0.7  0.3 2653088 100212 ?      Ssl  07:42   0:13 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
root        2226  7.8  0.7 7246472 233080 ?      Ssl  07:42   2:18 /usr/bin/dockerd --config-file /lzcsys/etc/docker/daemon.json
root       27520  0.0  0.2 2874220 92644 ?       Ssl  07:46   0:00 /usr/bin/dockerd --config-file /lzcsys/var/playground/daemon.json
root      568622  0.0  0.0   3748  2048 pts/1    S+   08:11   0:00 grep --colour=auto dockerd
办法 2: pkill -f './dev/daemon.json' 指定文件删除:
bash
pkill -f './dev/daemon.json'
INFO[2025-05-21T08:14:06.721816466+08:00] Processing signal 'terminated'
lzcbox-029c588e ~ # INFO[2025-05-21T08:14:06.728822927+08:00] stopping event stream following graceful shutdown  error="<nil>" module=libcontainerd namespace=dev-docker
INFO[2025-05-21T08:14:06.734923834+08:00] Daemon shutdown complete

[1]+  Done                    dockerd --config-file="./dev/daemon.json" --log-level=info
lzcbox-029c588e ~ # ps aux | grep dockerd
root         470  0.7  0.3 2653088 100340 ?      Ssl  07:42   0:14 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
root        2226  8.3  0.7 7246472 234356 ?      Ssl  07:42   2:41 /usr/bin/dockerd --config-file /lzcsys/etc/docker/daemon.json
root       27520  0.0  0.2 2874220 92500 ?       Ssl  07:46   0:01 /usr/bin/dockerd --config-file /lzcsys/var/playground/daemon.json
root      663902  0.0  0.0   3748  1792 pts/1    S+   08:14   0:00 grep --colour=auto dockerd

清除数据

rm -rf ./dev                   # 删数据目录
sudo rm -f /usr/local/bin/dev-docker   # 若装过 PATH

最后

再多一套 Docker,不是为了炫技,而是给开发或者测试环境一个“随时可重置、天然隔离、低成本回收”的保险箱。学会这一招,你就能在懒猫微服乃至任何 Linux 服务器上,放心大胆地尝鲜新内核、新 runtime,甚至复刻生产 bug —— 然后一句 pkill + rm -rf dev/,世界瞬间清爽如初。祝玩得尽兴!

❤️喜欢