我已经看到了许多解决方法,可以在docker容器中运行systemd,但是似乎大多数解决方案都会损害容器和主机的安全性。大多数人在这里如何处理在容器内运行systemd特定的东西。

评论

您能解释一下为什么需要systemd吗?

我的应用程序是使用一些bash脚本在生产环境中设置的,这些脚本广泛使用了systemd。我无法更改它们,但我想对解决方案进行dockerize。

您能否添加找到的信息并为每种方法添加优缺点?

客户一次又一次地希望docker映像在其CI / CD管道中进行测试

由于技术上的限制,业务决策不会改变:)

#1 楼

您没有提到您在容器内使用的发行版(这将暗示您正在使用哪个版本的systemd),但是以下内容将成功启动运行systemd的CentOS容器:
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


这是与Docker 17.05.0-ce一起使用的;旧版本可能需要附加标志。使用一个库存的centos:7图像,您在容器内的初始环境如下所示:

/>请注意,我在这里使用--rm并不是因为有必要,而是因为在事后我很想清理东西。



但大多数容器似乎损害了容器和主机的安全性



,运行systemd确实需要特权,而不是授予典型Docker容器的特权(因此--cap-add)。这是否对您的环境有安全影响取决于您在做什么。

评论


安全漏洞实际上并不取决于您在做什么,而是在这里,更多是关于您承认并接受您所做的事情。 (对不起,但我要强调一点,安装/ sys /'anything'是一个很大的安全漏洞,因为它使容器可以访问容器已隔离的底层主机的很大一部分)

–滕西拜
18年1月3日在19:49

#2 楼

例如,如果要在Arch Linux容器中运行systemd,请运行以下命令: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"

,然后在容器中运行以下命令:

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


然后启动容器并连接到它:docker start -ia ArchLinux

您需要使用--privileged来运行,这可能会引起一些安全问题。如果可能,请尽量避免。

#3 楼

根据此博客的介绍,可以通过以下命令构建dockerfile在docker容器中运行systemd:


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;
(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"]



使用以下命令:


docker build -t httpd_rawhide .



作者指出,构建的docker映像可用作基础映像。 />
FROM systemd_rawhide
RUN yum -y install httpd; yum clean all; systemctl enable httpd.service
EXPOSE 80
CMD ["/usr/sbin/init"]



,如果容器正在运行


docker run –privileged -ti -v /sys/fs/cgroup:/sys/fs/cgroup:ro -p 80:80 httpd_rawhide



systemd将在内部运行docker容器。也可以使用systemd运行多个服务。根据该博客的创建者所说,可以在同一容器中同时运行mariadb和http。

基于此博客和其他文章,我读到我的结论是,从技术上讲,可以运行systemd在docker容器中,但是我建议避免在容器中运行systemd。

首先,如果systemd能够在容器内运行,那么这意味着可以像作者一样运行多个服务。从docker的角度来看,不建议这样做,因为docker旨在水平扩展,即如果http的负载增加,则应启动其他docker映像。

其次,如果将这样的系统化容器部署在docker swarm等编排平台上。那行得通吗?我怀疑这是否行得通。

第三,通过将cgroup安装在特权容器中来运行systemd看起来不是很安全。

总之,尽管您指出该脚本需要systemd,但还是重写代码或使用其他代码。我认为应避免在docker容器中运行systemd。

评论


请注意,此处引用的博客文章来自2014年,考虑到Docker(和系统化)开发的步伐相对较早,因此该博客文章较为古老。

–幼虫
17年4月4日在17:28