Skip to content

supervisord in the container

This project's own container runs supervisord, and php-fpm and the web server run under it. Nothing on this pane has to be added or configured: the container is already known.

That is not true of every project. StackVo's generated image uses supervisord for the nginx and caddy servers; apache, frankenphp and swoole start their server another way, and a project that is not PHP has no supervisord at all. The pane says so rather than looking broken.

What the rows say

Mark What it means
Green RUNNING.
Red FATAL — it gave up, and the row says why.
Blue Starting, stopping, or backing off.
Grey Stopped.
Keeps restarting It comes back up every time, and it keeps dying.

The last one is not something supervisord reports. It is worked out by watching the process id change between looks, because the state column cannot show it: a php-fpm that has crashed and restarted forty times in the last minute says RUNNING every single time you ask.

Health checks

RUNNING means the process is up. It says nothing about whether the thing inside it is answering — a php-fpm out of workers and a web server returning 502 both look RUNNING.

The heart button on a row adds a probe for that process: an HTTP request to an address, or a TCP connection to a host and port. One per process, because a process either answers or it does not. The form has a Try it now button, so a check can be proved before it is saved.

A health endpoint behind authentication answers 401 and is working, so the status that counts as answering is a field rather than a constant.

Two things this deliberately does not do:

  • It does not restart anything. A local tool that silently restarted php-fpm would be hiding the exact thing somebody opened it to see.
  • It does not run against a stopped project. A probe of a container that is not there can only fail.

Being told when something breaks

While StackVo is open, every running project is looked at every twenty seconds in the background, and a desktop notification arrives when a process gives up, starts restarting over and over, or stops answering its health check.

The looking is done by the app itself rather than by this pane, and that is the whole point: a poll that only ran while this tab was open could only ever tell you what was already in front of you.

  • It says a thing once. A process sitting in FATAL is not news every twenty seconds — it was news when it got there. If it recovers and breaks again, that is news again.
  • It says nothing on the first look. A process that was already broken when StackVo opened did not just break.
  • It fixes nothing. No process is restarted. A tool that quietly restarted something while nobody was watching would be hiding the event it was built to surface.

A project whose container has no reachable supervisord raises nothing. Most projects are not PHP or run a server that does not use one, and announcing that every twenty seconds would be announcing the shape of your workspace.

When it says it cannot see anything

What it says What to do
No supervisord in this project Nothing — this project's server does not use one.
Rebuild the project The image was built before StackVo put a socket in the generated supervisord.conf. Rebuilding writes the new config in.
The container is not running Start the project.

Your own processes

The two rows the image comes with are not the whole story. A queue worker, a scheduler, a socket server — anything the project needs kept running — goes into stackvo.json under processes, and StackVo writes it into the same generated config:

"processes": {
  "scheduler": { "exec": ["php", "artisan", "schedule:work"] },
  "queue": { "exec": ["php", "artisan", "queue:work", "--tries=3"], "replicas": 2, "stopWait": 30 }
}

This is the only way that survives. The config in this container is generated by StackVo and baked into the image, so a program added inside a running container — or a file dropped into conf.d/ — is gone at the next rebuild, and the pane then shows the two rows it started with. Declared in the manifest, a rebuild restores it and a teammate's clone gets it.

A rebuild is not needed to start one. When the manifest declares something the running daemon does not have, a banner names it with an Apply button: the config is written into the container and supervisord re-reads it, starting what is new and leaving php-fpm and the web server as they were. The reverse is named too — a process running here that the manifest does not declare — because the next rebuild will drop it, and that is better said before than after.

The daemon as a whole

The terminal button on the pane's header, beside help, is supervisorctl for the daemon rather than for one row: status, re-read the config (reread), apply config changes (update), and start, stop or restart all. The daemon's own answer is shown under the header — queue: added process group, nginx: stopped, ERROR: CANT_REREAD — until it is closed, because those words are the point of asking.

Stop all and restart all ask first: all includes php-fpm and the web server, so the site goes down with the workers. reread and update here read whatever config the container holds; to push what stackvo.json declares first, use the Apply button the pane shows when the two differ.

One process in full

The info button on a row opens the process: what the daemon reports now, what stackvo.json declares for it, the [program:] block exactly as the config file in the container has it, and what it is costing — resident memory, threads, and CPU as a lifetime average, the number ps prints as %cpu. Each section is labelled by where the value came from, because the manifest and the file agree after a rebuild or an apply and disagree in between, and this is where you see which.

The chip beside the name says who put the process there: from the image for php-fpm and the web server, from stackvo.json for a declared one, and not declared for one the daemon is running that neither explains — added inside the container, and gone at the next rebuild.

The Log tab of the same sheet tails the process's log and follows it while open. A declared process writes to its own file, /var/log/supervisor-<id>.log, rotated by supervisord at 10 MB with three kept — a file, because supervisord cannot read a device back: php-fpm and the web server write to the container's stdout, and supervisorctl tail on that answers ERROR (unknown error reading log). For those two the tab shows the container's own output instead — every process mixed, which is what stdout is — and says so above it.

From here a process can be stopped, started, restarted, or sent a signal (HUP, USR1, TERM, …). Sending stdin is deliberately not offered: the daemon is reached through supervisorctl, which cannot do it.

Worth knowing

  • Nothing here is edited by hand. Change a process by changing processes in the manifest, then apply or rebuild.
  • The socket is a Unix socket inside the container, mode 0700. Nothing is published and no port is opened — reaching it means already being able to run a process in that container.
  • Restarting php-fpm here restarts PHP without restarting the container, so the web server keeps its connections and you do not wait for a whole boot.
  • php-fpm and the web server write to the container's stdout, which is the project's Logs tab. A declared process writes to its own file under /var/log, which the Log tab here reads.