Self-hosted service
just-containers/s6-overlay avatar
just-containers/s6-overlay

s6-overlay: a process supervisor and PID 1 for Docker containers

s6 overlay for containers (includes execline, s6-linux-utils & a custom init)

4,590 stars240 forksShellNOASSERTION

At a glance

What is it?
s6-overlay adds a real init system to any Docker image, with staged init, service supervision and log rotation. It is aimed at image authors who want multiple processes in one container without losing clean shutdowns.
Who is it for?
Adopt s6-overlay if you maintain a base image or an application image that legitimately runs several cooperating processes and you want a supervisor that still lets the container exit when a service fails. Do not adopt it if your image runs a single foreground binary, because an entrypoint wrapper gets you the same result with less surface area.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 76 days ago.
What is it written in?
Mainly Shell, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What s6-overlay solves for image authors

A container that runs several processes has a problem the single-process case does not: something has to be PID 1, reap orphans, and decide what happens when one of the processes dies. The README states the goal plainly, that s6-overlay should be usable on top of any Docker image and provide a stable pid 1, a fast and orderly init sequence and shutdown sequence, and process supervision with automatically rotated logs. It is distributed as tarballs you extract over an existing image, so it does not dictate a base distribution. Ubuntu, CentOS, Fedora, Alpine and Busybox are all listed as usable.

The audience is narrower than the topic list suggests. This is a tool for people who build images, not for people who only run them. If you pull an image that already contains s6-overlay, you interact with it through environment variables and by dropping scripts into directories. If you are writing the Dockerfile, you are the one who decides whether the overlay is there at all.

Init stages, supervision and the exit-code question

The overlay installs a set of scripts and utilities, with /init as the entrypoint. Init runs in stages. User initialization tasks go in cont-init.d, finalization tasks in cont-finish.d, and services are supervised by s6. The README's example of docker top on a running container shows the shape of the process tree: s6-svscan at the root, s6-supervise below it, rc.init running the init stage, and nginx's worker processes underneath.

The design decision worth noticing is that s6-overlay does not treat restart-on-failure as mandatory. The README argues against the assumption that a process supervisor must restart failed services, because a container that never exits breaks the expectation that a failure surfaces to whoever is running the container. The project's own framing is "one thing per container" rather than "one process per container", so a chat service or a GitLab instance can be several processes while still being one thing.

Logging is handled by logutil-service, which the README says uses s6-log underneath, so rotation is configured rather than bolted on with a sidecar. The README also notes that Docker's USER directive has some support, to run the whole process tree as a specific user, but explicitly says this is not compatible with all features and points to the notes section. That is a real boundary, not a footnote.

Installing s6-overlay and running a first service

The README's quickstart builds an image from a base of your choice, downloads two tarballs for a pinned version, extracts both at the filesystem root, and sets /init as the entrypoint. The noarch tarball carries the scripts and the architecture tarball carries the binaries. The version is passed as a build argument, so it is easy to bump.

dockerfile
FROM ubuntu
ARG S6_OVERLAY_VERSION=3.2.3.2

RUN apt-get update && apt-get install -y nginx xz-utils
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
CMD ["/usr/sbin/nginx"]

ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz /tmp
RUN tar -C / -Jxpf /tmp/s6-overlay-noarch.tar.xz
ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-x86_64.tar.xz /tmp
RUN tar -C / -Jxpf /tmp/s6-overlay-x86_64.tar.xz
ENTRYPOINT ["/init"]

Build and run it, then inspect the process tree. The README shows docker top with the acxf flags, and the output lists s6-svscan, s6-supervise, rc.init and the nginx workers. If you see that tree, the overlay is in place and nginx was started by the init stage rather than by Docker directly.

bash
docker build -t demo .
docker run --name s6demo -d -p 80:80 demo
docker top s6demo acxf

A request to the published port should return the nginx default page, which is what the README's curl example shows. The README also points out that the architecture tarball name depends on your target architecture, and that the suffix is not always the same as the Docker platform string, so check that mapping before copying a Dockerfile between builds.

Where s6-overlay gets in the way

The first cost is that you now own an init system. Scripts in cont-init.d and cont-finish.d run in a defined order, and services need a service script in the expected layout. For a container that starts one binary and exits with it, that is overhead with no return, and the README's own features list describes the overlay as a turnkey s6 installation rather than something you assemble. If your image is a single foreground process, the problem s6-overlay solves does not exist in your image.

Running as a non-root user is the second boundary. The README states plainly that support for Docker's USER directive is partial and not compatible with all features. If your deployment requires the whole tree to run unprivileged, verify each feature you rely on against the notes section before you design around it.

Upgrades are the third. The project keeps a separate MOVING-TO-V3.md page because v2 to v3 required changes to services and to how the overlay is used, and the README says you may need to change your services for everything to work smoothly. Pinning the version in a build argument, as the quickstart does, is the practical mitigation, but it means the upgrade is a deliberate act with a migration checklist rather than a rebuild.

s6-overlay compared with supervisord and tini

supervisord and s6-overlay overlap in intent but differ in what they are. supervisord is a Python process manager that you point at a config file, and it runs as a normal process inside the container. s6-overlay replaces PID 1 itself, installs s6 and execline as binaries, and splits startup into init, service supervision and finalization stages. The practical difference is that s6-overlay also handles orphan reaping and orderly shutdown, which the README lists as a feature, while a Python supervisor leaves those to whatever is at PID 1.

tini is the other comparison people make. tini is small and does one job: it runs as PID 1, forwards signals and reaps zombies. It does not supervise services, run init scripts, or rotate logs. If all you need is correct signal handling and no zombies, tini is the smaller answer. s6-overlay is the larger answer for the same problem plus process management, and the price is the staged directory layout and the service scripts you have to write.

Build, licence and upgrade cost

The overlay is built from a Makefile that pulls in conf/defaults.mk, conf/versions, mk/toolchain.mk, mk/bearssl.mk and mk/skaware.mk, and produces the tarballs the quickstart downloads: rootfs-overlay-arch-tarball, symlinks-overlay-arch-tarball, rootfs-overlay-noarch-tarball, symlinks-overlay-noarch-tarball and syslogd-overlay-noarch-tarball. The arch tarball target depends on building execlineb from the skaware sources, so the build is not a trivial packaging step. The README includes a section on building the overlay yourself for anyone who needs to.

The repository is not archived, and the last push was on 2026-07-16. The releases listed are v3.2.3.0 from 2026-05-09, v3.2.3.1 from 2026-07-14 and v3.2.3.2 from 2026-07-16, so patch releases arrive close together while minor versions are further apart. Upgrading means re-extracting tarballs at a new pinned version and reading the upgrade notes for anything that changed between the two.

The licence is recorded as NOASSERTION, which means the repository metadata does not map to a recognised SPDX identifier. The repository contains a COPYING file and an AUTHORS.md, and the README has a Verifying Downloads section covering how to check the tarballs you fetch. Read COPYING yourself and follow your own organisation's process, nothing here is legal advice.

Editorial conclusion

Adopt s6-overlay if you maintain a base image or an application image that legitimately runs several cooperating processes and you want a supervisor that still lets the container exit when a service fails. Do not adopt it if your image runs a single foreground binary, because an entrypoint wrapper gets you the same result with less surface area. Before committing, check the MOVING-TO-V3.md page against any v2 scripts you have, and confirm the architecture tarball name matches your build platform.

Frequently asked questions

What is s6-overlay in a Docker container?

It is a set of scripts and utilities that installs s6 as PID 1 in an existing image, so the container gets a stable init sequence, process supervision and log rotation. It is added by extracting the noarch and architecture tarballs over the image and setting /init as the entrypoint.

How does s6-overlay compare with tini?

tini runs as PID 1 to forward signals and reap zombies, and does nothing else. s6-overlay covers that ground and adds staged init scripts, service supervision with dependencies, and log rotation through logutil-service.

How does s6-overlay compare with supervisord?

supervisord is a process manager that runs inside the container as a normal process, while s6-overlay replaces PID 1 and installs s6 and execline as binaries. The README lists orphan reaping and orderly shutdown as part of what the overlay provides.

What are the alternatives to s6-overlay?

The realistic alternatives are a minimal PID 1 such as tini, or a supervisor that runs inside the container such as supervisord. Choose tini when signal handling is the only problem, and a supervisor when you also need process management but can accept a non-PID-1 design.

Official sources

  1. Issues
  2. just-containers/s6-overlay on GitHub
  3. README
  4. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/just-containers-s6-overlay.svg)](https://hysenlabs.com/projects/just-containers-s6-overlay)