Looking to create a simple website but don’t want to pay through the nose for hosting? Get started today for free with Jekyll and Docker.
Create Docker image
Alright, now onto the fun stuff! In this section we’re going to clone a seed for our Jekyll site and use it to create a Docker image we can run the same site both locally and on a server.
Never used Docker? No worries! Just head over to the Docker Jumpstart by Andrew Odewahn and start learning right away (recommended to continue).
Docker is designed to run on a variety of platforms including macOS, Windows and several varieties of Linux. To get Docker head to Install Docker on the docker docs website. Please install Docker before proceeding.
Clone Jekyll seed
In order to build a Docker image to run our Jekyll site we need an actual site to start with. Rather than creating one from scratch we’re going to use an open-source seed called Lanyon by Mark Otto. Go ahead and clone it now:
git clone https://github.com/poole/lanyon.git lanyon && cd $_
Tip: Looking for something more intersting or complex than Lanyon? Check out some of the wonderful themes created by the Jekyll god Michael Rose.
Configure Docker host container
Next we’ll configure a Docker container to host a Docker image we can use to run our site on DigitalOcean. Start by creating a
nginx.conf file in the root folder of the cloned Jekyll seed, modeling from the following:
# DOCKER-VERSION 1.6.0, build 4749651 # habd.as Dockerfile # Runs Jekyll under Nginx with Passenger FROM phusion/passenger-ruby21:0.9.15 MAINTAINER Josh Habdas "email@example.com" # Set environment variables ENV HOME /home/deployer # Use baseimage-docker's init process CMD ["/sbin/my_init"] # Expose Nginx HTTP service EXPOSE 80 # Start Nginx / Passenger RUN rm -f /etc/service/nginx/down # Remove the default site RUN rm /etc/nginx/sites-enabled/default # Add the Nginx site and config COPY nginx.conf /etc/nginx/sites-enabled/webapp.conf # Install bundle of gems WORKDIR /tmp COPY Gemfile /tmp/ COPY Gemfile.lock /tmp/ RUN bundle install # Add the Passenger app COPY . /home/app/webapp RUN chown -R app:app /home/app/webapp # Build the app with Jekyll WORKDIR /home/app/webapp RUN jekyll build # Clean up APT when done RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
What this will do is build a container image based off a container called passenger-docker, exposes traffic on 80 for port-forwarding, copies the site into the container, builds the site using Jekyll, configures Nginx to use it and then serves the whole thing up using Passenger.
Install Ruby dependencies
The dockerfile wants a file you don’t have yet called
Gemfile.lock. To create it use
Bundler from the same directory as the
Gemfile to create it:
With the lock file is created you’re ready to build the container image.
Build and run container image locally
Build the container image with the following command:
docker build --rm .
The above builds the image and removes intermediate containers after a successful build. Be patient while Docker pulls dependent layers during this process. Once completed, however, dependent layers will be cached during subsequent builds, making them faster.
After the build completes, get a listing of images:
Look at the top of the resulting list and copy the ID of the most recent image. Then run it in the background using the -d flag, forwarding port 80 on the container to port 80 to the host:
docker run -d -p 80:80 b64bea84255a
Verify the container is running with:
In this list look for an active container, meaning the image is up-and-running on port 80.
Connect to Jekyll site
With the container image running confirm it’s serving your Jekyll site:
curl $(boot2docker ip) # or localhost on linux
Note: See the Docker Docs website for help with the latest commands.
You can even connect to the above IP using a web browser. If everything’s working correctly you should see something like this:
That wasn’t so tough now, was it? Now that we’ve got a simple Jekyll website running under Docker let’s go ahead and deploy it to DigitalOcean.
Configure Server for Docker deployments
With the Docker image created we’re ready to host our site. For simplicity we’ll use DigitalOcean and take advantage of their 1-click Docker insta`llation.
Profit: If you don’t already have an account with DigitalOcean you may use my referral code and receive $10 in free credit toward usage fees. Steps may also be adapted for Vultr, Linode and Lightsail.
Create Docker Droplet
Login to DigitalOcean Control Panel and choose Create Droplet. Complete the subsequent form, selecting the $5/mo. size option and, in the Select Image section, click Applications and choose Docker as shown here:
Then Add SSH Key and create your droplet. Provisioning should finish in a matter of seconds. Once finished, create a new user account on the droplet.
Create new user
Once your droplet is provisioned create a new user so your not always executing commands using root. And while this is not strictly necessary, it’s beneficial for security and a good habit to get into anytime you create a new droplet.
SSH into your droplet by IP as the root user:
The first time you connect you should receive a prompt regarding host authenticity. When prompted type yes then press Return to continue connecting once you’ve verified the host is indeed yours.
rootuser. If not, you will need to enter the root password to continue connecting.
Once connected create a new user called
deployer and give them super user privileges as described in
How To Add and Delete Users on an Ubuntu 14.04 VPS.
Type exit followed by Return to end the remote connection. Next we’re going to add an authorized key to
deployer for easy access to the remote.
Add SSH key for deployer
Adding an SSH key for
deployer enables you to connect to the droplet without having to enter a password every time — both a convenience and security measure.
deployer created go ahead and go ahead and add your SSH key as an authorized key with the following one-liner:
cat ~/.ssh/id_rsa.pub | ssh deployer@HOST "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
Tip: Alternatively use ssh-copy-id if you can.
Where HOST is the IP of the droplet.
You will be prompted for the password the first go-around so go ahead and enter it. After that you will no longer be required to enter the
deployer password while connecting from this machine.
Run the site on DigitalOcean
To run our Jekyll site on our droplet we’ll first create an archive of the site source. Then we’ll upload the site source to DigitalOcean, build and run it.
Now that we’ve got a functional container image let’s go ahead and use it on DigitalOcean droplet with Docker pre-installed.
First commit any changes you’ve made and create a gzipped tarball of the source:
git add -A && git commit -m "All the things" && \ git archive -o app.tar.gz --prefix=app/ master
Note: This is a good time to push your changes to your own git repo.
Next use Secure copy to transfer the site’s source files from the current host to the droplet and rebuild the container image there:
scp app.tar.gz deployer@HOST:
Where HOST is the IP of the droplet created earlier.
This will copy the site archive to the server where it can be built and run.
Build and run container image remotely
With the app source uploaded to the server we’re ready to build and run the container image remotely. To do this first login to the remote server:
Where HOST is the IP of the droplet.
Once logged in to the remote, unarchive and build the site, tagging it
webapp to give it a more friendly name:
tar zxvf app.tar.gz && docker build -t webapp app/
Once the container image is built, run it on port 80 for both host and container:
docker run --rm -p 80:80 webapp
-dflag once you’ve confirmed the site is up to keep it running.
Confirm Docker web server is up
Now that the site’s up and running you can test it by browsing to http://HOST/ where HOST is the IP of your Droplet. If everything worked you should be staring at the same Jekyll site you saw on your local machine earlier.
Stopping the site
When we’re ready to bring your site down you can do so doing the following on the remote server:
docker stop $(docker ps -lq)
In this tutorial we learned how to create simple websites with Jekyll and Docker. Additionally we learned a simple workflow to deploy them to DigitalOcean via the command line, using Passenger to serve them with minimal required configuration.
Here are some ideas for things try next once you’re happy with the look-and-feel of your new Jekyll site:
- Host your Docker container on DockerHub. They’ll even automatically build images for you when you commit to GitHub or BitBucket.
- Install Octopress 3 and use it to simplify the process of managing pages and posts.
- Automate the deployment process using drone or Octopress.
- Learn about and set-up zero-downtime deployments using a proxy and tools such as flocker or Ansible.
Sign-up for a free CloudFlare account and use the CDN to boost site performance.
- Purchase a vanity domain name and use it to route DNS traffic to CloudFlare or directly to the app running on the Droplet.