Deploy a Jekyll Site on SnapDeploy: Build in Ruby, Serve with nginx, Any Plugin

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.

Where a Jekyll Site Can Be Hosted for Free in 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 PagesNative, but only the plugins on GitHub's allow-list; anything else needs your own Actions workflow100 GB/month soft limit; 10 builds/hour soft limitYes, with HTTPSNoPublic repositories only on GitHub Free; 1 GB site
Cloudflare PagesBuild command, any gemUnlimited; 500 builds/monthYes, 100 per projectNo20,000 files, 25 MiB per file
Netlify FreeBuild command, any gem300 credits/month; a production deploy costs 15 credits, bandwidth 20 per GBYes, with SSLNoDeploys and bandwidth draw from the same 300 credits
Render static sitesBuild command, any gem5 GB/month on the Hobby workspace, then $0.15/GBYes, 2 per workspaceNo (static)Small bandwidth cap
SnapDeployYour Dockerfile, any gem, any Ruby versionNot metered; 100 container-hours/month of running time; 10 deploys/dayAlways-On only ($12/mo)Yes, after 15 min idle; ~60 s wakeBuilt 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.

Deploy a Jekyll Site on SnapDeploy

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.

1.Add the Dockerfile

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.

2.Add nginx.conf for pretty permalinks and the 404 page

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.

3.Deploy from GitHub

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.

When a Jekyll Site Belongs on a Container

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.

  • Plugins outside GitHub's allow-list. GitHub Pages builds Jekyll natively but only with a fixed set of plugins; anything else means maintaining a GitHub Actions workflow. In the Dockerfile the Gemfile is the only rule.
  • A private repository on a free GitHub account. GitHub Pages needs a public repository on GitHub Free. The deploy here works from any repository you have connected.
  • Real server rules. Redirects with status codes, security headers, cache lifetimes, basic-auth protection for a draft site: all plain nginx configuration in the file you already have.
  • Something dynamic next to the site. A form handler, a search API or a database add-on runs as a second container on the same account; a Pages host needs a function platform for that.
  • A specific Ruby or Jekyll version. The image pins both; nothing changes under you when a host upgrades its build environment.

What the Free Tier Gives a Static Site, Honestly

A container follows container rules, which are not the rules of a CDN host. The complete list is on the free-tier page.

  • 4 containers, 512 MB and 0.25 vCPU each, no credit card. nginx serving a static site uses a few megabytes of it.
  • 100 container-hours a month, counted only while the container is awake.
  • Sleep after 15 idle minutes, wake in about 60 seconds behind a waiting page. A site that must answer instantly for every visitor at every hour needs Always-On at $12 a month, or belongs on a Pages host.
  • 10 deploys a day (5 per rolling 12 hours), failed builds included.
  • HTTPS on the container URL from the first deploy; a custom domain needs Always-On and the certificate is issued for you.
  • No bandwidth meter, but no global CDN either: the container runs in one AWS region.

Jekyll Hosting Questions, Answered

Do I need Ruby installed to deploy a Jekyll site on SnapDeploy?

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.

Can I use any Jekyll plugin?

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.

Why is the image only about 76 MB?

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.

Does the site sleep on the free tier?

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 does a Jekyll site belong on a container instead of GitHub Pages?

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.

How do pretty permalinks and the 404 page work?

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.

What about the site URL in feeds and sitemaps?

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.

Proud Member Of

As Seen On

Put Your Jekyll Site in a Container

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 Today
FIRST OF ITS KIND

Sprint Pack — $1 for 24 hours

The 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.