A two-stage Dockerfile at the root of your Jekyll repository: a Ruby stage runs jekyll build with every gem in your Gemfile, an nginx stage serves the result. SnapDeploy builds it on every push; nothing from the Ruby stage ships.
Free tier: 4 containers, 512 MB each, 100 hours a month, 10 deploys a day. No credit card. Always-On from $12 a month when the site must never sleep.
Last verified 6 October 2026 with Jekyll 4.4 and Ruby 3.3: the sample repository below was built for linux/arm64 with the exact files on this page. Host limits in the table are from each host's own documentation, read 28 September 2026.
Jekyll is the engine behind GitHub Pages, so for a public blog with standard plugins that is the obvious free home. A container earns its place when the site needs more than that. The limits below are from each host's own pages as of 28 September 2026.
| Host | Jekyll build | Bandwidth / builds | Custom domain | Sleeps | Catch |
|---|---|---|---|---|---|
| GitHub Pages | Native, but only the plugins on GitHub's allow-list; anything else needs your own Actions workflow | 100 GB/month soft limit; 10 builds/hour soft limit | Yes, with HTTPS | No | Public repositories only on GitHub Free; 1 GB site |
| Cloudflare Pages | Build command, any gem | Unlimited; 500 builds/month | Yes, 100 per project | No | 20,000 files, 25 MiB per file |
| Netlify Free | Build command, any gem | 300 credits/month; a production deploy costs 15 credits, bandwidth 20 per GB | Yes, with SSL | No | Deploys and bandwidth draw from the same 300 credits |
| Render static sites | Build command, any gem | 5 GB/month on the Hobby workspace, then $0.15/GB | Yes, 2 per workspace | No (static) | Small bandwidth cap |
| SnapDeploy | Your Dockerfile, any gem, any Ruby version | Not metered; 100 container-hours/month of running time; 10 deploys/day | Always-On only ($12/mo) | Yes, after 15 min idle; ~60 s wake | Built for sites that need nginx rules, a private repo, or an API next to them |
Isolation: the four static hosts serve your files from their CDN; there is no container of yours to isolate. On SnapDeploy your site is an nginx container that runs as its own AWS Fargate task with a reserved 0.25 vCPU and 512 MB, free tier included; AWS runs each task on a single-use, single-tenant compute instance.
Sources: docs.github.com (GitHub Pages limits, "About GitHub Pages and Jekyll", supported plugins); developers.cloudflare.com (Pages limits); netlify.com/pricing; render.com/docs/static-sites and render.com/pricing; aws.amazon.com/fargate/faqs (task isolation); SnapDeploy figures from /docs/free-tier. The four Pages hosts are the same rows as on our static hosting comparison.
Three files at the root of the repository, then a GitHub deploy. The sample repository has them all with a one-layout, one-post site around them.
The build stage installs your Gemfile and runs jekyll build with JEKYLL_ENV=production; the serve stage is nginx with only _site inside. Pin the Ruby image to what you use locally.
FROM ruby:3.3-slim AS build
RUN apt-get update \
&& apt-get install -y --no-install-recommends build-essential git \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /site
COPY Gemfile Gemfile.lock* ./
RUN bundle install --jobs 4
COPY . .
RUN JEKYLL_ENV=production bundle exec jekyll build --destination /site/_site
FROM nginx:1.27-alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /site/_site /usr/share/nginx/html
EXPOSE 80
Add a .dockerignore with _site, .jekyll-cache, vendor and .git, and list Dockerfile, nginx.conf and README.md under exclude: in _config.yml so Jekyll does not copy them into the site.
A bare nginx image returns 403 for directory URLs and its own 404 page. This config serves folder/index.html for permalink: pretty URLs and your Jekyll 404.html for misses.
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
error_page 404 /404.html;
location / {
try_files $uri $uri/ =404;
}
}
This is also where redirects, security headers and long cache lifetimes for hashed assets go, which is the main reason to prefer a container over a Pages host for some sites.
Deploy Your Application → GitHub → the repository and branch. The Dockerfile is detected and port 80 is read from its EXPOSE line. No environment variables are needed. The build installs the gems and runs Jekyll; the sample site builds in about a minute and the site is at https://<name>.containers.snapdeploy.app. Every push to the branch rebuilds it. If your site generates absolute links (feed, sitemap), set url: in _config.yml to that address or to your custom domain.
GitHub Pages is where Jekyll came from, and for a public blog it is hard to beat. These are the cases where people move the build into a Dockerfile.
A container follows container rules, which are not the rules of a CDN host. The complete list is on the free-tier page.
No. The Dockerfile on this page runs bundle install and jekyll build inside a ruby:3.3-slim stage on SnapDeploy's builders, then copies the generated _site into an nginx image. Your machine only needs git.
Yes. The build runs whatever your Gemfile lists, so plugins that GitHub Pages does not allow in its native build work here without a GitHub Actions workflow. The one limit is memory during the build, which is not an issue for a site of a few hundred pages.
Because of the two stages: the Ruby stage with Jekyll and the gems is thrown away, and only the generated HTML, CSS and assets are copied into nginx:alpine. The sample site on this page builds to a 76 MB image.
Yes. A free container sleeps after 15 minutes without visitors and wakes in about a minute when someone opens it in a browser, with a waiting page in between. For a site that must answer instantly at all times, Always-On is $12 a month; a pure static site with no server next to it is often better served by a Pages host, which this page says plainly in its comparison table.
When it needs plugins GitHub Pages will not build, a private repository on a free GitHub account, real nginx rules for headers and redirects, password protection, or an API or database next to it. For a public blog with no such needs, GitHub Pages or a Pages host is the simpler, always-awake choice.
The nginx.conf on this page serves folder/index.html for permalink: pretty URLs with try_files and returns Jekyll's own 404.html for missing paths. Without it, a bare nginx image would 403 on directory URLs and show its default 404.
Set url: in _config.yml to the container URL (https://<name>.containers.snapdeploy.app) or to your custom domain, and rebuild. Jekyll uses it for absolute links in the feed and sitemap plugins; relative links on pages work without it.
Any plugin, any Ruby, your own nginx rules. Free tier, no credit card; Always-On from $12 a month when it must never sleep.
Deploy Free TodayThe first managed container PaaS to offer a one-time 24-hour Always-On pass under $5. Unlimited deploys + Always-On for one Small (512 MB) container — including WebSockets & real-time apps. No subscription, no auto-renewal. Stack two for 48 hours.
Need a managed database too? DB Sprint Pack — $1 / 12h for Postgres, MySQL, MariaDB, Mongo, Redis, or RabbitMQ.