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

具有特权端口映射的无根 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

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

$ sudo capsh --caps=CAP_NET_BIND_SERVICE+eip  -- -c 'podman run --rm -it  -p 80:80 nginx:stable-alpine'

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

由于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 

答案1

systemd 服务中的 Rootless PodmanUser=可以使用以下命令启动 nginx 容器套接字激活使用特权端口。

  1. 创建用户测试如果它还不存在。
    $ sudo useradd test
    
  2. 检查用户的UID测试
    $ id -u test
    1000
    
  3. 创建文件/etc/systemd/system/example3.service与内容
    [Unit]
    Wants=network-online.target
    After=network-online.target
    [email protected]
    [email protected]
    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
    
    (要调整适合您系统的文件,请替换1000为步骤 2 中找到的 UID)
  4. 提高安全性的可选步骤:编辑文件/etc/systemd/system/example3.service 并将选项添加--network nonepodman run命令中。有关详细信息,请参阅部分限制容器中网络的可能性
  5. 创建文件/etc/systemd/system/example3.socket与内容
    [Unit]
    Description=Example 3 socket
    
    [Socket]
    ListenStream=0.0.0.0:80
    
    [Install]
    WantedBy=sockets.target
    
  6. 重新加载系统配置
    $ sudo systemctl daemon-reload
    
  7. 启动套接字
    $ sudo systemctl start example3.socket
    
  8. 测试网络服务器
    $ curl localhost:80 | head -4
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    

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

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

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

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

相关内容