Deploy Jekyll Site to Heroku
Published: 2020-06-15 16:54:51

---
title: Deploy Jekyll Site to Heroku
published: true
date: 2020-06-14 07:30:00 UTC
tags: 
canonical_url: https://blog.taufek.dev/kubernetes/2020/06/14/deploy-jekyll-site-to-heroku.html
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/xkuqtatlxltsavb4spba.png
---

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 `web`process in Heroku, you could name it as `Dockerfile.web`. This works well ifyou have multiple `Dockerfile`s with different process such as `web`, `worker`, or`clock`. Later on, when you run `heroku container:push --recursive`, it willbuild all the `Dockerfile`s 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.