docker-base
                                
                                
                                
                                    docker-base copied to clipboard
                            
                            
                            
                        Just enough to get process supervision and startup mechanisms
docker-base
https://hub.docker.com/r/behance/docker-base/tags/
Provides base OS, security patches, and tools for quick and easy spinup.
Variants
| OS | Tag | Notes | 
|---|---|---|
| Ubuntu 20.04 | -VERSION#-ubuntu-20.04 | 
Current | 
| Ubuntu 22.04 | -VERSION#-ubuntu-22.04 | 
Current | 
Tools
- S6 process supervisor is used for 
onlyfor zombie reaping (as PID 1), boot coordination, and termination signal translation - Goss is used for build-time testing
 - Dgoss is used for run-time testing.
 
Expectations
To add a service to be monitored, simply create a service run script
For programmatic switches, create the service in /etc/services-available, and symlink to /etc/services.d to enable
Security
A convenience script is provided for security-only package updates.
On Ubuntu and CentOS-based variants, run:
/bin/bash -e /security_updates.sh
This file is actually a symlink to the variant-specific script contained in the /scripts folder
Packaging
A convenience script is provided for post-package installation cleanup
On all variants, run:
/bin/bash -e /clean.sh
This file, like security_updates (above) is actually a symlink to the variant-specific script contained in the /scripts folder
Environment Variables
| Variable | Example | Description | 
|---|---|---|
| S6_KILL_FINISH_MAXTIME | S6_KILL_FINISH_MAXTIME=55000 | The maximum time (in ms) a script in /etc/cont-finish.d could take before sending a KILL signal to it. Take into account that this parameter will be used per each script execution, it's not a max time for the whole set of scripts. This value has a max of 65535 on Alpine variants. | 
| S6_KILL_GRACETIME | S6_KILL_GRACETIME=500 | Wait time (in ms) for S6 finish scripts before sending kill signal. This value has a max of 65535 on Alpine variants. | 
with-contenvtool, which is used to expose environment variables across scripts, has a limitation that it cannot read beyond 4k characters for environment variable values. To work around this issue, use the script/scripts/with-bigcontenvinstead ofwith-contenv. You'll need to remove thewith-contenvfrom the shebang line, and addsource /scripts/with-bigcontenvin the next line after the shebang line.
Startup/Runtime Modification
To inject changes just before runtime, shell scripts may be placed into the
/etc/cont-init.d folder.
As part of the process manager, these scripts are run in advance of the supervised processes. @see https://github.com/just-containers/s6-overlay#executing-initialization-andor-finalization-tasks
Processor Architectures
All variants are tested on x64 and arm64.
The convenience script archstring is provided to switch between strings based on the current machine.
Usage:
archstring --x64 intel --arm64 arm
Which will return "intel" when on x64 and arm when on arm64. This is handy when package names or download paths need to be modified per architecture.
Testing
- Container tests itself as part of build process using goss validator. To add additional build-time tests, overwrite (or extend) the 
./container/root/goss.base.yamlfile. - To initiate run-time validation, please execute 
test.sh. It uses dgoss validator. To add additional run-time tests, extend./test.shand./goss.yamlfile. 
Advanced Modification
More advanced changes can take effect using the run.d system. Similar to the /etc/cont-init.d/ script system, any shell scripts (ending in .sh) in the /run.d/ folder will be executed ahead of the S6 initialization.
- If a 
run.dscript terminates with a non-zero exit code, container will stop, terminating with the script's exit code, unless... - If script terminates with exit code of $SIGNAL_BUILD_STOP (99), this will signal the container to stop cleanly. This can be used for a multi-stage build process
 
Shutdown Behavior
Sequence of events for a crashed supervised service:
- S6 finish scripts are executed. The supervised service is presumed down at this point, its return code is a variable (
${1}). - If no 
finishscript is specified, service gets restarted, with no further action - If 
finishscript specifies to bring the container down, admin-initiated container termination behavior applies (below). 
Sequence of events for a docker stop or admin-initiated container termination:
- SIGTERM is broadcast to all supervised services, described as a run script. 
S6_KILL_GRACETIMEcorresponds with how long to wait for a SIGTERM to complete and return. This first signal can be trapped/intercepted to convert into a graceful stop (see below). Failure for the supervised service to respond to the signal withinS6_KILL_GRACETIMEwill result in an untrappable SIGKILL. - Scripts in 
/etc/cont-finish.dare executed, each withS6_KILL_FINISH_MAXTIME. - S6 finish scripts are executed. The supervised service is presumed down at this point, its return code is a variable (
${1}). - Beyond this point, signals cannot be trapped or interrupted. All services should already be down by this point, or they will be forcibly brought down by the following signals.
 - SIGHUP is broadcast to all services, in all trees.
 - SIGTERM is broadcast to all services, in all trees.
 - SIGKILL terminates anything remaining
 
Implementing graceful shutdown from admin-initiated container termination
- Set 
S6_KILL_FINISH_MAXTIMElong-enough to shutdown/drain service properly. See table above for upper limits. - Trap SIGTERM in supervised service 
runscript. Take no action directly at this time. - Create a graceful shutdown script, place in 
/etc/cont-finish.ddirectory. Supervised service must terminate itself as a result, withinS6_KILL_FINISH_MAXTIMEtime. Some examples include: sending alternate shutdown control signals (like SIGWINCH or SIGQUIT), 
Long-running processes (workers + crons)
This container image can be used with multiple entrypoints (not to be confused with Docker entrypoints).
For example, a codebase that runs a web service, but also requires crons and background workers. These processes should not run inside the same container (like a VM would), but can be executed separately from the same image artifact by adding arguments to the run command.
docker run {image_id} /worker.sh 3 /bin/binary -parameters -that -binary -receives
Runs 3 copies of /bin/binary that receives the parameters -parameters -that -binary -receives
Container Organization
Besides the instructions contained in the Dockerfile, the majority of this
container's use is in configuration and process. The ./container/root repo directory is overlayed into a container during build. Adding additional files to the folders in there will be present in the final image. All paths from the following explanation are assumed from the repo's ./root/ base:
| Directory | Use | 
|---|---|
/etc/cont-init.d/ | 
startup scripts that run ahead of services booting: https://github.com/just-containers/s6-overlay#executing-initialization-andor-finalization-tasks | 
/etc/fix-attrs.d/ | 
scripts that may fix permissions at runtime: https://github.com/just-containers/s6-overlay#fixing-ownership--permissions | 
/etc/services.d/ | 
services that will be supervised by S6: https://github.com/just-containers/s6-overlay#writing-a-service-script | 
/etc/services-available/ | 
same as above, but must be symlinked into /etc/services.d/ to take effect | 
/run.d/ | 
shell scripts (ending in .sh) that make runtime modifications ahead of S6 initialization | 
/scripts | 
convenience scripts that can be leveraged in derived images | 
Release Management
Github actions provide the machinery for producing tags distributed through Docker Hub. Once a tested and approved PR is merged, simply cutting a new semantically-versioned tag will generate the following matrix of tagged builds:
[major].[minor].[patch](?-variant)[major].[minor](?-variant)[major](?-variant)Platform support is available for architectures:linux/arm64linux/amd64
To add new variant based on a new Dockerfile, add an entry to the matrix.props with its file and variant suffix.