【问题标题】:Start service using systemctl inside docker container在 docker 容器中使用 systemctl 启动服务
【发布时间】:2018-03-29 18:17:17
【问题描述】:

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

Dockerfile:

FROM centos:7

RUN yum -y install mariadb mariadb-server

COPY start.sh start.sh

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

我的 start.sh 文件:

service mariadb start

Docker 构建:

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

Docker 运行:

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

我检查了centos:systemd 图像,但也没有帮助。如何使用 systemctl/service 命令启动服务的容器。

【问题讨论】:

  • 您需要使用 systemd 有什么特别的原因吗?使用较小的 docker init 系统之一或将每个容器分成一个服务可能会更容易。
  • 不使用systemd,如何启动我的服务?我的容器需要几乎 5-6 个需要启动的服务。其中之一是 mariadb。所以我不能为每个服务单独的容器。如何在上面的 Dockerfile 中创建一个较小的 docker init?您能否举例说明如何在启动时使用 3 个服务(mariadb、httpd、sshd)来启动容器
  • 你有在容器中运行 systemd 的运气吗?

标签: docker containers


【解决方案1】:

我找到了这个项目:

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

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

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

如果没有 systemd,安装程序会失败,并且使用 vagrant 编写测试会更加困难。因此,在 docker 中有 systemd 的有效用例。

【讨论】:

  • 不幸的是,以上导致404错误
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • :) 很高兴能帮上忙。如果您不介意,请点赞或标记为已回答,以便其他有相同问题的人在以后更轻松地找到解决方案。
    • 嗨 Dima,当您使用 /sbin/init 运行容器时,即 docker run -it -d --privileged=true pbellamk/mariadb /sbin/init,我可以运行一次 systemctl 命令我进入容器的外壳。但是,当容器启动时,我仍然无法自动启动 mariadb 服务。我必须登录到 shell 并手动启动。在我的运行命令中使用 /sbib/init 仍然会覆盖 Dockerfile 中的 CMD 对吗?那么我如何在 Dockefile 中运行 CMD 下的命令以在我启动容器时自动运行?
    • docker run -it -d --privileged=true image_id /sbin/init 让我在 centos 容器中使用 ansible 启动 nginx。我只是想在 docker 容器中本地测试 ansible playbook。由于该错误,ansible 无法启动 nginx。
    【解决方案4】:

    Docker 的设计理念是每个容器都有一个服务/进程。尽管它绝对支持在一个容器中运行多个进程并且绝不会阻止您这样做,但您最终会遇到容器中的多个服务无法完全映射到 Docker 或外部工具所期望的区域。诸如转向服务扩展或跨主机使用 Docker swarm 之类的事情仅支持每个容器一个服务的概念。

    Docker Compose 允许您将多个容器组合到一个定义中,这意味着您可以使用更多标准的预构建容器(httpdmariadb),而不是构建自己的容器。编写定义映射到Docker Swarm 服务相当容易。另请查看 KubernetesMarathon/Mesos 以将容器组作为服务进行管理。

    Docker 中的进程管理

    可以在容器中使用run systemd,但它需要--privileged 访问主机并安装/sys/fs/cgroup 卷,因此可能不是最适合大多数用例。

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

    您很少将actually need ssh access 放入容器中,但如果这是一个硬性要求,那么您将无法构建自己的容器并使用流程管理器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-05
      • 2017-11-29
      • 1970-01-01
      • 1970-01-01
      • 2023-01-28
      • 1970-01-01
      • 2016-12-16
      相关资源
      最近更新 更多