Running Jekyll on Docker - For Easy Local Development
This website was create using Jekyll. If you wanna know more details, including how I am hosting this website on AWS S3 you can find all the details on How This Site Was Made article.
While working with Jekyll is super easy, the process of writing a post, building it, running a local server, having to use localhost:4000
every time, is not super optimal from my perspective and can be done easier.
A few pain points I noticed while writing posts in Jekyll:
- I have to start the server locally every time I want to write a post.
- Dealing with
localhost
and port numbers. - I have to use a code editor to make the writing and building more convenient, although there might be better alternatives to only focus on the writing part.
In this article, I’m sharing with you an easy solution for the first 2 pain points.
Solution for: I have to start the server locally every time I want to write a post.
For this one, you can make use of Docker in order to create a docker image that once running will keep Jekyll’s server running with --livereload
enabled for as long as you want. (I just leave it running all the time).
Fortunately, that’s not a hard task to accomplish.
Create a Dockerfile
in the root of your project and copy the content below:
FROM ruby:3.0.1-slim
RUN apt-get update && apt-get install -y build-essential openssl bundler
RUN mkdir -p /www
WORKDIR /www
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . ./
EXPOSE 4000
ENTRYPOINT ["bundle", "exec"]
CMD jekyll serve --host 0.0.0.0 --livereload
Note: In order to run Jekyll with Ruby 3.x you’ll have to add the Webrick
gem to your Gemfile as Ruby 3+ does not bundle Webrick
by default anymore. If you are using Ruby 2.x then it’s not necessary to add Webrick
to your Gemfile.
gem 'webrick', '~> 1.7'
Latest version can be found at https://rubygems.org/gems/webrick.
Create the docker image by typing:
$ docker build -t image-name .
Wait for the process to finish and at the end your image will be ready to run!
Runing the image:
Before you run your docker container, you should create a mapping between your current working directory and the working directory inside the docker container so that you can edit the blog files locally and see the results immediately.
As we don’t have a multi-container application here, I recommend you do the mapping as part of the docker run
command.
$ docker run --name container-name -dp 4000:4000 -v "$(pwd)":/www image-name
Wait the command to finish, and access localhost:4000 and you should be able to see your Jekyll website up and running :)
The best thing, if you edit an existing post or create a new one, you will be able to see it immediately on your browser :) Yay!!
Note: Live reloading, although enabled, is not triggering a reload on the hosting machine’s browser (your local machine), for now you’ll have to refresh the browser. If I find a solution for that I’ll update this post or if you know the solution, please share with me :)
Solution for: Dealing with localhost
and port numbers.
I usually run multiple services on my machine assigned to different ports. Having to type the port on the browser’s address bar it’s not the most pleasant task to do. Adding a mapping to the etc/hosts
file is not enough in this case as you cannot map ports there, just hosts.
Fortunately, again, there’s an easy solution for that. You can install and configure a reverse proxy such as Nginx to redirect a particular domain to a particular server on a specific port! That’s just what we want! Perfect! (There are other methods, but I find this one a very easy one).
Install Nginx:
$ brew install nginx
Configure a server for your local domain:
On Mac:
$ cd /usr/local/etc/nginx/servers
On Linux:
$ cd /etc/nginx/sites-available
Create a file with your domain name:
$ touch your-domain.local
Add the following content to your server file:
server {
listen 80;
server_name your-domain.local;
location / {
proxy_pass http://127.0.0.1:4000/;
}
}
The configuration above is creating a virtual server in Nginx which will resolve the domain your-domain.local
to the address http://127.0.0.1:4000/
.
Now, start your Nginx server:
On Mac:
$ brew services start nginx
Note: If you want to stop Nginx for any reason:
$ brew services stop nginx
On Linux:
Replace brew services
with sudo systemctl
and start/stop with enable/disable.
Alternatively you can just use sudo systemctl reload nginx
Open the /etc/hosts
file with your preferred text editor (will require admin privileges to save the file):
I’m using vi
in the example below:
$ sudo vi /etc/hosts
Go to the end of the filePress i
to enter in INSERT
mode and add:
127.0.0.1 your-domain.local
Press ESC
, :wq
to write the change.
Now, head to http://your-domain.local in your browser and you’ll be able to access your Jekyll website running on Docker with live reload enable using a local domain!
That’s it, with this simple setup, you’ll be one step further to being able to only focus on writing your posts while enjoying the easiness of using Jekyll as your static site generator.
If you’re interested on video tutorials as well, I have a couple of them published on my Independent Pixels youtube channel. Check it our to see if you like it :)