s6 and s6 overlay - blitterated/docker-dev-env-s6 GitHub Wiki
Here we'll explore setting up s6 in a container. We'll begin with just s6 by itself in a container, and then move on to setting up services.
The first approach will use the original service configuration in /etc/services.d
, and we'll try various ways of running it that way.
The second approach will use s6-rc
and s6-rc-compile
as well as running it in various ways.
Build an image that only installs and runs the s6 overlay.
cat <<"EOF" > Dockerfile
FROM ubuntu
RUN apt update && apt --yes upgrade && \
apt install --yes tar gzip
ADD https://github.com/just-containers/s6-overlay/releases/download/v2.2.0.3/s6-overlay-amd64-installer /tmp/
RUN chmod +x /tmp/s6-overlay-amd64-installer && \
/tmp/s6-overlay-amd64-installer /
ENTRYPOINT ["/init"]
EOF
docker build -t s6_ovrly .
Run a container and look at the output.
docker run -it --rm s6_ovrly /bin/bash
[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] done.
[services.d] starting services
[services.d] done.
root@a44bb3262771:/#
See what processes are running in the container.
ps a
PID TTY STAT TIME COMMAND
1 pts/0 Ss 0:00 s6-svscan -t0 /var/run/s6/services
35 pts/0 S 0:00 foreground if /etc/s6/init/init-stage2-redirfd foreground if if s6-echo -n -- [s6-
36 pts/0 S 0:00 s6-supervise s6-fdholderd
45 pts/0 S 0:00 foreground s6-setsid -gq -- with-contenv backtick -D 0 -n S6_LOGGING printcontenv S6_LOGGING impor
176 pts/0 S 0:00 /bin/bash
185 pts/0 R+ 0:00 ps a
Exit out of the container and observe its shutdown sequence.
exit
exit
[cmd] /bin/bash exited 0
[cont-finish.d] executing container finish scripts...
[cont-finish.d] done.
[s6-finish] waiting for services.
[s6-finish] sending all processes the TERM signal.
[s6-finish] sending all processes the KILL signal and exiting.
Run a container in daemon mode.
docker run -d --name s6_test s6_ovrly
Check that it's running.
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ee7182a481b8 s6_ovrly "/init" 8 seconds ago Up 7 seconds s6_test
That looks good. Now attach to it using docker exec
. There's no running shell or console right now, so docker attach
gives a blank and unresponsive terminal.
docker exec -it s6_test /bin/bash
Take a look at the running processes.
ps ax
PID TTY STAT TIME COMMAND
1 ? Ss 0:00 s6-svscan -t0 /var/run/s6/services
36 ? S 0:00 s6-supervise s6-fdholderd
177 pts/0 Ss 0:00 /bin/bash
186 pts/0 R+ 0:00 ps ax
Looks good. Now exit out of the container.
exit
The container will still be up and running.
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ee7182a481b8 s6_ovrly "/init" About a minute ago Up About a minute s6_test
It will have to be stopped explicitly.
docker stop s6_test
Double check that it's stopped.
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ee7182a481b8 s6_ovrly "/init" About a minute ago Exited (0) 4 seconds ago s6_test
If you want to restart, use docker start
. Do not use the --attach
switch as there's no console for it to attach to. You can use docker exec -it
instead.
docker start s6_test
docker exec -it s6_test /bin/bash
Delete the container.
docker rm s6_test
It has a three second delay to allow the container to get itself in order, and then every second it tells us how many bottles of beer are left on the wall. It will also trap SIGTERM, and exit appropriately. To help approximate a real daemon, all output is logged to STDERR.
cat <<"EOF" > beer.sh
#!/bin/sh
# echo out to STDERR
errcho () {
echo $@ >&2
}
# set up a handler for TERM signal
cut_off () {
errcho "WHADDYA MEAN I'M CUT OFF?"
exit 0
}
trap cut_off TERM
# Wait for other services to start, but don't block signals.
for i in $(seq 1 3)
do
sleep 1
done
# Drink!
for i in $(seq -s ' ' $BOTTLES -1 0)
do
case "$i" in
1) NUM_BOTTLES="1 bottle" ;;
0) NUM_BOTTLES="No more bottles" ;;
*) NUM_BOTTLES="$i bottles" ;;
esac
errcho "**CRASH!** $NUM_BOTTLES of beer on the wall, $NUM_BOTTLES of beer..."
sleep 1
done
exit 0
EOF
Make it executable.
chmod +x beer.sh
Here's a quick way to test.
BOTTLES=99 ./beer.sh &
The &
above will run it in the background and print out a PID. Use that PID to shut it down.
[1] 51078
kill 51078
Due to race conditions with the processes in the terminal, things may look a little garbled.
$ BOTTLES=99 ./beer.sh &
[1] 51078
$ **CRASH!** 99 bottles of beer on the wall, 99 bottles of beer...
**CRASH!** 98 bottles of beer on the wall, 98 bottles of beer...
**CRASH!** 97 bottles of beer on the wall, 97 bottles of beer...
**CRASH!** 96 bottles of beer on the wall, 96 bottles of beer...
kill**CRASH!** 95 bottles of beer on the wall, 95 bottles of beer...
**CRASH!** 94 bottles of beer on the wall, 94 bottles of beer...
**CRASH!** 93 bottles of beer on the wall, 93 bottles of beer...
5**CRASH!** 92 bottles of beer on the wall, 92 bottles of beer...
10**CRASH!** 91 bottles of beer on the wall, 91 bottles of beer...
78**CRASH!** 90 bottles of beer on the wall, 90 bottles of beer...
$ WHADDYA MEAN I'M CUT OFF?
[1]+ Done BOTTLES=99 ./beer.sh
$
The idea here is to use a simplistic faux daemon, the Beer Daemon, to observe the life cycle of a service in s6. We'll start off with the simpler and easier to use services.d
method. Then we'll move on to the much more flexible but also more complicated s6-rc
method.
s6 uses the /etc/services.d/
directory for managing services. Each subdirectory is a service, and requires a run
and finish
script.
We'll need to chain from with-contenv
into the runtime, execlineb
, in the run
script code in order for beer.sh
to be able to "see" the value of the BOTTLES
environment variable. s6 cleans the environment by default before starting services, and with-contenv
brings it all back.
See here for a committer's recommendation to use with-contenv
in reply to a user's issue with environment variable visibility in the run
script.
Another committer wrote the following about with-contenv
in an article about s6:
Each service is started with a completely blank environment, and it’s up to you to setup the environment variables. When the container starts up, all the environment variables are saved to /var/run/s6/container_environment/. The s6-overlay has a script to re-import all of those environment variables – with-contenv. It loads the environment variables, then chainloads into another program – so I recommend just including it in your run script’s shebang (#!) line
Another way to do this is to use envfile
and provide a file with environment variables assignments inside, but I'm just trying to keep this simple. Also I didn't know about this at the time of writing this example.
cat <<"EOF" > run
#!/usr/bin/env -S with-contenv execlineb
beer.sh
EOF
The example here is pretty contrived what with beer.sh
trapping SIGTERM, exiting, and then this finish
script printing out a quick message.
cat <<"EOF" > finish
#!/usr/bin/env -S with-contenv execlineb
echo You don't have to go home, but you can't stay here!
EOF
The Dockerfile does the following:
- copies
beer.sh
over into/opt/beer/
- copies
run
andfinish
into/etc/services.d/beer/
It also supplies the container with a number of bottles of beer to start with in the BOTTLES environment variable
cat <<"EOF" > Dockerfile
FROM ubuntu
RUN apt update && apt --yes upgrade && \
apt install --yes tar gzip
ADD https://github.com/just-containers/s6-overlay/releases/download/v2.2.0.3/s6-overlay-amd64-installer /tmp/
RUN chmod +x /tmp/s6-overlay-amd64-installer && \
/tmp/s6-overlay-amd64-installer /
COPY run /etc/services.d/beer/run
COPY finish /etc/services.d/beer/finish
COPY beer.sh /opt/beer/beer.sh
ENV PATH=$PATH:/opt/beer \
BOTTLES=20
ENTRYPOINT ["/init"]
EOF
The s6-overlay version 3 Dockerfile will need to do a couple of things differently than the version 2 Dockerfile.
- mark the
run
andfinish
scripts as executable. - add
/opt/beer/
to theglobal_path
file.
Alternatively, you could chmod +x
both run
and finish
before copying them to the image. You could also explicitly specify /opt/beer/
in the executable path in both run
and finish
as well. Neither one would probably break backwards compatibility with s6-overlay v2.
cat <<"EOF" > Dockerfile
FROM ubuntu
RUN apt update && apt --yes upgrade && \
apt install --yes tar xz-utils
ARG S6_OVERLAY_VERSION=3.0.0.2
ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch-${S6_OVERLAY_VERSION}.tar.xz /tmp
RUN tar -C / -Jxpf /tmp/s6-overlay-noarch-${S6_OVERLAY_VERSION}.tar.xz
ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-x86_64-${S6_OVERLAY_VERSION}.tar.xz /tmp
RUN tar -C / -Jxpf /tmp/s6-overlay-x86_64-${S6_OVERLAY_VERSION}.tar.xz
COPY run /etc/services.d/beer/run
COPY finish /etc/services.d/beer/finish
COPY beer.sh /opt/beer/beer.sh
RUN chmod +x /etc/services.d/beer/run && \
chmod +x /etc/services.d/beer/finish
RUN sed -i '$ s|$|:/opt/beer/|' \
/etc/s6-overlay/config/global_path
ENV BOTTLES=20
ENTRYPOINT ["/init"]
EOF
docker build -t s6_beer .
Before we run a container, let's take a look at how we can troubleshoot any issues with the beer daemon service.
This will stop any error messages from being display in the console (STDERR) while trying to troubleshoot.
stop:
s6-svc -Ot /var/run/s6/services/beer/
start:
s6-svc -u /var/run/s6/services/beer/
stop:
s6-rc -d change legacy-services
start:
s6-rc -u change legacy-services
Commands to examine and run service scripts after s6-overlay has copied them to the runtime location.
s6-overlay will copy /etc/services.d/beer/
to /var/run/s6/services/beer/
while starting up. See here for a good review of this.
list service directory:
ls /var/run/s6/services/beer/
run the service once manually:
/var/run/s6/services/beer/run
s6-overlay will copy /etc/services.d/beer/
to /run/s6/legacy-services/beer/
while starting up.
list service directory:
ls /run/s6/legacy-services/beer/
run the service once manually:
/run/s6/legacy-services/beer/run
Run a container.
docker run -it --rm s6_beer /bin/bash
The output looks good. Ctrl-D
was pressed just after 15 bottles to initiate shutdown of the container. We can see that the beer daemon printed out its countdown, then its TERM trap fired off in protest, and the finally
script gave its response.
$ docker run -it --rm s6_beer /bin/bash
[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] done.
[services.d] starting services
[services.d] done.
root@8e9a13109fd9:/# **CRASH!** 20 bottles of beer on the wall, 20 bottles of beer...
**CRASH!** 19 bottles of beer on the wall, 19 bottles of beer...
**CRASH!** 18 bottles of beer on the wall, 18 bottles of beer...
**CRASH!** 17 bottles of beer on the wall, 17 bottles of beer...
**CRASH!** 16 bottles of beer on the wall, 16 bottles of beer...
**CRASH!** 15 bottles of beer on the wall, 15 bottles of beer...
exit
[cmd] /bin/bash exited 0
[cont-finish.d] executing container finish scripts...
[cont-finish.d] done.
[s6-finish] waiting for services.
WHADDYA MEAN I'M CUT OFF?
You don't have to go home, but you can't stay here!
[s6-finish] sending all processes the TERM signal.
[s6-finish] sending all processes the KILL signal and exiting.
$
Let's take a look at s6 reloading the daemon once it's run its course. Fire up a container, but change the default number of bottles to 3.
docker run -it --rm --env BOTTLES=3 s6_beer /bin/bash
In the results, we can see that the finish script runs, and then the supervisor starts the daemon again with the run script.
[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] done.
[services.d] starting services
[services.d] done.
root@7472a4c2ec78:/# **CRASH!** 3 bottles of beer on the wall, 3 bottles of beer...
**CRASH!** 2 bottles of beer on the wall, 2 bottles of beer...
**CRASH!** 1 bottle of beer on the wall, 1 bottle of beer...
**CRASH!** No more bottles of beer on the wall, No more bottles of beer...
You don't have to go home, but you can't stay here!
**CRASH!** 3 bottles of beer on the wall, 3 bottles of beer...
**CRASH!** 2 bottles of beer on the wall, 2 bottles of beer...
**CRASH!** 1 bottle of beer on the wall, 1 bottle of beer...
**CRASH!** No more bottles of beer on the wall, No more bottles of beer...
You don't have to go home, but you can't stay here!
**CRASH!** 3 bottles of beer on the wall, 3 bottles of beer...
**CRASH!** 2 bottles of beer on the wall, 2 bottles of beer...
**CRASH!** 1 bottle of beer on the wall, 1 bottle of beer...
exit
[cmd] /bin/bash exited 0
[cont-finish.d] executing container finish scripts...
[cont-finish.d] done.
[s6-finish] waiting for services.
WHADDYA MEAN I'M CUT OFF?
You don't have to go home, but you can't stay here!
[s6-finish] sending all processes the TERM signal.
[s6-finish] sending all processes the KILL signal and exiting.
This is the same experiment as above, but we're running the beer daemon in a container that itself is running in daemon mode.
docker run -d --rm --env BOTTLES=3 --name s6_beerdaemon s6_beer
Then tail the container's logs with docker logs
docker logs --follow s6_beerdaemon
Use Ctrl-C
to exit the log tailing. Stop the daemon withe the following.
docker stop s6_beerdaemon
s6-overlay (not s6) in version 3 will automatically compile a directory, a.k.a. service database, from services definitions found in the /etc/s6-overlay/s6-rc.d/
directory on container start. With a typical s6 installation, it would be up to us to compile a directory manually with s6-rc-compile
, but s6-overlay takes care of that for us.
From the s6-overlay init doc:
stage2 reads two s6-rc source directories: the system one in /package/admin/s6-overlay/etc/s6-rc/sources, and a user-provided one in /etc/s6-overlay/s6-rc.d which must provide a bundle named "user" (which can be empty). It compiles these source directories into a compiled s6-rc database in /run/s6/db.
stage2 runs the s6-rc engine on that compiled database.
cat <<"EOF" > type
longrun
EOF
By default, s6-overlay version 3 does not import the PATH variable. All executables in a run
script require one of the following:
- fully qualified paths in the
run
script. - paths already added to
/etc/s6-overlay/config/global_path
. - paths specified in
S6_GLOBAL_PATH
(3.1.0.0 and higher)
we're just going with fully qualified paths in the executable.
cat <<"EOF" > run
#!/command/with-contenv execlineb
/opt/beer/beer.sh
EOF
s6-overlay version 3 requires run
to be marked executable
chmod +x run
Executables in a finish
script have the same path requirements as above. Still a contrived example, too.
This one doesn't need with-contenv
. There's no references to the environment paths or variables, just an echo
.
cat <<"EOF" > finish
#!/command/execlineb
echo You don't have to go home, but you can't stay here!
EOF
s6-overlay version 3 requires finish
to be marked executable
chmod +x finish
touch beer
The Dockerfile does the following:
- copies
beer.sh
over into/opt/beer/
- copies
type
andrun
into/etc/s6-overlay/s6-rc.d/beer/
- copies
beer
into/etc/s6-overlay/s6-rc.d/user/contents.d/
It also supplies the container with a number of bottles of beer to start with in the BOTTLES environment variable.
s6-overlay 3.0.0.2 version:
cat <<"EOF" > Dockerfile
FROM ubuntu
RUN apt update && apt --yes upgrade && \
apt install --yes tar xz-utils
ARG S6_OVERLAY_VERSION=3.0.0.2
ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch-${S6_OVERLAY_VERSION}.tar.xz /tmp
RUN tar -C / -Jxpf /tmp/s6-overlay-noarch-${S6_OVERLAY_VERSION}.tar.xz
ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-x86_64-${S6_OVERLAY_VERSION}.tar.xz /tmp
RUN tar -C / -Jxpf /tmp/s6-overlay-x86_64-${S6_OVERLAY_VERSION}.tar.xz
COPY type /etc/s6-overlay/s6-rc.d/beer/type
COPY run /etc/s6-overlay/s6-rc.d/beer/run
COPY finish /etc/s6-overlay/s6-rc.d/beer/finish
COPY beer /etc/s6-overlay/s6-rc.d/user/contents.d/beer
COPY beer.sh /opt/beer/beer.sh
ENV BOTTLES=20
ENTRYPOINT ["/init"]
EOF
Build the image.
docker build -t s6_beer .
Before we run a container, let's take a look at how we can troubleshoot any issues with the beer daemon service.
s6-rc
and s6-rc-db
are used to interact with services and the service database
stop:
s6-rc -d change beer
start:
s6-rc -u change beer
# list every active service
s6-rc -a list
# list every service in the current live database, active or not
s6-rc -d list
s6-rc-db list services
s6-rc-db -l /run/s6-rc list services
# list every service in a compiled database, active or not
s6-rc-db -c /run/s6/db list services
References:
Commands to examine and run service scripts after s6-overlay has copied them to the runtime location.
s6-overlay will compile services found in /etc/s6-overlay/s6-rc.d/
into a database found at /run/s6/db/servicedirs/
while starting up.
You really shouldn't ever do this, but sometimes it's handy for troubleshooting.
run the service once manually:
/run/s6/db/servicedirs/beer/run
Run a container.
docker run -it --rm s6_beer /bin/bash
This is the same experiment as above, but we're running the beer daemon in a container that itself is running in daemon mode.
docker run -d --rm --name s6_beerdaemon s6_beer
Then tail the container's logs with docker logs
docker logs --follow s6_beerdaemon
Use Ctrl-C
to exit the log tailing. Stop the daemon withe the following.
docker stop s6_beerdaemon
The two ways are contrasted starting in the second paragraph of the "Writing a service script" section of the s6-overlay README.
Examples of both approaches are in the logging section of the s6-overlay README.
The s6-rc
approach is NOT available in the 2.x versions.
The s6-rc
approach is recommended by the developers. They have this to say at the end of the Logging section in the s6-overlay README:
It (
s6-rc
) really accomplishes the same things as the/etc/cont-init.d
plus/etc/services.d
method, but it's a lot cleaner underneath, and can handle much more complex dependency graphs, so whenever you get the opportunity, we recommend you familiarize yourself with the s6-rc way of declaring your services and your loggers.
The services.d
approach is considered legacy by the developers. See the "stage 2" bullet item in the Init stages portion or the s6-overlay README:
stage 2: This is where most of the end-user provided files are meant to be executed:
i. Execute legacy oneshot user scripts contained in
/etc/cont-init.d
.ii. Run user s6-rc services declared in
/etc/s6-overlay/s6-rc.d
, following dependenciesiii. Copy legacy longrun user services (
/etc/services.d
) to a temporary directory and have s6 start (and supervise) them.
All that being said, the services.d
method is much easier to configure. It appears to me that the nuanced approach of s6-rc
is beyond the scope of what's needed for running s6 and services in a container. It's a better fit for an actual OS distribution running on metal or in a VM. That's where you're more likely to have many more services and processes running in the background with complex dependency graphs.
I wasn't paying attention that 3.0.0.0 had just came out. The README had changed to 3.0.0.0, but I was still using s6-overlay 2.2.0.3. Once I noticed, I checked the README for 2.2.0.3, and there's no mention of s6-rc
anywhere.
cat <<"EOF" > Dockerfile
FROM ubuntu
RUN apt update && apt --yes upgrade && \
apt install --yes tar gzip
ADD https://github.com/just-containers/s6-overlay/releases/download/v2.2.0.3/s6-overlay-amd64-installer /tmp/
RUN chmod +x /tmp/s6-overlay-amd64-installer && \
/tmp/s6-overlay-amd64-installer /
COPY type /etc/s6-overlay/s6-rc.d/beer/type
COPY run /etc/s6-overlay/s6-rc.d/beer/run
COPY beer /etc/s6-overlay/s6-rc.d/user/contents.d/beer
COPY beer.sh /opt/beer/beer.sh
ENV PATH=$PATH:/opt/beer \
BOTTLES=20
ENTRYPOINT ["/init"]
EOF
docker build -t s6_beer .
docker run -ti --rm s6_beer /bin/bash
[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] done.
[services.d] starting services
[services.d] done.
cd /etc/s6-overlay/s6-rc.d/beer/
sh run
**CRASH!** 20 bottles of beer on the wall, 20 bottles of beer...
**CRASH!** 19 bottles of beer on the wall, 19 bottles of beer...
**CRASH!** 18 bottles of beer on the wall, 18 bottles of beer...
**CRASH!** 17 bottles of beer on the wall, 17 bottles of beer...
**CRASH!** 16 bottles of beer on the wall, 16 bottles of beer...
**CRASH!** 15 bottles of beer on the wall, 15 bottles of beer...
**CRASH!** 14 bottles of beer on the wall, 14 bottles of beer...
**CRASH!** 13 bottles of beer on the wall, 13 bottles of beer...
**CRASH!** 12 bottles of beer on the wall, 12 bottles of beer...
**CRASH!** 11 bottles of beer on the wall, 11 bottles of beer...
**CRASH!** 10 bottles of beer on the wall, 10 bottles of beer...
**CRASH!** 9 bottles of beer on the wall, 9 bottles of beer...
**CRASH!** 8 bottles of beer on the wall, 8 bottles of beer...
**CRASH!** 7 bottles of beer on the wall, 7 bottles of beer...
**CRASH!** 6 bottles of beer on the wall, 6 bottles of beer...
**CRASH!** 5 bottles of beer on the wall, 5 bottles of beer...
**CRASH!** 4 bottles of beer on the wall, 4 bottles of beer...
**CRASH!** 3 bottles of beer on the wall, 3 bottles of beer...
**CRASH!** 2 bottles of beer on the wall, 2 bottles of beer...
**CRASH!** 1 bottle of beer on the wall, 1 bottle of beer...
**CRASH!** No more bottles of beer on the wall, No more bottles of beer...
tree /etc/s6-overlay/s6-rc.d
/etc/s6-overlay/s6-rc.d
|-- beer
| |-- run
| `-- type
`-- user
`-- contents.d
`-- beer
tree /var/run/s6
/var/run/s6
|-- container_environment
| |-- BOTTLES
| |-- CWD
| |-- HOME
| |-- HOSTNAME
| |-- PATH
| `-- TERM
|-- env-stage1
| `-- PATH
|-- env-stage2
|-- env-stage3
|-- etc
| |-- cont-finish.d -> /etc/cont-finish.d
| |-- cont-init.d -> /etc/cont-init.d
| |-- fix-attrs.d -> /etc/fix-attrs.d
| `-- services.d -> /etc/services.d
`-- services
`-- s6-fdholderd
|-- down
|-- event
|-- notification-fd
|-- rules
| `-- uid
| |-- 0
| | |-- allow
| | `-- env
| | |-- S6_FDHOLDER_GETDUMP
| | |-- S6_FDHOLDER_LIST
| | |-- S6_FDHOLDER_RETRIEVE_REGEX
| | |-- S6_FDHOLDER_SETDUMP
| | `-- S6_FDHOLDER_STORE_REGEX
| `-- default
| |-- allow
| `-- env
| `-- S6_FDHOLDER_LIST
|-- run
`-- supervise
|-- control
|-- death_tally
|-- lock
`-- status
19 directories, 22 files
These are things I used to guide my way through writing this page.
- Run multiple processes. For example:
- init
- sshd
- tmux session
- Gradle Daemon
- init
- Prevent any failed processes from shutting down the container.
- by default s6 will not terminate the container. You need a finish script.
- It will, however, restart anything running as a service.
- Logging
- possibly even with fake syslogng
-
figure out how to shut down an s6 container.
-
docker stop
should work. It'll trigger s6'sinit
to send SIGTERM to all child processes.- This won't work if the Dockerfile uses shell mode for CMD or ENTRYPOINT. The
/bin/sh -c
wrapper process won't pass along the SIGTERM signal.
- This won't work if the Dockerfile uses shell mode for CMD or ENTRYPOINT. The
-
ctrl-d
inside the container should work.
-
-
figure out how to prevent a service from restarting. Here's a few ways:
-
-O : mark the service to run once at most. iow: do not restart the supervised process when it dies. If it is down when the command is received, do not even start it.
-
A finish script exiting with exit code 125
If the finish script exits 125, then s6-supervise interprets this as a permanent failure for the service, and does not restart it, as if an s6-svc -O command had been sent.
-
The new way is to make an
s6-rc
source definition directory in the/etc/s6-overlay/s6-rc.d
directory, and add the name of that directory to the user bundle, i.e. create an empty file with the same name in the/etc/s6-overlay/s6-rc.d/user/contents.d
directory. Note that you can define longruns, i.e. daemons that will get supervised by s6 just like with the/etc/services.d
method, but also oneshots, i.e. programs that will run once and exit.
-
-
Configure and test container staying up if one of the processes dies.
- This flies in the face of Docker philosophy, but seems like it'd be beneficial for development.
- May not have to do anything. "finish scripts" that call
s6-svscanctl
are optional and have to be explicitly written.- https://github.com/just-containers/s6-overlay#writing-an-optional-finish-script
- May need a finish script to prevent a service from restarting though.