Spawn-fcgi doesn't run after container start

Hi, I’m trying to create a gitweb docker image but I’m stuck on launching the fcgi process after container started up.

My Dockerfile:

FROM alpine:3.18

RUN apk update
RUN apk add --no-cache bash nginx cifs-utils git-gitweb perl-cgi fcgiwrap spawn-fcgi highlight perl-cgi-fast perl-cgi perl-fcgi

COPY nginx_config.conf /etc/nginx/http.d/default.conf
COPY gitweb.conf /etc/gitweb.conf

RUN set -x ; \
  addgroup -g 82 -S www-data ; \
  adduser -u 82 -D -S -G www-data www-data && exit 0 ; exit 1

RUN chown -R www-data:www-data /usr/share/nginx/*
RUN chmod -R 0755 /usr/share/nginx/*
RUN chown -R www-data:www-data /var/run/fcgiwrap/

RUN mkdir /mnt/git_repos


CMD ["nginx", "-g", "daemon off;"]

RUN spawn-fcgi -u 82 -g 82 -s /var/run/fcgiwrap/fcgiwrap.socket /usr/bin/fcgiwrap
# alternatively tried:
#CMD ["spawn-fcgi", "-u", "82", "-g", "82", "-s", "/var/run/fcgiwrap/fcgiwrap.socket" "/usr/bin/fcgiwrap"]

Building the image works.
Starting the image works.
Nginx starts up but gitweb access failes because of the spawn-fcgi process / socket (“No such file or directory”). The socket file is missing.

I can start the process inside the container successfully:
spawn-fcgi -u 82 -g 82 -s /var/run/fcgiwrap/fcgiwrap.socket /usr/bin/fcgiwrap

Then everything works fine. But I dont want to run the command manually and at startup automatically.

What am I missing?

As a workaround I tried the following which doesn’t work either. The process is not running after startup.

Adding the following to the end of the Dockerfile. Building works.


# start fcgi
spawn-fcgi -u 82 -g 82 -s /var/run/fcgiwrap/fcgiwrap.socket /usr/bin/fcgiwrap

At the end of the Dockerfile:

COPY /tmp/
RUN /tmp/

Thanks for your help!

Each Dockerifile instruction uses a fresh build container for its operation. Thus, no processes are kept alive.

So if you want your container to start something, you will need to handle it using the ENTRYPOINT and/or CMD instruction. @rimelek made a blog post about how these instructions compose the command the container will execute when started: Constructing commands to run in Docker containers - DEV Community

If it’s possible to use a tcp socket connection, instead of a socket connection, you should prefer it, as a container is only able to forward the SIGTERM signal to a single process. Though, you try to run spawn-fcgi and nginx inside the container, so the solution will always be unclean unless a process manager like tiny or s6-overlay is used.

Thank you for your reply and the instructions. I now tried the following options:

1) Using CMD directly in Dockerfile:
CMD "/usr/bin/spawn-fcgi -u 82 -g 82 -s /var/run/fcgiwrap/fcgiwrap.socket /usr/bin/fcgiwrap"
The container posts the following logs and stops:
/bin/sh: /usr/bin/spawn-fcgi -u 82 -g 82 -s /var/run/fcgiwrap/fcgiwrap.socket /usr/bin/fcgiwrap: not found

Starting the container without the command I can verify that all these pathes und binaries exist. Maybe not at the start time of the container?

2) Using CMD with shell script in Dockerfile (with and without shebang):

COPY /tmp/
RUN chmod +x /tmp/
CMD /tmp/

The container posts the following logs and stops:
spawn-fcgi: child spawned successfully: PID: 9

3) Using ENTRYPOINT in Dockerfile:

COPY /tmp/
RUN chmod +x /tmp/
ENTRYPOINT ["/tmp/"]

The container posts the following logs and stops:
spawn-fcgi: child spawned successfully: PID: 8

PS: I couldn’t find any information that gitweb supports TCP sockket.

Have you checked the my blogpost recommended by @meyay? The answer is in that post. In the second example:

But use the exec form for the CMD instruction rather than the shell form. You actually had a correct instruction in your first post in comment.

I made that blogpost so we don’t have to write long explanations here about the same topic every day. It is important to know how the CMD and other instructions work.

Then I guess it is running in the background as a service

ENTRYPOINT or CMD, it doesn§t matter. My blogpost explains (I also have a video link in the written version) how you can use these instructions together. If you use just one of them, it is just means you chose a different way to run the same script, but the process in the container has to run in the foreground in order to keep the container alive.

By the way, if you just want to use a lightweight git server, you can also try Gogs. I used it for years on my VPS. It is not a replacement of gitweb, but much more, so I just leave it here in case you are interested.

Thank your for your hints. I do know understand the reason for “the not found” problem.

But as you wrote, the reason seems to be the background service. But why?

I also run the nginx process in the same container. When I run the container without spawn-cgi, the container stays alive without a problem. But when I add the fcgi process additionally the container dies after starting. Even if I place the nginx CMD after it, like:

CMD ["spawn-fcgi", "-u", "82", "-g", "82", "-s", "/var/run/fcgiwrap/fcgiwrap.socket" "/usr/bin/fcgiwrap"]
CMD ["nginx", "-g", "daemon off;"]

I found some hints like the following but this seems tweaked to me.
CMD command & sleep infinity

And thank you for the suggestion of Gogs. I will have a look. I nevertheless hope you can answer my question above because I’m really trying to understand and to become better at building docker images.

You might want to look at it’s fork Gitea, or Gitea’s fork Forgejo instead.

As all of them are either Gogs or offsprings of Gogs, they all share that they have a very small cpu/memory footprint in general.

Please stop following your approach with handling everything using a CMD instruction → the solution always remains messy, unless you start using a process supervisor like s6-overlay.

I’m not entirely sure what you are referring to. Could you quote tha part from my message?

If you mean this

I was writing about spawn-cgi itself. Processes has to run in the foreground in the container. Since I don’t use GitWeb or spawn-fcgi, I leave to you to figure it out how it runs.

Did you really used the CMD instruction twice? You can’t do that. The last CMD instruction will always overwrite the previous one so if you put a CMD instruction after at the end that runs a process which stops or starts in the background therefore the container stops, it will never work.

As @meyay suggested. I also have a tutorial, but that doesn’t mention s6-overlay, which would be probably smaller than Supervisor, but I haven’t used it yet except for one test maybe.

I’m afraid I’m unable to quote any answers - I simply can’t find the function. Sorry. :zipper_mouth_face:

Thank you @rimelek and @meyay. You made me realise I had to do some more ground work of learning instead of heading forward into it. For example I had a complete missunderstanding of how the CMD command works.

On the first look Gitea seemed to be a good alternative but I’m going to check it out further.

It appears when you select a text with your mouse, but copying the relevant text and pasting it into a new message between quotation marks is fine too. I just noted it so you can use it next time.