有没有办法使用映射的特权端口启动无根 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 容器套接字激活使用特权端口。
- 创建用户测试如果它还不存在。
$ sudo useradd test
- 检查用户的UID测试
$ id -u test 1000
- 创建文件/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) - 提高安全性的可选步骤:编辑文件/etc/systemd/system/example3.service
并将选项添加
--network none
到podman run
命令中。有关详细信息,请参阅部分限制容器中网络的可能性 - 创建文件/etc/systemd/system/example3.socket与内容
[Unit] Description=Example 3 socket [Socket] ListenStream=0.0.0.0:80 [Install] WantedBy=sockets.target
- 重新加载系统配置
$ sudo systemctl daemon-reload
- 启动套接字
$ sudo systemctl start example3.socket
- 测试网络服务器
$ curl localhost:80 | head -4 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title>
注意,本例中使用的方法要求容器镜像支持套接字激活。例如docker.io/library/mariadb和docker.io/library/nginx支持套接字激活但许多其他容器镜像不支持套接字激活。
上面的步骤来自我写的一个demo: https://github.com/eriksjolund/podman-nginx-socket-activation/tree/main/examples/example3
我刚刚尝试过这个,所以我仍然需要弄清楚这个解决方案的效果如何。
有一个Podman 功能请求
用于添加 Podman 对User=
systemd 系统服务的支持。该功能请求已移至 GitHub 讨论中。