我们有时在使用docker的时候,会发现在容器中是用systemctl 或者 service的时候,会遇到下面的错误:
Failed to connect to bus: No such file or directory

原因

That’s because “systemctl” talks to the systemd daemon by using the d-bus. In a container there is no systemd-daemon. Asking for a start will probably not quite do what you expect - the dev-mapping need to be a bit longer.

容器里面是没有systemd进程的,所以不能正常开启systemctl。为什么docker会这样呢:

This is by design. Docker should be running a process in the foreground in your container and it will be spawned as PID 1 within the container’s pid namespace. Docker is designed for process isolation, not for OS virtualization, so there are no other OS processes and daemons running inside the container (like systemd, cron, syslog, etc), only your entrypoint or command you run.
If they included systemd commands, you’d find a lot of things not working since your entrypoint replaces init. Systemd also makes use to cgroups which docker restricts inside of containers since the ability to change cgroups could allow a process to escape the container’s isolation. Without systemd running as init inside your container, there’s no daemon to process your start and stop commands.

docker只是提供了进程隔离,不是操作系统的虚拟。

解决方案

  1. 我们可以在启动容器的时候将在启动参数加上 /sbin/init 来让其生效。
    以centos为例:
    docker run -d -v /sys/fs/cgroup/:/sys/fs/cgroup:ro --cap-add SYS_ADMIN --name systemd_websrv centos /sbin/init
    就可以正常使用systemd了
    但是如果容器重启,那么就可能导致失效。

  2. 替换systemctl
    使用 docker-systemctl-replacement替换容器中的systemctl。
    以ubuntu镜像为例:
    1). 安装python2
    sudo apt install python
    2). 替换systemcl (注意路径,可以使用whereis systemctl查看当前默认路径)
    wget https://raw.githubusercontent.com/gdraheim/docker-systemctl-replacement/master/files/docker/systemctl.py -O /bin/systemctl
    3). 给定权限
    sudo chmod a+x /bin/systemctl
    这样接可以使用非systemd的systemctl,但是因为是非官方的systemcl所以可能存在一些未知问题。

最好还是建议将docker作为进程隔离环境,single app single container, 但是遇到非常特殊的情况下,可以上述两个解决方案,如果有更好的方案,欢迎提出。

参考

  1. 关联问题:Docker里面如何启动Postgresql?
  2. https://stackoverflow.com/questions/49285658/how-to-solve-docker-issue-failed-to-connect-to-bus-no-such-file-or-directory
  3. https://stackoverflow.com/questions/39169403/systemd-and-systemctl-within-ubuntu-docker-images