Docker系统未使用systemd作为初始化系统启动

79

我在Docker容器中运行了一个Ubuntu 18.04的镜像。我登录进去并安装了Openrestysystemd。当我使用命令systemctl时,出现了以下错误:

System has not been booted with systemd as init system (PID 1). Can't operate.

我该如何解决这个问题?

https://dev59.com/T1QK5IYBdhLWcg3wPNlG - Srini M
3
作为两个通用规则,您不应在正在运行的容器内安装软件(一旦容器退出,它将丢失),而像 systemctl 这样的命令在 Docker 内部根本无法工作。 您可以将 Docker 视为打包“应用程序”的方式,而不是具有 init 系统、用户和进程的完整 VM;Docker 的 Containerizing an application 教程介绍了一个基本的标准用例。 - David Maze
1
这个回答解决了你的问题吗?如何从最新版本的Ubuntu(18.10)运行使用SystemD的Docker容器? - Bruno Wego
9个回答

29
如果我理解正确,OP想要在容器内运行systemctl。这不起作用,因为systemd一开始就没有在容器中运行。这在非特权容器中是无法实现的。这里有另一个stackoverflow问题解释为什么他不应该在容器中运行systemd
我快速谷歌了一下,并找到了这个2014年的页面使用在docker容器中使用systemd, 其中有一个简短的解释。修复方法是使用一个特权容器(运行docker run --privileged ...),这可能是一个糟糕的主意,但可能适合OP。这是2019年最后一篇文章的更新, 结论是他们开发了自己的容器引擎(所以没有docker)。
显然的解决方案是只有一个服务,因此不需要systemd,尽管在OP的情况下可能不可能。
总之,可能的解决方案如下:
  • 不要使用systemd
  • 使用特权容器
  • 不要使用docker

10
docker run --privileged ... 没有帮助我 :( - tolache

20

在你的终端中,你可以键入:

$ sudo dockerd

奇迹就在此刻发生

因此,请打开另一个终端并尝试它

$ docker ps -a
如果仍然存在权限问题,请运行以下命令:
$ sudo usermod -aG docker your-user

1
+1 对于 dockerd。至少守护进程已经启动,我可以看到错误消息显示正在发生的事情!但仍然出现 docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: can't get final child's PID from pipe: EOF: unknown. 的问题。 - GlenPeterson
1
出现以下错误:grpc: addrConn.createTransport 连接失败 {unix:///var/run/docker/containerd/containerd.sock <nil> 0 <nil>}。错误信息:connection error: desc = "transport: Error while dialing dial unix:///var/run/docker/containerd/containerd.sock: timeout"。正在重新连接... module=grpc 无法启动守护程序:未挂载设备 cgroup。 - smartmouse

16

你尝试使用:sudo /etc/init.d/docker start,而不是 systemd 吗?

我有一个类似的问题,这解决了它。


16

您需要使用此命令启动容器以启用systemd。

docker run -itd --privileged docker pull ubuntu:18.04 /usr/sbin/init

你正在复制Javier Gonzalez在2020年6月已经说过的内容... ;-( - Martin Mächler
1
不,他没有提到 /usr/sbin/init,他的回答不够。这个答案可以解决问题。 - jan

0
为了补充@javier-gonzalez的答案,如果您正在遵循在容器中运行systemd并且在尝试运行容器时出现错误bash:/usr/sbin/init:没有那个文件或目录,则可以在Dockerfile中使用/lib/systemd/systemd作为ENTRYPOINT,而不是/usr/sbin/init,因为它只是指向相同内容的符号链接。
FROM ubuntu:<anyversion>

ENTRYPOINT ["/lib/systemd/systemd"]

0

在我自己玩弄Systemd并遇到这个问题后,我发现在Docker中有一个好的解决方法来解决这个问题。

您可以设置一个定时任务,在容器重新启动时运行。

Dockerfile.yml:

COPY startup.sh /home/$USERNAME
WORKDIR /home/$USERNAME
RUN chmod +x startup.sh
RUN runuser -u $USERNAME -- echo "@reboot /home/$USERNAME/startup.sh" >> cronjobs
RUN runuser -u $USERNAME -- crontab cronjobs
RUN runuser -u $USERNAME -- rm cronjobs

https://askubuntu.com/questions/814/how-to-run-scripts-on-start-up#816


经过进一步测试,似乎这也不起作用。最好的方法是在主机上安排一个cron来运行此docker容器上的命令。在我的情况下,我只需要在第一次运行时这样做。 - Barco

0

如果以上方法都不能解决问题,那么可能是您在虚拟机上使用了wsl,那么您需要重新检查是否启用了 硬件虚拟化

  1. 使用客户端或Web客户端连接到VM管理主机。
  2. 关闭或关闭要启用虚拟化的虚拟机。
  3. 右键单击虚拟机,选择“编辑设置”或“虚拟机设置”。
  4. 在“虚拟机设置”窗口中,导航到“VM选项”或“CPU”部分。
  5. 查找与虚拟化相关的选项,例如“硬件虚拟化”或“向客户操作系统公开硬件支持的虚拟化”。
  6. 如果虚拟化选项尚未启用,请启用虚拟化选项。
  7. 保存虚拟机设置。
  8. 打开虚拟机电源。

-2
sudo apt-get update && sudo apt-get install -yqq daemonize dbus-user-session fontconfig

sudo daemonize /usr/bin/unshare --fork --pid --mount-proc /lib/systemd/systemd --system-unit=basic.target

exec sudo nsenter -t $(pidof systemd) -a su - $LOGNAME

-5

在使用 Docker 之前,您可能忘记启动它了。

 sudo service docker start

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