尝试将无根 Podman + docker-compose + Traefik 与 podman.sock 一起使用时权限被拒绝

Jan*_*ila 5 docker-compose traefik podman rootless

TL:DR:尝试通过 podman 套接字将无根 Podman 与 docker-compose 结合使用,并使用 Traefik 容器(与 podman 套接字通信)将流量代理到其他容器,与/sf/answers/5164202921/相关

我收到权限被拒绝的错误,我可以使用我不想使用的特权容器来修复该错误。

设置

我在 RHEL 8 上运行

$ cat /etc/redhat-release 
Red Hat Enterprise Linux release 8.6 (Ootpa)
Run Code Online (Sandbox Code Playgroud)

Podman 是预安装的,我添加了 docker-compose(“独立”)和 podman-docker:

$ curl -SL https://github.com/docker/compose/releases/download/v2.10.2/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
$ chmod a+x /usr/local/bin/docker-compose
$ sudo yum install podman-docker
Run Code Online (Sandbox Code Playgroud)

并激活 rootless podman 套接字,以便 podman 和 docker-compose 可以相互通信:

$ systemctl --user enable podman.socket
$ systemctl --user start podman.socket
$ systemctl --user status podman.socket
$ export DOCKER_HOST=unix:///run/user/$UID/podman/podman.sock
$ echo $DOCKER_HOST
unix:///run/user/1001/podman/podman.sock
Run Code Online (Sandbox Code Playgroud)

我还将网络后端切换为 netavark,如果不进行更改,DNS 就无法工作

$ podman info |grep -i networkbackend
  networkBackend: netavark
Run Code Online (Sandbox Code Playgroud)

问题

首先,我尝试了/sf/answers/5164202921/中的 compose 堆栈,并进行了一些小修改:

version: "3"
services:
  frontend:
    image: "docker.io/traefik:v2.8"
    ports:
      - "3000:80"
      - "127.0.0.1:3080:8080"
    command:
      - --api.insecure=true
      - --providers.docker
    volumes:
      - /run/user/$UID/podman/podman.sock:/var/run/docker.sock

  backend:
    labels:
      traefik.http.routers.backend.rule: Host(`localhost`)
    image: "tomcat:latest"
    scale: 3
Run Code Online (Sandbox Code Playgroud)

我的设置不喜欢该$UID变量:

WARN[0000] The "UID" variable is not set. Defaulting to a blank string. 
...
Error response from daemon: make cli opts(): error making volume mountpoint for volume /run/user//podman/podman.sock: mkdir /run/user//podman: permission denied
Run Code Online (Sandbox Code Playgroud)

我用硬编码的 UID=1001 替换了卷映射(这是运行 rootless podman 的用户的 UID,我认为我应该使用那个?)。套接字看起来像这样:

ls -la /run/user/1001/podman/podman.sock 
srw-rw----. 1 myrootlessuser myrootlessuser 0 22. 9. 11:28 /run/user/1001/podman/podman.sock


volumes:
  - /run/user/1001/podman/podman.sock:/var/run/docker.sock
Run Code Online (Sandbox Code Playgroud)

但现在我从 Traefik 尝试连接到 /var/run/docker.sock 时收到权限被拒绝错误:

example-docker-compose-frontend-1  | time="2022-09-22T12:04:52Z" 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 5.656635591s" providerName=docker
Run Code Online (Sandbox Code Playgroud)

如果我将 Traefik-container 更改为privileged: true,就可以解决问题。我不再收到错误,代理也能正常工作。

但是,出于安全原因,我宁愿不使用特权容器,或者至少了解为什么会这样。

问题

  1. 如何在非特权 Traefik 容器中实现此功能?

  2. 如何验证无根 docker/podman 套接字是否正常工作?我见过这样的命令来测试 rootful podman 套接字,但在 rootless 上还没有成功

    $ sudo curl -H "Content-Type: application/json" --unix-socket /var/run/docker.sock http://localhost/_ping

    curl: (7) Couldn't connect to server

  3. 在哪里可以找到为 rootless Podman 设置 docker 套接字的文档?我的设置是否正确(systemctl --user enable podman.socket等等)?我只能找到一些与此相关的博客,并且建议各不相同,并且通常适用于较旧的 Podman 版本。例如:

Eri*_*und 13

问题1和2

\n

如果您正在使用

\n
export DOCKER_HOST=unix:///run/user/$UID/podman/podman.sock\n
Run Code Online (Sandbox Code Playgroud)\n

您正在使用无根(非特权)Podman(即使您privileged: true在 Compose 文件中指定)。

\n

要在容器中使用泄漏的套接字,需要podman run使用命令行选项运行--security-opt label=disable

\n

例子:

\n

启动并启用 podman 套接字

\n
$ systemctl --user enable --now podman.socket\nCreated symlink /home/testuser/.config/systemd/user/sockets.target.wants/podman.socket \xe2\x86\x92 /usr/lib/systemd/user/podman.socket.\n
Run Code Online (Sandbox Code Playgroud)\n

测试 Docker API 服务。\n结果:失败。卷曲印花Couldn't connect to server

\n
$ podman run --rm \\\n  -v $XDG_RUNTIME_DIR/podman/podman.sock:/var/run/docker.sock \\\n  docker.io/library/fedora \\\n    /usr/bin/curl \\\n      -H "Content-Type: application/json" \\\n      --unix-socket /var/run/docker.sock \\\n        http://localhost/_ping\ncurl: (7) Couldn't connect to server\n
Run Code Online (Sandbox Code Playgroud)\n

再次测试 Docker API 服务,但现在添加--security-opt label=disable。\n结果:成功

\n
$ podman run --rm \\\n  --security-opt label=disable \\\n  -v $XDG_RUNTIME_DIR/podman/podman.sock:/var/run/docker.sock \\\n  docker.io/library/fedora \\\n    /usr/bin/curl \\\n      -Hs "Content-Type: application/json" \\\n      --unix-socket /var/run/docker.sock \\\n        http://localhost/_ping\nOK$\n
Run Code Online (Sandbox Code Playgroud)\n

Docker API 服务以文本字符串 OK进行响应。

\n

(在上面的命令中我还添加了curl选项-s,以便curl打印更少的调试输出)

\n

我猜想添加到 Compose文件privileged: truepodman run.

\n

使用--privileged的​​效果之一 是它意味着--security-opt label=disable

\n

问题3

\n

概括:

\n

跑起来就够了

\n
$ systemctl --user start podman.socket\n
Run Code Online (Sandbox Code Playgroud)\n

为无根 Podman 设置 UNIX 套接字。

\n

这不是必要的,但如果你除了跑步之外

\n
$ systemctl --user start podman.service\n
Run Code Online (Sandbox Code Playgroud)\n

podman.service 将立即启动(甚至在第一个客户端连接到 UNIX 套接字之前)。

\n

更长的版本:

\n

如果podman.socket处于活动状态,则podman.service将在客户端连接时启动。(Podman支持socket激活

\n

如果podman.service已启用 ( ) 且延迟已启用 ( ),则podman.service也将在重新引导启动。systemctl --user enable podman.serviceloginctl enable-linger

\n

如果podman.service已启用 ( ) ,则当用户登录时, podman.service也会启动systemctl --user enable podman.service

\n

在podman.service中运行的 podman 进程将在不活动一段时间(默认为 5 秒)后自动退出。

\n

在 Fedora 36 计算机上,该Restart指令设置为no(默认值):

\n
$ grep Restart= /usr/lib/systemd/user/podman.service\n$ \n
Run Code Online (Sandbox Code Playgroud)\n

这意味着是否真的并不重要

\n
systemctl --user enable podman.service\n
Run Code Online (Sandbox Code Playgroud)\n

是否已运行。如果没有客户端访问,服务podman.service无论如何都会在 5 秒内停止。

\n