具有特权端口映射的无根 podman 容器

cze*_*rny 6 linux container podman

有没有办法启动具有映射特权端口的无根 podman 容器(容器服务通过主机的端口 1023 或更低端口公开)?

跑步

$ podman run --rm -it  -p 80:80 nginx:stable-alpine 
Error: rootlessport cannot expose privileged port 80, you can add 'net.ipv4.ip_unprivileged_port_start=80' to /etc/sysctl.conf (currently 1024), or choose a larger port number (>= 1024): listen tcp 0.0.0.0:80: bind: permission denied
Run Code Online (Sandbox Code Playgroud)

自然会因为权限不足而失败。

$ sudo capsh --caps=CAP_NET_BIND_SERVICE+eip  -- -c 'podman run --rm -it  -p 80:80 nginx:stable-alpine'
Run Code Online (Sandbox Code Playgroud)

root以用户身份运行 podman

$ sudo capsh --caps=CAP_NET_BIND_SERVICE+eip --user=$USER -- -c 'podman run --rm -it  -p 80:80 nginx:stable-alpine'
Unable to set group list for user: Operation not permitted
Run Code Online (Sandbox Code Playgroud)

由于su权限原因失败。

到目前为止,我最终得到了一个次优的解决方案,暂时允许任何进程绑定特权端口几秒钟:

sudo sysctl net.ipv4.ip_unprivileged_port_start=80 ;\
( sleep 5 ; sudo sysctl net.ipv4.ip_unprivileged_port_start=1024 ) &\
podman run --rm -it  -p 80:80 nginx:stable-alpine 
Run Code Online (Sandbox Code Playgroud)

Eri*_*und 0

systemd 服务中的 Rootless Podman可以使用特权端口通过套接字激活User=来启动 nginx 容器。

  1. 创建用户测试(如果尚不存在)。
    $ sudo useradd test
    
    Run Code Online (Sandbox Code Playgroud)
  2. 检查用户test的UID
    $ id -u test
    1000
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用以下内容 创建文件/etc/systemd/system/example3.service
    [Unit]
    Wants=network-online.target
    After=network-online.target
    Requires=user@1000.service
    After=user@1000.service
    RequiresMountsFor=/run/user/1000/containers
    
    [Service]
    User=test
    Environment=PODMAN_SYSTEMD_UNIT=%n
    KillMode=mixed
    ExecStop=/usr/bin/podman rm -f -i --cidfile=/run/user/1000/%N.cid
    ExecStopPost=-/usr/bin/podman rm -f -i --cidfile=/run/user/1000/%N.cid
    Delegate=yes
    Type=notify
    NotifyAccess=all
    SyslogIdentifier=%N
    ExecStart=/usr/bin/podman run \
         --cidfile=/run/user/1000/%N.cid \
         --cgroups=split \
         --rm \
         --env "NGINX=3;" \
          -d \
         --replace \
         --name systemd-%N \
         --sdnotify=conmon \
         docker.io/library/nginx
    
    Run Code Online (Sandbox Code Playgroud) (要调整适合您系统的文件,请替换1000为步骤 2 中找到的 UID)
  4. 提高安全性的可选步骤:编辑文件/etc/systemd/system/example3.service 并将该选项添加到命令--network none中podman run。有关详细信息,请参阅限制容器中网络的可能性部分
  5. 使用内容 创建文件/etc/systemd/system/example3.socket
    [Unit]
    Description=Example 3 socket
    
    [Socket]
    ListenStream=0.0.0.0:80
    
    [Install]
    WantedBy=sockets.target
    
    Run Code Online (Sandbox Code Playgroud)
  6. 重新加载系统配置
    $ sudo systemctl daemon-reload
    
    Run Code Online (Sandbox Code Playgroud)
  7. 启动套接字
    $ sudo systemctl start example3.socket
    
    Run Code Online (Sandbox Code Playgroud)
  8. 测试网络服务器
    $ curl localhost:80 | head -4
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    
    Run Code Online (Sandbox Code Playgroud)

请注意,本示例中使用的方法要求容器镜像支持套接字激活。例如docker.io/library/mariadb和docker.io/library/nginx支持套接字激活,但许多其他容器镜像不支持套接字激活。

上面的步骤来自我编写的演示: https://github.com/eriksjolund/podman-nginx-socket-activation/tree/main/examples/example3

我刚刚尝试过,所以我仍然需要弄清楚这个解决方案的效果如何。

有一个Podman 功能请求, 要求User=在 systemd 系统服务中添加 Podman 支持。该功能请求已移至 GitHub 讨论中。