Docker (CentOS 7 with SYSTEMCTL): 无法挂载tmpfs和cgroup

22

(我是一个Docker初学者,然后我按照一些CentOS-7的教程进行了学习)

在我的CentOS 7.2系统中,我尝试通过以下步骤来学习Docker。

# docker version

Client:
 Version:      1.10.3
 API version:  1.22
 Go version:   go1.5.3
 Git commit:   20f81dd
 Built:        Thu Mar 10 15:39:25 2016
 OS/Arch:      linux/amd64

Server:
 Version:      1.10.3
 API version:  1.22
 Go version:   go1.5.3
 Git commit:   20f81dd
 Built:        Thu Mar 10 15:39:25 2016
 OS/Arch:      linux/amd64

# docker pull centos:latest
# docker images
centos     latest    778a53015523    12 days ago    196.7 MB

# mkdir ~/docker/centos7-systemd
# cd ~/docker/centos7-systemd
# vi Dockerfile
FROM centos
MAINTAINER "XXXX XXXX" <xxxx@xxxx.com>
ENV container docker
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"]

# docker build --rm -t local/centos7-systemd .
..
Successfully built 1a9f1c4938b3

# docker images
centos                  latest    778a53015523    12 days ago    196.7 MB
local/centos7-systemd   latest    1a9f1c4938b3    8 seconds ago  196.7 MB

到目前为止,一切(似乎)都还好。
现在的问题是当我运行以下命令时:

# docker run -ti -v /sys/fs/cgroup:/sys/fs/cgroup:ro -p 80:80 local/centos7-systemd
Failed to mount tmpfs at /run: Operation not permitted
Failed to mount cgroup at /sys/fs/cgroup/systemd: Operation not permitted
[!!!!!!] Failed to mount API filesystems, freezing.

这到底是什么意思,更重要的是,正在发生什么以及我该如何解决,请?谢谢大家 :)
6个回答

38
更现代的方法是在Daniel Walsh提交了一系列补丁后,如下所示...
docker run -ti --tmpfs /tmp --tmpfs /run -v /sys/fs/cgroup:/sys/fs/cgroup:ro -p 80:80 local/centos7-systemd

基本上在特权容器中启动是出于安全原因不好的想法。由于Daniel贡献了补丁使其变得不必要,我们能够在不提升权限的情况下启动。
虽然通常情况下我们应该遵循“每个容器只运行一个服务/进程”的原则,但有些人想要运行受RedHat支持的容器,这意味着使用systemd。
请参见https://developers.redhat.com/blog/2016/09/13/running-systemd-in-a-non-privileged-container/获取更多信息。
为了演示一个精简的systemd容器,像这样的容器将运行apache和tomcat;虽然不符合单一服务/进程原则,但只是一个例子。你显然需要对这个镜像做更多的工作,但这是基本思路。我想我从Daniel的某篇文章中看到过这个内容,但现在我记不清了。
FROM centos:7
ENV container docker
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/*;
RUN yum -y install httpd tomcat tomcat-javadoc.noarch \
    tomcat-docs-webapp.noarch tomcat-admin-webapps.noarch ; \
    yum clean all
RUN systemctl enable tomcat.service
RUN systemctl enable httpd.service

VOLUME [ "/sys/fs/cgroup" ]
EXPOSE 80 8080
CMD ["/usr/sbin/init"]

docker build -t apache ./
docker run --tmpfs /tmp --tmpfs /run -it -v /sys/fs/cgroup:/sys/fs/cgroup:ro -p 8081:80 -p 8080:8080 --name apache apache

5
需要大量点赞。如果可能的话,您应该避免在特权模式下运行。 - udondan
如果您的主机系统不是BSD(即没有systemd cgroup basedir),则应该从任何类似于BSD的系统中将其复制到本地目录并替换它!例如,在Mac上可以使用它。 - Mário de Sá Vera

29

尝试以特权模式运行您的容器:

docker run -ti --privileged=true -v /sys/fs/cgroup:/sys/fs/cgroup:ro -p 80:80 local/centos7-systemd

这应该可以解决你的问题。


这真的有效!非常感谢!!(还有,你知道为什么当我运行时它不在后台运行吗?相反,它一直占用我的终端。)抱歉我不知道如何解释这个问题。再次感谢:D - 夏期劇場
1
如果你想使用后台模式,可以尝试使用“-d”选项。 - hiproz
你可以给一个理由吗? - Tengerye
在高层次上,出现问题的原因是命令行参数“-v /sys/fs/cgroup:/sys/fs/cgroup:ro”指示Docker将主机机器上的/sys/fs/cgroup挂载到Docker容器中的同一目录。/sys/fs/cgroup是由root拥有的内核控制的目录结构。那么,/sys/fs/cgroup是什么?请参阅https://man7.org/linux/man-pages/man7/cgroups.7.html中的Linux内核资源控制。为什么要将其从主机挂载到Docker容器中呢?请参阅https://hub.docker.com/_/centos中描述了这个问题的相同步骤,创建一个启用systemd的容器。 - gaoithe

2

如我在这里所说,你并不需要强制使用--privileged=true参数(在我看来有些危险),你只是忘记在docker run命令中添加-v /run

因此,你最终应该使用以下运行命令:

docker run -ti -v /sys/fs/cgroup:/sys/fs/cgroup:ro -v /run -p 80:80 local/centos7-systemd

2

我遇到了与Docker for Windows (1.12.3)相同的问题...

$ docker logs bareos
systemd 219 running in system mode. (+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ -LZ4 -SECCOMP +BLKID +ELFUTILS +KMOD +IDN)
Detected virtualization docker.
Detected architecture x86-64.

Welcome to CentOS Linux 7 (Core)!

Set hostname to <bareos>.
Failed to install release agent, ignoring: No such file or directory
Failed to create root cgroup hierarchy: No such file or directory
Failed to allocate manager object: No such file or directory
[!!!!!!] Failed to allocate manager object, freezing.

最新的boot2docker没有systemd。如果主机没有systemd,则Docker容器中无法使用它。因为此文件夹的重要性在于/sys/fs/cgroup/systemd
因此,最终我在Alpine Linux上创建了一个基于VirtualBox的default虚拟机和一个generic驱动的defaultdocker-machine

2

MacOS X不需要在容器中挂载cgroups卷。

$docker run -it -p 80:80 ${ImageID}

运行了许多容器实例后,我的Mac卡住了。

[!!!!!!] 挂载API文件系统失败,冻结。

参考文献目前bash模式对我来说工作正常。

$docker run -it -p 80:80 ${ImageID} /bin/bash


2
如果您不需要在前台运行容器,可以以分离模式启动它以避免此错误。例如:
docker run -d --name=my_container_name image_id

然后您可以使用类似以下的命令进入容器的 shell:
docker exec -ti my_container_name /bin/bash

如果您在Dockerfile CMD中没有前台命令,导致容器立即退出,您可以添加一个保持其运行的命令,例如:
docker run -d --name=my_container_name image_id tail -f /dev/null

查看SO答案以获取有关最后一个示例的更多详细信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接