人们似乎可以通过多种不同的方式在 Docker 容器中运行 systemd 服务。最新的例子是直接建议我发现使用--volume=/sys/fs/cgroup:/sys/fs/cgroup:ro --cap-add=SYS_ADMIN --security-opt=seccomp:unconfined
.然而,它仍然只是失败:
错误:无法启动服务[ntpd]:执行“/usr/sbin/systemctl start ntpd”返回1:无法连接到总线:没有这样的文件或目录
要在具有最新 Arch Linux 发行版的 docker 1.12.1 容器上的 systemd 231 下运行简单服务,我至少需要做什么?
答案1
我在测试需要 systemd 的 Ansible playbook 时遇到了同样的问题。正如您所说,docker 似乎是最好的方法,因为启动和关闭容器比虚拟机要容易得多。
首先基础/archlinux图像已被弃用 - 你应该使用archlinux/基地反而。然后,要完全以非特权方式运行 systemd,需要完成以下几件事:
- 提供一个
container=
变量,这样 systemd 就不会尝试执行引导硬件机器时通常执行的许多操作 - systemd 主动使用 cgroup,因此
/sys/fs/cgroup
从主机绑定挂载文件系统 /sys/fs/fuse
不需要绑定安装,但有助于避免依赖熔丝的软件出现问题- systemd 认为
tmpfs
到处使用是一个很好的方法,但是以非特权方式运行使其无法安装到tmpfs
任何它想要的地方,因此预先安装tmpfs
到/tmp
,/run
和/run/lock
- 作为最后一位,您需要指定
sysinit.target
为默认启动单位,而不是multi-user.target
其他,因为您确实不想在容器内启动图形化的东西
结果命令行是
docker run \
--entrypoint=/usr/lib/systemd/systemd \
--env container=docker \
--mount type=bind,source=/sys/fs/cgroup,target=/sys/fs/cgroup \
--mount type=bind,source=/sys/fs/fuse,target=/sys/fs/fuse \
--mount type=tmpfs,destination=/tmp \
--mount type=tmpfs,destination=/run \
--mount type=tmpfs,destination=/run/lock \
archlinux/base --log-level=info --unit=sysinit.target
如果我们正在讨论在那里运行特定的服务,例如您示例中的 ntpd,您将需要添加
--cap-add=SYS_TIME
否则ntpd
会因权限拒绝而失败,因为没有人希望容器默认设置系统时间。
PS 我花了相当长的时间来学习 systemd 的行为方式并设法让它在许多操作系统映像上工作。我在一篇文章中描述了我的经历在 docker 容器中运行 systemd。它是俄语的,但我相信谷歌翻译应该可以在您的浏览器中使用。谢谢