Configuration and Customization

This page describes how to configure Jekyll Docker using environment variables, local package manifests, and host-mounted caching directories.


Environment Variables

Configure Jekyll Docker's internal wrappers by passing these environment variables when starting your container:

User and File Access Mappings

  • JEKYLL_UID (Default: 1000)
  • Why it matters: By default, containers execute as the root user. If your host developer account has a different User ID (e.g., 1001), files generated by Jekyll inside the container (like the _site output folder) will be owned by root, preventing you from editing or deleting them on your host.
  • Resolution: Set -e JEKYLL_UID=$(id -u) to align the container with your host user account.
  • JEKYLL_GID (Default: 1000)
  • Resolution: Set -e JEKYLL_GID=$(id -g) to map group permissions securely.
  • JEKYLL_ROOTLESS (Default: "")
  • Resolution: When running rootless container runtimes like Podman, set -e JEKYLL_ROOTLESS=1 to run the execution loop directly as root inside the namespace, which securely maps back to your host user account.

Execution Toggles

  • FORCE_POLLING (Default: false)
  • Why it matters: Jekyll uses file system events to watch for changes. On virtualized systems (such as WSL1/WSL2, VirtualBox Shared Folders, or NFS mounts), these events are often blocked.
  • Resolution: Set -e FORCE_POLLING=true to force Jekyll to poll the file system for changes manually.
  • VERBOSE (Default: false)
  • Resolution: Set -e VERBOSE=true to print detailed compilation diagnostics and track gem resolution issues.
  • DRAFTS (Default: false)
  • Resolution: Set -e DRAFTS=true to include files located in your _drafts directory during compilation.

Installing Custom Alpine Packages (.apk Support)

If your build process depends on system utilities that are not pre-installed in the base image (such as custom rendering engines, font libraries, or native image preprocessors), you can install them dynamically at boot.

Step-by-Step Package Installation

  1. In your project's root folder (next to your _config.yml), create a text file named .apk.
  2. Add the exact Alpine package names, one per line:
imagemagick
graphviz
inkscape
  1. Start your container with an active internet connection. The internal bundle script will intercept this file, parse its contents, and run apk add --no-cache to install the packages before running Jekyll.

!!! warning "Network Requirement" Dynamic package installation requires an active internet connection at startup. If the container is offline, package installation is skipped, which may cause build failures if your plugins depend on those utilities.


Gem Cache Optimization

When a project includes a custom Gemfile, Jekyll Docker runs bundle install at startup to ensure all dependencies are resolved. To prevent the container from re-downloading these packages on every run, configure a persistent host directory to cache your compiled gems.

Configure Your Volumes

Map a local path on your host machine to the container's /usr/local/bundle directory:

docker run --rm \
  --volume="$PWD:/srv/jekyll:Z" \
  --volume="$PWD/vendor/bundle:/usr/local/bundle:Z" \
  -it jekyll/jekyll:latest \
  jekyll build

Prevent Infinite Build Loops

If you mount your gem cache folder inside your project directory (such as vendor/bundle), you must explicitly instruct Jekyll to ignore it. Otherwise, Jekyll will treat newly compiled gems as source modifications, triggering an infinite rebuild loop.

Update your _config.yml configuration file to exclude your cache directory:

exclude:
  - vendor/
  - Gemfile.lock
  - .bundle/
  - .apk