Building a blog with Jekyll, Docker and GitLab

Building a blog with Jekyll, Docker and GitLab Image

I recently rebuilt my blog using Jekyll with Docker and GitLab so I'm going to share a similar process I used to create it.

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

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:

  • make changes to the src folder by adding new posts, changing styles etc..
  • 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'

    image: jekyll/jekyll
      - ./src:/srv/jekyll/site
      - ./dist:/srv/jekyll/_site
      - "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

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

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

  image: alpine:latest
  - cp -R ./dist ./public
    - public
  - 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 called project:


Commit and push the changes to the master branch:

$ git init
$ git remote add origin{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}

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.