如何在Docker里面使用systemctl
我们有时在使用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只是提供了进程隔离,不是操作系统的虚拟。
解决方案
我们可以在启动容器的时候将在启动参数加上 /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了
但是如果容器重启,那么就可能导致失效。替换systemctl
使用 docker-systemctl-replacement替换容器中的systemctl。
以ubuntu镜像为例:
1). 安装python2sudo 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
, 但是遇到非常特殊的情况下,可以上述两个解决方案,如果有更好的方案,欢迎提出。
参考
Author: DongSheng
Link: http://ehds.github.io/2021/01/21/docker_systemctl/
License: 知识共享署名-非商业性使用 4.0 国际许可协议