Jekyll + AsciiDoc in a devcontainer — zero local setup
Setting up a Jekyll site with AsciiDoc support usually means installing Ruby, Bundler, and a handful of gems on your machine. With the tpo42/adoc container and the Dev Containers specification, you can skip all of that.
The idea
The ghcr.io/tpo42/adoc container already ships Ruby 3.x, Bundler 4.x, and the full
Asciidoctor toolchain (asciidoctor, asciidoctor-pdf, asciidoctor-diagram, …).
Jekyll and its plugins are just a bundle install away — no need to pollute
your host system.
Setup
1. Gemfile
A standard Jekyll Gemfile — the container provides Ruby and Bundler, so nothing else is needed on the host:
source "https://rubygems.org"
gem "jekyll", "~> 4.4"
gem "jekyll-remote-theme"
gem "jekyll-asciidoc"
gem "asciidoctor"
gem "jekyll-sitemap"
gem "jekyll-feed"
gem "jekyll-include-cache"
gem "webrick"
2. .devcontainer/devcontainer.json
{
"name": "my-site",
"image": "ghcr.io/tpo42/adoc:latest",
"workspaceFolder": "/workspace",
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind",
"postCreateCommand": "bundle config set --local path vendor/bundle && bundle install",
"appPort": [4000, 35729],
"forwardPorts": [4000, 35729],
"portsAttributes": {
"4000": { "label": "Jekyll", "onAutoForward": "notify" },
"35729": { "label": "LiveReload", "onAutoForward": "silent" }
}
}
Key points:
image-
Uses
ghcr.io/tpo42/adoc:latestdirectly (the "simple case" from ADR-005). No custom Dockerfile needed. postCreateCommand-
Installs gems into
vendor/bundle(writable by the container user, ignored by.gitignore). appPort-
Maps ports at the Docker level, so
jekyll serveis reachable from the host even without VS Code. forwardPorts-
Does the same for VS Code’s built-in port forwarding.
3. Start the container
With the devcontainer CLI:
devcontainer up --workspace-folder .
Then serve the site:
devcontainer exec --workspace-folder . \
bundle exec jekyll serve --host 0.0.0.0 --livereload
Why not a dedicated Jekyll image?
Images like bretfisher/jekyll-serve work, but they ship their own Ruby and
gem set. If your content is AsciiDoc, you end up needing the Asciidoctor
toolchain and Jekyll — two separate containers, or one bloated custom image.
With ghcr.io/tpo42/adoc as the base, you get Asciidoctor for document processing
(flatten, validate, extract diagrams via adcw) and Jekyll for serving — from a single image, driven by your project’s Gemfile.
AsciiDoc validation — still works from the host
The adcw wrapper does not require a devcontainer. You can validate your
.adoc files any time:
adcw validate -i _pages/about.adoc
This runs a quick docker run --rm — no long-lived container needed.
Lessons learned
appPortvsforwardPorts-
The devcontainer CLI does not forward ports on its own.
forwardPortsis a VS Code feature. For CLI-only workflows,appPortis required. - Gem permissions
-
The
ghcr.io/tpo42/adoccontainer runs as an unprivileged user.bundle installwithout--pathtries to write to system gem directories and fails.bundle config set --local path vendor/bundlesolves this cleanly. - Container reuse
-
devcontainer upreuses existing containers. After changingdevcontainer.json, remove the old container first (docker rm -f <id>) before runningdevcontainer upagain.