eriksjolund / podman-nginx-socket-activation

Demo of how to run socket-activated nginx with Podman
MIT License
27 stars 5 forks source link

How to run docker.io/library/nginx with rootless Podman and socket activation? #1

Closed eriksjolund closed 2 years ago

eriksjolund commented 2 years ago

I tried to run docker.io/library/nginx with rootless Podman and socket activation but it fails with the error message [crit] 1#1: getsockname() of the inherited socket #3 failed (88: Socket operation on non-socket)

To reproduce the error message:

$ mkdir ~/nginx_conf
$ podman create --env "NGINX=3;" -v ~/nginx_conf/default.conf:/etc/nginx/conf.d/default.conf:Z --name nginx docker.io/library/nginx
b115d7b3b21807905dfa4f33a4ca8834cf8a2c2ea52438a807116cf474fb6dc7
$ podman cp nginx:/etc/nginx/conf.d/default.conf ~/nginx_conf/
$ cp ~/nginx_conf/deafult.conf ~/nginx_conf/default.conf.orig
$ emacs -nw  ~/nginx_conf/deafult.conf

This diff shows the edit that was made

--- /home/test200/nginx_conf/default.conf.orig  2022-07-19 17:06:54.000000000 +0200
+++ /home/test200/nginx_conf/default.conf   2022-08-26 21:18:02.738482113 +0200
@@ -1,5 +1,5 @@
 server {
-    listen       80;
+    listen       0.0.0.0:8404;
     server_name  localhost;

     #access_log  /var/log/nginx/host.access.log  main;

Run

mkdir -p ~/.config/systemd/user
podman generate systemd --name --new nginx > ~/.config/systemd/user/nginx.service
systemctl --user daemon-reload

Create ~/.config/systemd/user/nginx.socket with this contents

[Unit]
Description=nginx

[Socket]
ListenStream=0.0.0.0:8404

[Install]
WantedBy=sockets.target

Start the socket and test with curl

systemctl --user start nginx.socket
curl localhost:8404

The error message [crit] 1#1: getsockname() of the inherited socket #3 failed (88: Socket operation on non-socket) is shown:

$ journalctl -xe --user -u  nginx.service | grep -A 2 "using inherited sockets from"
Aug 26 21:10:39 asus nginx[6798]: 2022/08/26 19:10:39 [notice] 1#1: using inherited sockets from "3;"
Aug 26 21:10:39 asus nginx[6798]: 2022/08/26 19:10:39 [crit] 1#1: getsockname() of the inherited socket #3 failed (88: Socket operation on non-socket)
Aug 26 21:10:39 asus nginx[6798]: nginx: [crit] getsockname() of the inherited socket #3 failed (88: Socket operation on non-socket)
$ 
Luap99 commented 2 years ago

Hey @eriksjolund, thanks for this investigation.

The official image does not work because they use a entrypoint script which will overwrite the fd number 3 with a new fd, see line 7 or 9.

Bash (and some other shells) have a feature which supports automatically using a free fd, see https://unix.stackexchange.com/questions/226164/what-does-exec-fd-dev-watchdog-do-in-bash. Unfortunately these tiny container shell do not seem to support this.

So to fix this the docker-entrypoint.sh must be patched to not overwrite fd 3 and instead use a free one.

eriksjolund commented 2 years ago

Thanks @Luap99 for finding the problem!

I created

and

(Currently this draft PR is a bit untested).

I removed the logging to FD 3 and instead wrapped the logging into a shell function, in other words, log messages are sent with

     entrypoint_log "$ME: info: can not guess the operating system"

instead of

    echo >&3 "$ME: info: can not guess the operating system"