无法在Ubuntu Docker容器中使用systemd

93

问题

似乎在Ubuntu Docker容器中未激活或未安装systemd

设置

我正在使用ubuntu:16.04ubuntu:16.10镜像运行Docker容器。

测试

如果我在16.04容器中执行:

systemctl status ssh

结果是错误:Failed to connect to bus: No such file or directory

16.10容器中的错误是:bash: systemctl: command not found

如果我执行which systemctl,则在16.04容器中可以找到systemctl,但在16.10容器中找不到。

我发现/lib/systemd存在。

我尝试使用以下命令安装systemd:

apt-get install systemd libpam-systemd systemd-ui

然后which systemctl16.10中找到了systemctl

但是systemctl status ssh仍然出错,提示Failed to connect to bus: No such file or directory

问题

如何在Ubuntu Docker镜像中激活或安装systemd和systemctl?

为什么Ubuntu Docker容器中没有激活systemd?在实例化容器时是否未使用systemd?

我未能找到有关Ubuntu / Ubuntu Docker镜像的文档,只有有关Ubuntu从Upstart转换到systemd的信息。是否有任何给出完整解释的文档?


如果你想要一个完全运行的初始化系统,请使用虚拟机。 - user2105103
有几个提案来模拟容器内 PID-1 的 init 系统。基本上,它应该对由 "docker stop" 发送的 SIGTERM 做出反应,并将其分发到容器中的其他进程。它还应该能够清理已终止的后台进程的僵尸进程。现在只需要选择其中一个实现即可。有些只是将真正的 C/C++ "init" 移植过来,而其他一些则在高级语言中使用 signal(3) 和 waitpid(3) 进行脚本编写 - Python 的 "signal" 标准库也适用于此(如我的 docker-systemctl-replacement 脚本所示)。 - Guido U. Draheim
3
使用命令docker run --privileged -v /sys/fs/cgroup:/sys/fs/cgroup:ro <image>可以运行Docker镜像,同时命令systemctl也可以正常工作。 - bucky
为什么这个问题被关闭了? - gary69
1个回答

95
这是有意设计的。Docker应该在容器中运行前台进程,并作为容器PID命名空间中的PID 1生成。 Docker旨在进行进程隔离,而不是进行操作系统虚拟化,因此容器内没有其他操作系统进程和守护程序运行(如systemd、cron、syslog等),只有您运行的入口点或命令。
如果包含systemd命令,则会发现许多东西无法正常工作,因为入口点会替换init。Systemd还使用cgroups,而docker限制了容器内的cgroups,因为更改cgroups的能力可以允许进程逃脱容器的隔离。如果容器内没有systemd作为init运行,那么就没有守护程序来处理启动和停止命令。

7
在您所提供的教程中,并未讨论您提出的任何观点,因此我不明白您如何说它是“教程中的第一条注释”,仅链接到文档首页并无帮助。我从《自学Docker培训视频》中了解到容器的Entrypoint为PID 1,因此隐含地理解Entrypoint替换了systemd。然而,在阅读了Docker文档的多个章节后,我仍然感觉没有完整清晰的解释。 - Duncan Gravill
4
几乎所有有用的操作都需要一个基础镜像作为操作环境。我的理解是,与完整操作系统唯一的不同之处在于它没有内核,而是使用主机操作系统的内核。也许这需要有关操作系统的知识。我是 Linux 新手,需要详细解释常规 Ubuntu/Linux 发行版操作环境和 Docker 化的 Ubuntu/Linux 发行版操作环境之间的区别。 - Duncan Gravill
1
另一点是,第一个自学视频暗示容器内可以运行多个进程,因此我认为您关于容器内“没有其他进程”运行的说法至少部分不准确。无论如何,感谢您的回复。 - Duncan Gravill
1
与此相关的排名最高的问题是如何区分Docker和普通虚拟机?,您可能会发现它很有帮助。 - BMitch
4
顺便提一下,我有一些脚本可以发出“systemctl start”和“systemctl stop”的命令,因此我简单地创建了一个替代脚本来处理必要的步骤......它只是解释/etc/systemd/system/中的*.service文件。不需要SystemD守护程序。甚至可以执行在docker容器中PID-1进程所期望的操作。欢迎查看https://github.com/gdraheim/docker-systemctl-replacement。 - Guido U. Draheim
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接