https://github.com/ericwq/s6
docker image with s6-overlay or openrc as init system.
https://github.com/ericwq/s6
Last synced: 6 months ago
JSON representation
docker image with s6-overlay or openrc as init system.
- Host: GitHub
- URL: https://github.com/ericwq/s6
- Owner: ericwq
- License: cc0-1.0
- Created: 2023-05-05T01:49:37.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2023-05-30T01:17:32.000Z (about 3 years ago)
- Last Synced: 2025-07-23T12:20:33.164Z (about 1 year ago)
- Language: Dockerfile
- Homepage:
- Size: 45.9 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# alpine container with s6-rc or openrc support
This is an alpine container which suppport [s6](https://skarnet.org/software/s6/) or [openrc](https://github.com/OpenRC/openrc) as init system. The container need [utmps](https://git.skarnet.org/cgi-bin/cgit.cgi/utmps/about/) service and [ssh](https://www.openssh.com/) service. The sshd service is used to support remote login. The utmps services is used to support `last` and `who` command.
I came cross s6 because `utmps` need a process supervisor. `utmps` is required because default alpine doesn't support [utmpx.h API](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/utmpx.h.html). I tried `s6` first, after several days study, it turns out to be that [s6-rc](https://skarnet.org/software/s6-rc/index.html) and [s6-overlay](https://github.com/just-containers/s6-overlay) is what I need for container. With the help from [utmps document](https://git.skarnet.org/cgi-bin/cgit.cgi/utmps/tree/examples/s6-rc), I built a `s6-rc` container for `utmps`. Eventually, s6-rc container has all the required packages, except the utmps init script. That means the container cant't support `last` and `who` command, even if the container has all the necessary services.
`openrc` is the next effort. Got a clue from this [post](https://gitlab.alpinelinux.org/alpine/aports/-/issues/13659). Then a [dockerfile](https://github.com/dockage/alpine/blob/main/3.17/Dockerfile) in github.com help me to build the `openrc` container. This time the container can support `last` and `who` command.
Compare s6-rc container and openrc container, `utmps-openrc` package is the key to provide init script for openrc container. Maybe you can find the solution from the `utmps-openrc` package. The following is the content of `utmps-openrc`:
utmps-openrc package
```sh
openrc-ssh:/etc/init.d# apk info -a utmps-openrc
utmps-openrc-0.1.2.1-r1 description:
A secure utmp/wtmp implementation (OpenRC init scripts)
utmps-openrc-0.1.2.1-r1 webpage:
https://skarnet.org/software/utmps/
utmps-openrc-0.1.2.1-r1 installed size:
32 KiB
utmps-openrc-0.1.2.1-r1 depends on:
utmps-openrc-0.1.2.1-r1 provides:
utmps-openrc-0.1.2.1-r1 is required by:
utmps-openrc-0.1.2.1-r1 contains:
etc/init.d/btmpd
etc/init.d/utmp-init
etc/init.d/utmp-prepare
etc/init.d/utmpd
etc/init.d/wtmpd
utmps-openrc-0.1.2.1-r1 triggers:
utmps-openrc-0.1.2.1-r1 has auto-install rule:
openrc
utmps=0.1.2.1-r1
utmps-openrc-0.1.2.1-r1 affects auto-installation of:
utmps-openrc-0.1.2.1-r1 replaces:
utmps-openrc-0.1.2.1-r1 license:
ISC
```
If you check the `utmps-openrc` package, you will find the `utmp-init`, `utmp-prepare` script.
I don't have enough time to research all available init system. There is some articles to compare the init systems:
- [A new service manager for Linux distributions](https://skarnet.com/projects/service-manager.html)
- [Why another supervision suite ?](https://skarnet.org/software/s6/why.html)
- [Why s6-rc ?](https://skarnet.org/software/s6-rc/why.html)
- [Comparison of init systems](https://wiki.gentoo.org/wiki/Comparison_of_init_systems)
- [systemd bad for dev and gentoo?](https://forums.gentoo.org/viewtopic-t-994548.html).
## openrc container
This container use `openrc` as the init system. It also support utmpd, wtmpd and sshd service on boot.
### usage
Run the following command to build the openrc container. Check [here](https://github.com/ericwq/nvide#build-and-run-the-sshmosh-image) if you don't understand hwo to generate `~/.ssh/id_rsa.pub` file.
```sh
% docker build --build-arg ROOT_PWD=passowrd \
--build-arg USER_PWD=password \
--build-arg SSH_PUB_KEY="$(cat ~/.ssh/id_rsa.pub)" \
--progress plain -t openrc-ssh:0.1.0 -f openrc.dockerfile .
```
Run the following command to start the container.
```sh
% docker run --env TZ=Asia/Shanghai --tty --privileged --volume /sys/fs/cgroup:/sys/fs/cgroup:ro \
-h openrc-ssh --name openrc-ssh -d -p 5022:22 openrc-ssh:0.1.0
```
Run the following command to login in to the container.
```sh
% rm ~/.ssh/known_hosts ~/.ssh/known_hosts.old
% ssh -p 5022 root@localhost
```
Login in to the container and run `setup-utmp` init script for utmps. unfortunately I can't find the right way to run `setup-utmp` at building image time.
```sh
% setup-utmp
```
~~Finally, you need to reboot the container and login in again.~~ Now you can run `who` and `last` command.
```sh
openrc-ssh:/etc/init.d# who
root pts/1 00:00 May 13 18:46:42 172.17.0.1
openrc-ssh:/etc/init.d# last
USER TTY HOST LOGIN TIME
ide pts/2 172.17.0.1 May 13 18:47
root pts/1 172.17.0.1 May 13 18:46
reboot system boot 5.15.49-linuxkit May 13 18:47
```
You can check the init system and required services with the following command.
```sh
openrc-ssh:/etc/init.d# pstree -p
init(1)-+-s6-ipcserverd(154)
|-s6-ipcserverd(217)
|-s6-ipcserverd(245)
`-sshd(190)---sshd(286)---ash(288)---pstree(338)
```
## s6-rc container
### usage
check the `build.md` for how to build image and run container.
### the relationship between s6 and s6-overlay
`s6` is the base, it is best used in virtual machine environment instead of docker container. `s6-overlay` is the `s6` wrapper for docker container environment.
### installation via package or tar ball
Alpine and other linux distribution support `s6` related package. For example, on alpine there are full set of `s6` package available.
s6 related package in alpine
```sh
# apk search s6
s6-portable-utils-2.3.0.2-r1
s6-networking-2.5.1.3-r1
s6-2.11.3.2-r1
s6-rc-0.5.4.1-r1
s6-dns-doc-2.3.5.5-r1
s6-dns-2.3.5.5-r1
s6-dns-dev-2.3.5.5-r1
s6-ipcserver-2.11.3.2-r1
s6-portable-utils-doc-2.3.0.2-r1
s6-linux-utils-2.6.1.2-r1
s6-networking-man-pages-2.5.1.3.3-r0
s6-overlay-helpers-0.1.0.1-r0
s6-linux-init-static-1.1.1.1-r0
s6-openrc-2.11.3.2-r1
s6-linux-init-1.1.1.1-r0
s6-rc-doc-0.5.4.1-r1
s6-networking-dev-2.5.1.3-r1
s6-dns-static-2.3.5.5-r1
s6-overlay-doc-3.1.5.0-r0
s6-dev-2.11.3.2-r1
s6-overlay-3.1.5.0-r0
s6-doc-2.11.3.2-r1
s6-static-2.11.3.2-r1
s6-linux-init-doc-1.1.1.1-r0
s6-linux-utils-doc-2.6.1.2-r1
s6-networking-static-2.5.1.3-r1
s6-man-pages-2.11.3.2.4-r0
s6-rc-static-0.5.4.1-r1
s6-overlay-syslogd-3.1.5.0-r0
s6-rc-man-pages-0.5.4.1.2-r0
s6-linux-init-man-pages-1.1.1.0.1-r0
s6-portable-utils-man-pages-2.3.0.2.2-r0
s6-rc-dev-0.5.4.1-r1
s6-linux-init-dev-1.1.1.1-r0
s6-networking-doc-2.5.1.3-r1
```
While the origianl `s6-overlay` site suggest `tar.xz` installation. Such as:
```dockerfile
# extract s6-overlay
#
ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz /tmp/s6/
RUN tar xf /tmp/s6/s6-overlay-noarch.tar.xz -C /
ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-x86_64.tar.xz /tmp/s6/
RUN tar xf /tmp/s6/s6-overlay-x86_64.tar.xz -C /
RUN rm -rf /tmp/s6
```
For alpine, `s6-overlay` package is more convinient for us. The following docker command is much more simple.
```dockerfile
RUN apk add --no-cache --update openssh-server s6-overlay
```
### sshd problem
`s6-overlay` support running `sshd` as supervised process in the follwoing way. In this way, the container will execute `ENTRYPOINT` first, then the system will execute `CMD` part.
```dockerfile
CMD ["/usr/sbin/sshd", "-D"]
# start s6-overlay
#
ENTRYPOINT ["/init"]
```
### PATH problem
With the tar ball installation, the `s6-overlay` is installed under `/command` and `/package` directory. utmps give an example `s6-rc` configuration. You need to change shebangs line to respect the above installation.
The origianl content of `utmpd/run` script:
```sh
#!/bin/execlineb -P
fdmove -c 2 1
s6-setuidgid utmp
cd /run/utmps
fdmove 1 3
s6-ipcserver -1 -- /run/utmps/utmpd-socket
utmps-utmpd
```
The modified content of `utmpd/run` script, keep your eye on the first shebangs line. Without the modification, your run script is not executeable.
```sh
#!/command/execlineb -P
fdmove -c 2 1
s6-setuidgid utmp
cd /run/utmps
fdmove 1 3
s6-ipcserver -1 -- /run/utmps/utmpd-socket
utmps-utmpd
```
### reference
- [s6-example](https://github.com/beldpro-ci/s6-entrypoint)
- [Docker and S6 – My New Favorite Process Supervisor](https://tutumcloud.wordpress.com/2014/12/02/docker-and-s6-my-new-favorite-process-supervisor/)
- [Building a skarnet.org s6 Init System](https://danmc.net/posts/s6-1/)
- [Quickstart and FAQ for s6-linux-init](http://skarnet.org/software/s6-linux-init/quickstart.html)
- [An overview of s6](https://skarnet.org/software/s6/overview.html)
- [s6 overlay](https://github.com/just-containers/s6-overlay)
- [S6 Made Easy, with the S6 Overlay](https://tutumcloud.wordpress.com/2015/05/20/s6-made-easy-with-the-s6-overlay/)
- [How to understand S6 Overlay v3](https://darkghosthunter.medium.com/how-to-understand-s6-overlay-v3-95c81c04f075)