jekyll
4.4.1-alpineJekyll runtime with native build deps pre-installed. Multi-version retention tracks Jekyll upstream daily.
Trust posture
VERIFIABLE TRUST ARTIFACTS
Provenance
- Build commit
43b72a4- Build digest
-
sha256:29fbba00abecc5f96d5edca1789dc3b0f48b865a6599a3d6df34121f0eb00b9f - Index digest
-
sha256:948cac19eccb8398e54c4eac5144fe793e1124564320f9dfe3680c17a324720c - Manifest digest (amd64)
-
sha256:a351ca019eaad4b9005300bad36759b0d84cb1320fecf6810b475707b07a35e6 - Manifest digest (arm64)
-
sha256:b4f01eeb087a05bae7c86785a065855c1e75c71f7f1e67ee1a6ba05003d6fc14 - SBOM attestation
-
55834413β¦ - Trivy evidence
- Code Scanning fetched 2026-10-17 11:24 UTC
- Base image
ghcr.io/oorabona/library/ruby:3.3-alpine3.21- Verify
gh attestation verify oci://ghcr.io/oorabona/jekyll:4.4.1-alpine --owner oorabonaguide β
Security evidence
Trivy Β· Code Scanning for image 4.4.1-alpine fetched 2026-10-17
Top advisories (upstream, advisory)
- CVE-2026-42257 (CRITICAL) β net-imap-0.4.21.gemspec β net-imap: Net::IMAP: Arbitrary IMAP command injection via CRLF sequences in unvalidated input
- CVE-2026-31789 (CRITICAL) β jekyll β openssl: OpenSSL: Heap buffer overflow on 32-bit systems from large X.509 certificate processing
- CVE-2026-31789 (CRITICAL) β jekyll β openssl: OpenSSL: Heap buffer overflow on 32-bit systems from large X.509 certificate processing
- CVE-2026-27820 (CRITICAL) β zlib-3.1.1.gemspec β zlib: zlib: Memory corruption via buffer overflow in Zlib::GzipReader
- CVE-2026-84782 (HIGH) β jekyll β openssl: compat-openssl: openssl: Information disclosure via DTLS handshake retransmission
β See verification steps.
Explore
Build lineage29fbba00abec
Package summary 393 packages
Recent changes +0 β0 ~2
Build history 10 builds
Dependency health all up to date
Dependency Health
all up to dateUp-to-date dependencies
Documentation
README
Jekyll
Lightweight Alpine-based container for building and serving Jekyll static sites with live reload support.
Verify this image
Every build ships a Sigstore-signed SBOM and a full Trivy scan β verify them yourself, no login required:
gh attestation verify oci://ghcr.io/oorabona/jekyll:latest --owner oorabona
Full walkthrough (SBOM payload, Trivy findings, multi-arch manifest inspection, upstream dependency tracking) β https://oorabona.github.io/docker-containers/verify-images/
Quick Start
Docker Run
# Serve a site with live reload
docker run --rm -it \
-v "$(pwd):/site" \
-p 4000:4000 \
-p 35729:35729 \
ghcr.io/oorabona/jekyll:latest
# Build only (no server)
docker run --rm \
-v "$(pwd):/site" \
ghcr.io/oorabona/jekyll:latest \
build
# Build to custom destination
docker run --rm \
-v "$(pwd):/site" \
ghcr.io/oorabona/jekyll:latest \
build --destination /site/public
Docker Compose
services:
jekyll:
image: ghcr.io/oorabona/jekyll:latest
ports:
- "4000:4000"
- "35729:35729"
volumes:
- ./site:/site
command: ["serve", "--host", "0.0.0.0", "--livereload", "--force_polling"]
Then run:
docker compose up
Site available at: http://localhost:4000
The Compose profile runs with uid/gid 1000 by default, matching the imageβs
jekyll user. To keep bind-mounted files owned by your host account, pass your
numeric identity explicitly:
LOCAL_UID="$(id -u)" LOCAL_GID="$(id -g)" docker compose up
With rootless Podman, container uids are remapped, so uid 1000 in the
container is not your host account and cannot write the bind mount
(Permission denied @ dir_s_mkdir - /site/.jekyll-cache). Map your host
identity into the container instead:
podman run --rm --userns=keep-id -v "$(pwd):/site" ghcr.io/oorabona/jekyll:latest build
Features
- Ruby 3.3 on Alpine Linux (minimal footprint)
- Jekyll 4.4.1 with live reload
- Bundler for dependency management
- Node.js for JavaScript processing
- Pre-installed plugins:
jekyll-feed- RSS/Atom feed generationjekyll-seo-tag- SEO optimization meta tagsjekyll-sitemap- XML sitemap generation
- WebRick server included
- Git support for themes and plugins
Build Arguments
All dependency versions are pinned for reproducible builds:
| Argument | Default | Description |
|---|---|---|
RUBY_VERSION |
3.3 |
Ruby major version |
ALPINE_VERSION |
3.21 |
Alpine Linux version |
JEKYLL_VERSION |
4.4.1 |
Jekyll core version |
BUNDLER_VERSION |
4.0.6 |
Bundler dependency manager |
WEBRICK_VERSION |
1.9.2 |
WebRick HTTP server |
JEKYLL_FEED_VERSION |
0.17.0 |
RSS/Atom feed plugin |
JEKYLL_SEO_TAG_VERSION |
2.8.0 |
SEO meta tags plugin |
JEKYLL_SITEMAP_VERSION |
1.4.0 |
Sitemap generation plugin |
Ports
| Port | Purpose |
|---|---|
4000 |
Jekyll development server |
35729 |
LiveReload websocket |
Volumes
Mount your Jekyll site directory to /site:
-v "$(pwd):/site"
Directory Structure
your-site/
βββ _config.yml # Jekyll configuration
βββ _posts/ # Blog posts
βββ _layouts/ # HTML templates
βββ _includes/ # Reusable components
βββ assets/ # CSS, JS, images
βββ Gemfile # Additional gem dependencies
βββ _site/ # Generated output (auto-created)
Using a Gemfile
The container does not run bundle install. For gems the image does not ship,
see Adding Custom Dependencies.
Security
Volume Permissions
The image runs as the non-root jekyll user (uid/gid 1000), and /site is
writable by that user. Its HOME and Ruby/Bundler cache locations use /tmp,
which is writable even when Docker runs the image with an arbitrary numeric uid
that has no passwd entry. For a bind mount, use your host uid/gid so generated
files remain owned by your account:
# Run as the host user
docker run --user "$(id -u):$(id -g)" \
-v "$(pwd):/site" \
ghcr.io/oorabona/jekyll:latest build
Production Deployment
For serving Jekyll sites in production:
- Build static files locally:
docker run --rm -v "$(pwd):/site" ghcr.io/oorabona/jekyll:latest build - Serve with a dedicated web server:
Use nginx, Apache, or a CDN to serve the
_site/directory. The Jekyll container is intended for development only.
Network Security
- Bind to
127.0.0.1for local-only access:-p 127.0.0.1:4000:4000 - Never expose port
4000to the public internet - Use environment-specific
_config.ymlfiles to prevent sensitive data leaks
Dependencies
All Ruby gem versions are pinned and monitored for updates:
| Gem | Version | Purpose |
|---|---|---|
| bundler | 4.0.6 | Dependency management |
| webrick | 1.9.2 | HTTP server |
| jekyll-feed | 0.17.0 | RSS/Atom feed generation |
| jekyll-seo-tag | 2.8.0 | SEO meta tags |
| jekyll-sitemap | 1.4.0 | XML sitemap generation |
Adding Custom Dependencies
The image installs its gems at build time and runs as a non-root user, so it
does not install a siteβs Gemfile. To add gems, extend the image:
FROM ghcr.io/oorabona/jekyll:latest
USER root
RUN gem install jekyll-theme-cayman jekyll-redirect-from jemoji
USER jekyll
Architecture
jekyll/
βββ Dockerfile # Alpine-based build
βββ config.yaml # Dependency versions
βββ version.sh # Upstream version checker
βββ docker-compose.yml # Local development setup
βββ README.md # This file
Build Process
The Dockerfile uses a single-stage build:
- Start from
ruby:{RUBY_VERSION}-alpine{ALPINE_VERSION} - Install build dependencies (build-base, git, nodejs)
- Install Jekyll and plugins at pinned versions
- Remove build dependencies to reduce image size
- Set working directory to
/site - Configure default command:
serve --host 0.0.0.0 --livereload
Building Locally
# Build with default versions
./make build jekyll
# Build with specific Jekyll version
./make build jekyll 4.4.1
# Build with custom arguments
docker build \
--build-arg JEKYLL_VERSION=4.4.0 \
--build-arg RUBY_VERSION=3.2 \
-t jekyll:custom .
Version Management
# Check current version
cd jekyll && ./version.sh
# Check latest upstream version
cd jekyll && ./version.sh latest
# JSON output for automation
cd jekyll && ./version.sh --json
Links
- Jekyll Documentation: https://jekyllrb.com/docs/
- Docker Hub: https://hub.docker.com/r/oorabona/jekyll
- GitHub Container Registry: https://ghcr.io/oorabona/jekyll
- Source Repository: https://github.com/oorabona/docker-containers
- Issue Tracker: https://github.com/oorabona/docker-containers/issues