The goal of this article is to build a simple Jekyll blog without installing anything on your machine (using Docker technology) and automate the deployment to a free GitLab page using GitLab CI.

If you don’t know what Docker is read my article Docker Presentation

Project structure

I chose the following structure for our blog named project:

src: the Jekyll sources
dist: the compiled static site

The development workflow will be as follows:

Editor will make changes to the `src` folder by adding new posts, changing styles and so on

Then, run Jekyll inside a Docker container to compile and preview the static site mounted locally to the `dist` folder
inspect the generated site in the dist folder if needed
use GitLab CI to rebuild the GitLab page from the content of the dist folder after a push to the master branch

Project setup

Let’s create the project directory to host the new blog and add a docker-compose.yml file containing the following:

version: '2'

services:
  jekyll:
    image: jekyll/jekyll
    volumes:
      - ./src:/srv/jekyll/site
      - ./dist:/srv/jekyll/_site
    ports:
      - "4000:4000"

We can now build a new Jekyll project named site that will be mounted to our local src folder:

$ docker-compose run jekyll jekyll new site

If you look into your project directory, you will see the following structure:

.
├── dist
├── docker-compose.yml
└── src
    ├── Gemfile
    ├── Gemfile.lock
    ├── _config.yml
    ├── _posts
    │   └── xxxx-xx-xx-welcome-to-jekyll.markdown
    ├── about.md
    └── index.md

Building and previewing the blog

When everything is in place we can build and serve our blog while watching for changes:

$ docker-compose run --service-ports jekyll jekyll serve --source=site

If you browse to http://localhost:4000, you will see your new blog!

Gitlab setup

You need an account on gitlab.com. It’s free.

Add a .gitlab-ci.yml file at the root of the project, containing the following:

pages:
  image: alpine:latest
  script:
  - cp -R ./dist ./public
  artifacts:
    paths:
    - public
  only:
  - master

From now, a GitLab CI pipeline will be launched each time there is a push to the master branch and will mount our dist folder content as the root of the GitLab page.

Setup a new Gitlab repository.

Commit and push the changes to the master branch:

$ git init
$ git remote add origin git@gitlab.com:{username}/project.git
$ git add .
$ git commit -m "Initial commit"
$ git push -u origin master

A new pipeline has just been created. Once it’s passed, the blog is available at https://{username}.gitlab.io/project/.

But, as you can see, asset paths are broken because the base url of the page is /project/.

In order to change it, we need to edit /src/_config.yml:

baseurl: "/project"

We can now rebuild the site:

$ docker-compose run jekyll jekyll build --source=site

When our changes are committed and pushed to the repo, the paths are fixed.

Daily workflow

When we want to work on the blog, for example, to create a new post, we just need to start Jekyll to build and serve the site:

$ docker-compose run --service-ports jekyll jekyll serve --source=site
The site will be automatically reloaded when there is a change in the src folder 

To preview it, we can browse to http://localhost:4000/project/.

When we are happy with the changes, we can push them to the GitLab repo and the live blog will be rebuilt.

Create a Jekyll based Blog

Clone a jekyll repository and rename it to projectid.gitlab.io

Create .gitlab-ci.yml

image: ruby:2.3

variables:
  JEKYLL_ENV: production

before_script:
  - bundle install

test:
  stage: test
  script:
  - bundle exec jekyll build -d test
  artifacts:
    paths:
    - test
  except:
  - master

pages:
  stage: deploy
  script:
  - bundle exec jekyll build -d public
  artifacts:
    paths:
    - public
  only:
  - master

Have fun!