在Docker容器中运行systemd的解决方案

99次阅读
没有评论

问题描述

有用户提出了一个问题,他想在Docker容器内运行systemd,并希望找到一个确切且可接受的解决方案。他注意到有很多绕过方法可以在Docker容器内运行systemd,但大多数方法似乎会损害容器和主机的安全性。他想知道大多数人是如何处理在容器内运行systemd特定任务的问题的。

解决方案

请注意以下操作可能涉及特权和安全问题,请根据具体情况谨慎操作。
在Docker容器内运行systemd是一个有争议的话题,因为这涉及到容器的隔离性和安全性。但如果确实有这个需求,以下是一些解决方案,供用户参考。

方案1

准备工作

确保你已经安装了Docker并具备基本的Docker使用经验。

步骤

  1. 在容器中运行systemd,可以使用以下命令:
    bash
    docker run -it --rm \
    -e container=docker \
    --tmpfs /run \
    --tmpfs /tmp \
    -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
    --cap-add SYS_ADMIN \
    centos /sbin/init

    这个命令将以交互式方式启动一个CentOS容器,并运行systemd。在某些较旧的Docker版本中,可能需要添加其他标志。
  2. 验证容器内systemd的运行状态:
    bash
    systemctl status

    如果一切正常,你应该能够看到systemd的状态。

注意事项

  • 上述命令使用--privileged特权来启动容器,这可能会引起一些安全问题。特别是,-v /sys/fs/cgroup:/sys/fs/cgroup:ro将主机的cgroup文件系统挂载到容器中,这可能会导致一些安全风险。
  • 容器内的systemd需要一些特权来运行,这可能与容器的本来目的相悖,因为Docker容器通常是以轻量级、隔离的方式运行的。
  • 尽量避免在生产环境中使用这种方法,除非你对安全性和特权问题有充分的了解。

方案2

步骤

  1. 以Arch Linux为例,使用以下命令在容器内运行systemd:
    bash
    docker run -it --privileged -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
    --name=ArchLinux archlinux /bin/sh -c "if [ -x /etc/docker-start ]; then exec /etc/docker-start; else exec /bin/sh; fi"
  2. 在容器内执行以下命令,以配置systemd运行环境:
    bash
    echo 'Server = https://THE_FASTEST_MIRROR_FOR_YOU/archlinux/$repo/os/$arch' >/etc/pacman.d/mirrorlist
    pacman -Sy --noconfirm systemd systemd-sysvcompat
    passwd -d root
    echo -en '#!/bin/sh\numount /etc/hostname; umount /etc/hosts; umount /etc/resolv.conf; exec /usr/lib/systemd/systemd' >/etc/docker-start
    chmod 700 /etc/docker-start
    echo -e 'nameserver 8.8.8.8' >/etc/resolv.conf
    exit
  3. 启动容器并连接到容器:
    bash
    docker start -ia ArchLinux

注意事项

  • 使用--privileged特权来运行容器可能会引起安全问题,因此尽量避免在生产环境中使用。
  • 这种方法可能不够稳定,并且可能与Docker的设计初衷不符。如果可能的话,建议重新审视需求,考虑其他方式来达到目标。

方案3

步骤

  1. 创建一个Dockerfile,以Fedora为基础镜像,并按照以下内容构建镜像:
    “`Dockerfile
    FROM fedora:rawhide
    MAINTAINER “Dan Walsh” dwalsh@redhat.com

ENV container docker

RUN yum -y update; yum clean all
RUN yum -y install systemd; yum clean all
RUN (cd /lib/systemd/system/sysinit.target.wants/; \
for i in ; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/
; \
rm -f /etc/systemd/system/.wants/; \
rm -f /lib/systemd/system/local-fs.target.wants/; \
rm -f /lib/systemd/system/sockets.target.wants/
udev; \
rm -f /lib/systemd/system/sockets.target.wants/
initctl; \
rm -f /lib/systemd/system/basic.target.wants/
; \
rm -f /lib/systemd/system/anaconda.target.wants/*

VOLUME [ “/sys/fs/cgroup” ]

CMD [“/usr/sbin/init”]
2. 使用Docker构建镜像:bash
docker build -t systemd_image .
3. 基于该镜像创建一个容器,并运行systemd:bash
docker run –privileged -ti -v /sys/fs/cgroup:/sys/fs/cgroup:ro systemd_image
“`

注意事项

  • 这个方案参考了一个2014年的博客,由于Docker和systemd的发展速度,这个博客可能已经过时。
  • 尽管理论上可以在容器中运行systemd,但建议尽量避免,因为它可能与Docker的设计初衷和容器的隔离性相冲突。
  • 将多个服务运行在一个容器内可能导致可扩展性和管理问题,因为Docker更倾向于水平
正文完