我在 docker 中使用 traefik 时,在 /run/docker.sock 上遇到了 SELinux 安全问题。
docker ps
运行正常,只是 traefik 需要映射卷 /var/run/docker.sock 存在问题
以下是我尝试过的:
git clone https://github.com/jamct/traefik-example.git
cd traefik-example/04_config_files
sudo setenforce 0
docker-compose up
#it works
sudo setenforce 1
docker-compose up
# it fails
$ ls -lsZ /run/docker.sock
0 srw-rw-rw-. 1 root docker system_u:object_r:container_file_t:s0:c134,c237 0 4 mars 11:38 /run/docker.sock
我收到了这个错误日志
traefik_1 | time="2020-03-04T15:46:16Z" level=error msg="Provider connection error Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.24/version: dial unix /var/run/docker.sock: connect: permission denied, retrying in 4.506218855s" providerName=docker
并且 /var/log/audit/audit.log 中的日志是允许模式的:
type=AVC msg=audit(1583336776.607:1931): avc: denied { connectto } for pid=16969 comm="traefik" path="/run/docker.sock" scontext=system_u:system_r:container_t:s0:c134,c237 tcontext=system_u:system_r:container_runtime_t:s0 tclass=unix_stream_socket permissive=0
docker-compose.yml
version: "3.7"
services:
traefik:
image: traefik:v2.0
command: --providers.docker
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:rw
- ./traefik.yml:/etc/traefik/traefik.yml
- ./dynamic.yml:/etc/traefik/dynamic/traefik.yml
web1:
image: nginx:alpine
labels:
- traefik.http.routers.web1.rule=Host(`web1.localhost`)
web2:
image: containous/whoami
labels:
- traefik.http.routers.web2.rule=Host(`web2.localhost`) || ( Host(`localhost`) && PathPrefix(`/web2`) )
- traefik.http.routers.web2.middlewares=demo-whitelist@file
有没有一种干净的方法可以让 traefik 在启用 selinux 的情况下工作?是否有可以在 /run/docker.sock 文件上使用的“chcon”CLI?
答案1
编辑和免责声明:此解决方案不推荐,因为它破坏了docker的安全规则,解决方案如下: https://stackoverflow.com/questions/29089023/var-run-docker-sock-unaccessible-in-container-running-on-centos-7/30368817#30368817
感谢@Bert给出的redhat的bug报告让我得到了解决方案:
为什么 SELinux 阻止在 redhat 配置(fedora、centos)中访问 /run/docker.sock
Bug 1495053 - SELinux 阻止 traefik 进行“connectto” 由于以下原因,此错误报告被归类为“非错误”:
您正在尝试将受限域连接到 docker 套接字。这样做毫无意义,因为与 docker 套接字通信的能力允许您完全控制主机。这要么是您的容器的严重突破,要么您应该运行特权容器。SELinux 正在做它应该做的事情,即阻止对 docker 套接字的访问。
所以我不应该更改对 docker.sock 的访问权限,因为这与禁用 selinux 相同。相反,我可以在“特权”容器中运行。
解决方案
我只是将 docker-compose.yml 文件更改为以特权模式运行(可以在其他 docker 启动器中获得相同模式)。
这是有效的 docker-compose.yml 文件
version: "3.7"
services:
traefik:
image: traefik:v2.1.6
command: --providers.docker
ports:
- "80:80"
- "8080:8080"
privileged: true
volumes:
- /var/run/docker.sock:/var/run/docker.sock:rw
- ./traefik.yml:/etc/traefik/traefik.yml
- ./dynamic.yml:/etc/traefik/dynamic/traefik.yml
web1:
image: nginx:alpine
labels:
- traefik.http.routers.web1.rule=Host(`web1.localhost`) || PathPrefix(`/web1`)
web2:
image: containous/whoami
labels:
- traefik.http.routers.web2.rule=Host(`web2.localhost`) || ( Host(`localhost`) && PathPrefix(`/web2`) )
- traefik.http.routers.web2.middlewares=demo-whitelist@file
重要的一行是 特权:真实在 traefik 容器中。
和特权:真实并且启用了 selinux,它就可以工作了,如果我改回privileged: false
,我会得到错误日志,这是预期的。