在docker容器中使用systemctl启动服务

Start service using systemctl inside docker container

在我的Dockerfile中,我试图安装多个服务,并希望在启动容器时使它们全部自动启动。
服务之一是mysql,当我启动容器时,我看不到mysql服务正在启动。 当我尝试手动启动时,出现错误:
Failed to get D-Bus connection: Operation not permitted

Dockerfile:

1
2
3
4
5
6
7
FROM centos:7

RUN yum -y install mariadb mariadb-server

COPY start.sh start.sh

CMD ["/bin/bash","start.sh"]

我的start.sh文件:

1
service mariadb start

Docker构建:

1
docker build --tag="pbellamk/mariadb" .

Docker运行:

1
docker run -it -d --privileged=true pbellamk/mariadb bash

我检查了centos:systemd图像,这也无济于事。 如何使用使用systemctl / service命令启动的服务启动容器。


当您使用bash作为命令执行docker run时,初始化系统(例如SystemD)不会启动(启动脚本也不会启动,因为您传递的命令会覆盖Dockerfile中的CMD)。尝试将您使用的命令更改为/sbin/init,使用-d在守护程序模式下启动容器,然后使用docker exec -it sh在shell中环顾四周。


Docker围绕每个容器一个服务/进程的想法进行设计。尽管它绝对支持在容器中运行多个进程,并且绝不会阻止您这样做,但是您最终会遇到容器中的多个服务与Docker或外部工具期望不完全对应的区域。转向服务扩展或跨主机使用Docker群之类的事情仅支持每个容器提供一项服务的概念。

Docker Compose允许您将多个容器组合成一个定义,这意味着您可以使用更多标准的预构建容器(httpdmariadb),而不是构建自己的容器。组合定义相当容易地映射到Docker Swarm服务。另请参阅Kubernetes和Marathon / Mesos,以管理一组容器即服务。

Docker中的流程管理

可以在容器中运行systemd,但是它需要--privileged对主机的访问和/sys/fs/cgroup卷的安装,因此对于大多数用例而言可能不是最合适的。

s6-overlay项目使用s6提供了对docker更加友好的流程管理系统。

您实际上确实需要对容器进行ssh访问,这种情况很少见,但是如果这是一项艰巨的要求,那么您将不得不建立自己的容器并使用流程管理器。


您可以避免完全在docker容器中运行systemd守护程序。您甚至可以避免编写特殊的start.sh脚本-这是使用docker-systemctl-replacement脚本时的另一个好处。

docker systemctl.py可以解析普通的* .service文件,以了解如何启动和停止服务。您可以将其注册为映像的CMD,在这种情况下,它将查找所有启用了systemctl的服务-这些服务将以正确的顺序启动和停止。

当前的测试套件包括包含centos的LAMP堆栈的测试用例,因此它应该在您的设置中运行良好。


我找到了这个项目:

https://github.com/defn/docker-systemd

可以用于基于股票ubuntu映像创建映像,但具有systemd和多用户模式。

我的用例是其自述文件中提到的第一个用例。我用它来测试作为systemd服务安装的应用程序的安装脚本。安装程序将创建systemd服务,然后启用并启动它。我需要安装程序的CI测试。测试应该创建安装程序,在ubuntu上安装应用程序,然后从外部连接到服务。

没有systemd,安装程序将失败,并且要用流浪汉编写测试要困难得多。因此,docker中有systemd的有效用例。