DEV Community

Cover image for Deploy Jekyll Site to Heroku
Taufek Johar
Taufek Johar

Posted on • Originally published at blog.taufek.dev on

Deploy Jekyll Site to Heroku

Generally there are 2 ways to deploy Jekyll static site to Heroku.

  1. Deploy as rails app using web server gem such as puma, passenger, thin, ‘etc’.
  2. Deploy as Docker image running nginx service.

In this post, I chose 2nd approach since I like to use Docker image.

Prepare Dockerfile

We will serve this Jekyll site via nginx service. In order to map Heroku portnumber to our nginx service, we will need to use below default.conf template.

server {
  # Placeholder for Heroku port
  listen $PORT;

  location / {
    root /usr/share/nginx/html;
    index index.html;
  }
}

Dockerfile.

FROM nginx:alpine

# copy nginx `default.conf`
COPY nginx/default.conf /etc/nginx/conf.d/
# copy Jekyll generated files
COPY _site /usr/share/nginx/html/

# replace $PORT placeholder with HEROKU given port in default.conf and run nginx service
CMD sed -i -e 's/$PORT/'"$PORT"'/g' /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'

You can named this file as Dockerfile or have a suffix to indiciate theHeroku process. For instance, if you want to run this application as webprocess in Heroku, you could name it as Dockerfile.web. This works well ifyou have multiple Dockerfiles with different process such as web, worker, orclock. Later on, when you run heroku container:push --recursive, it willbuild all the Dockerfiles with the correct suffix and push them to Heroku dockerregistry.

Configure Github Action

Even without Github Action, all I need is Heroku CLI to deploy this Dockerimage using below commands.

> bundle exec jekyll build

> heroku container:login

> heroku container:push -a <HEROKU_APP_NAME> --resursive

> heroku container:release -a <HEROKU_APP_NAME> web

Basically, in Github Actions, we are running above commands. Below is the fullGithub Action workflow yaml.

name: Push Container to Heroku

on:
  push:
    branches:
      - master

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1

    - name: Retrieve Gem Bundles Cache
      uses: actions/cache@v2
      with:
        path: _bundle
        key: $-gems-$
        restore-keys: |
          $-gems-

    - name: Generate site
      run: |
        mkdir -p _bundle/cache
        chmod a+rwx -R .
        docker-compose run -e JEKYLL_ENV=production jekyll bundle install
        docker-compose run -e JEKYLL_ENV=production jekyll bundle exec jekyll build --trace

    - name: Login to Heroku Container registry
      env:
        HEROKU_API_KEY: $
      run: heroku container:login

    - name: Build and push
      env:
        HEROKU_API_KEY: $
      run: heroku container:push -a $ --recursive

    - name: Release
      env:
        HEROKU_API_KEY: $
      run: heroku container:release -a $ web

With a push to master branch, it will trigger a build which will

  1. Checkout code from master branch.
  2. Generate Jekyll static files.
  3. Build and push the Docker image to heroku registry.
  4. Deploy the Docker image to Heroku with web process.

Conclusion

This approach not only work for static site, but also for other typesof application such as Rails application. Having a Dockerfile will give youfull control on what other linux packages you wish to install within theapplication server instance such as ImageMagick. It will also give youconsistent environment between running your application on your local machineand on Heroku.

Top comments (0)