Container Internals and Wrapper Scripts
Jekyll Docker uses a series of integrated shell and Ruby wrapper scripts located in /usr/jekyll/bin/ to manage file permissions, system packages, and command line arguments automatically. This section describes how these wrappers work under the hood.
1. Entrypoint Wrapper (/usr/jekyll/bin/entrypoint)
This is the initial wrapper script executed by the container runtime. It ensures the environment permissions match your host configuration before starting any Ruby processes:
# Check for rootless configuration
if [ "$JEKYLL_ROOTLESS" ]; then
JEKYLL_UID=0
JEKYLL_GID=0
fi
: ${JEKYLL_UID:=$(id -u jekyll)}
: ${JEKYLL_GID:=$(id -g jekyll)}
export JEKYLL_UID
export JEKYLL_GID
Key Operations
- Identity Matching: If the provided
JEKYLL_UIDdiffers from the container's defaultjekylluser account (UID 1000), the script runsusermodandgroupmodto update the container's user and group definitions dynamically. - Permissions Fixes: Runs a targeted
chownover/srv/jekylland/var/jekylldirectories to align workspace access rights and prevent permissions lockouts on your host system.
2. Argument Translation (/usr/jekyll/bin/default-args)
This custom Ruby utility parses and cleans incoming command line arguments, converting environment variables into standard Jekyll CLI flags:
def build?; %w(b build).include?(ARGV[0]); end
def serve?; %w(s serve server).include?(ARGV[0]); end
Key Operations
- Host Binding: If you run
jekyll serve, the script automatically injects-H 0.0.0.0to bind the server to all network interfaces, allowing you to access the site from your host browser. - Flag Injection: Translates environment configurations into standard flags:
- Appends
--force_pollingifFORCE_POLLINGis active. - Appends
--draftsifDRAFTSis active. - Appends
--verboseifVERBOSEis active. - Shell Integration: Uses
Shellwords.shelljointo return the cleaned argument array securely back to the execution wrapper.
3. Bundler Override (/usr/jekyll/bin/bundle)
This script replaces the standard bundle executable. It runs pre-flight system package validations and manages local caching directories:
if [ "$1" = "install" ] || [ "$1" = "update" ]; then
if [ "$1" = "update" ] || ! su-exec jekyll $exe check 1>/dev/null 2>&1; then
if [ ! -f "/updated" ] && connected && [ -f ".apk" ]; then
apk add --no-cache --no-progress $(cat .apk)
fi
# ... (runs Bundler optimizations)
fi
fi
Key Operations
- Automatic Package Installation: If a
.apkfile is present in your project root, the wrapper reads it and runsapk addto install the packages before starting your Ruby dependencies build. - Performance Optimization: Configures standard Bundler optimizations to speed up gem installations:
- Sets parallel installation jobs (
jobs 2). - Suppresses unnecessary messages (
ignore_messages true). - Instructs compiled libraries to use system packages (
build.nokogiri --use-system-libraries).
4. Connectivity Engine (/usr/jekyll/bin/connected)
To prevent build delays when working offline, this script checks if the container has internet access before attempting package or gem updates:
url=https://detectportal.firefox.com
if wget -q --spider "$url" -O /dev/null 2>/dev/null; then
su-exec jekyll touch "$connected"
exit 0
else
su-exec jekyll touch $disconnected
exit 1
fi
Key Operations
- State Caching: Saves connectivity status files (
connectedordisconnected) in/var/jekyll/. Subsquent runs check these files first to avoid network timeout delays during offline development.