Docker 内替换 systemctl

1. 问题背景

Docker 只是提供了进程隔离,而不是真正的虚拟机。Docker 容器的入口代替了 Linux 的 init 进程,所以也没有 systemd 等服务。Docker 应用一般都是单容器单应用,一般也不使用 systemctl 进行管理,如常见的 Nginx、MySQL 等在官方镜像中都是直接提供的,相互独立运行。

我们常常需要对一些历史应用进行容器化,但是有一些应用依赖于 systemctl 命令进行管理。由于在 Docker 容器内部一般是不提供 systemctl 命令的,这对应用的容器化造成阻碍。因此需要在容器内部模拟 systemctl 命令。

2. 解决方案

2.1 修改应用

最好的方法是找到应用依赖 systemctl 命令的原因,然后修改应用的启动代码,将其生命周期托管给 Docker 本身。但这种方式需要针对具体应用进行修改,需要较大的成本。

2.2 模拟 systemctl

如果应用难以修改,可以模拟 systemctl 命令本身。开源项目 gdraheim/docker-systemctl-replacement在新窗口打开 实现了 systemctl 命令的大部分功能,可以直接使用,一般也很少遇到问题。

在 Debian/Ubutnu 系统中,直接使用下面的命令来安装 docker-systemctl-replacement,安装后效果一致:

apt install -y systemctl

在编写 Dockerfile 时,通常需要将入口换为 systemctl 命令,例如:

CMD ["systemctl", "-1"]

作者也提供了一些示例,可以参考 gdraheim/docker-systemctl-images在新窗口打开

另外也可以通过 pip 安装使用:

pip install docker-systemctl-replacement

其他系统可以下载源码直接使用。前提是需要提供 Python(2.x 和 3.x 都可以),例如安装 Python 2 版本:

curl -o /bin/systemctl https://raw.githubusercontent.com/gdraheim/docker-systemctl-replacement/master/files/docker/systemctl.py
chmod +x /bin/systemctl

安装 Python 3 版本:

curl -o /bin/systemctl https://raw.githubusercontent.com/gdraheim/docker-systemctl-replacement/master/files/docker/systemctl3.py
chmod +x /bin/systemctl

注意,docker-systemctl-replacement 在行为上并不等同于 systemctl 命令,只是提供了相似的命令行接口,具体差异见 项目文档在新窗口打开