在服务器上,我有一个具有不同网络命名空间的环境,这些命名空间是使用命令
sudo ip netns add ns_name
创建的。服务器的物理接口被分配到不同的命名空间,在“默认”网络命名空间中保留没有物理接口。
启动时,docker 守护进程会在“默认”网络命名空间中创建 docker0 网桥。如何告诉 docker 不在默认的桥接器中创建 docker0 桥接器,而是在我创建的桥接器之一中创建?
我的系统是 (2023) 最近安装的 Archlinux,但这些说明应该与您的发行版类似:
启动此命令时确保 docker 已停止:
systemctl stop docker.socket
systemctl stop docker.service
编辑你的docker systemd单元文件,你可以通过
systemctl status docker.service
找到它
● docker.service - Docker 应用程序容器引擎 已加载:已加载(/usr/lib/systemd/system/docker.service;禁用;预设:禁用)
修改单元文件
[Service]
部分/usr/lib/systemd/system/docker.service
:
[Service]
Type=notify
# This tells systemd to run dockerd in the network namespace
NetworkNamespacePath=/run/netns/ns_name
# This is the original docker command, it caused some issues for me
#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
# This is the replacement if the default exec doesn't work
ExecStart=/usr/bin/dockerd -H fd://
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutStartSec=0
RestartSec=2
Restart=always
现在刷新配置并启动 docker
systemctl daemon-reload
systemctl restart docker
如果幸运的话,您现在可以尝试运行 docker 容器,它就会正常工作。正在发生一些奇怪的恶作剧,因此每当您启动任何容器(如下所示)时,您都可能会收到错误消息:
来自守护进程的错误响应:无法为容器创建任务: 未能创建 shim 任务:OCI 运行时创建失败:runc create 失败:无法启动容器进程:exec:“/sbin/tini”:stat /sbin/tini:没有这样的文件或目录:未知
此错误似乎是由于 Containerd 和 docker 之间的配置错误造成的。 打开 containerd 单元文件并将其
ExecStart
替换为以下内容:
ExecStart=/usr/bin/containerd --config=/var/run/docker/containerd/containerd.toml
这将告诉containerd使用docker的配置,并且在重新加载配置并重新启动所有服务后,您的容器应该可以工作。 坦率地说,此时重新启动机器会更容易。
至于它的作用,我们得到了一系列有趣的效果。
docker
可执行文件通过unix套接字与dockerd
进行通信,因此只要套接字可访问,您运行哪个命名空间docker
或docker-compose
命令并不重要。containerd
在默认网络命名空间中运行,该命名空间具有用于创建容器的所有正确 cgroup。dockerd
在您的命名空间内运行,因此它将在该命名空间内创建所有网络接口,并且默认情况下将在该命名空间内生成所有容器网络。最后一点,除非您设置一个服务来在启动时创建网络命名空间,否则您可能希望禁用 docker,并让启动脚本创建命名空间,然后启动 docker。 此外,您可能需要在单元文件上运行
chattr +i
以防止更新覆盖您的配置更改。