Hugo is one of the most popular open-source Static Site Generator (SSG) frameworks written in Go. It allows developers to build fast HTML websites by combining content and templates. Visit the official documentation of Hugo to know more about it.
In this Hands-on lab, we will see how to deploy a simple HTML website using Hugo on Kubernetes. However, to understand the whole process clearly, we will first set up Hugo's website on a simple VM and then try to set up in a Docker container. Lastly we deploy the Hugo site on Kubernetes. After setting up, we will also try to make some changes to the website and ensure that the website is updated.
About Lab Setup
Our lab has been set up with necessary tools like base OS (Ubuntu), developer tools like Git, Vim, wget and others.
You can bring this setup on by clicking on the Lab Setup on the right side of the screen. Note that there are two app specific URLs exposed specifically for the hands-on lab purpose.
Hugo on VM
In this step, we will see how to deploy Hugo on a simple VM. The following steps should also work in the desktop environment as well.
Install and extract the tarball
curl -L https://github.com/gohugoio/hugo/releases/download/v0.92.0/hugo_0.92.0_Linux-64bit.tar.gz -o hugo_0.92.0_Linux-64bit.tar.gz && tar -xzf hugo_0.92.0_Linux-64bit.tar.gz
Make the binary executable and move inside /usr/local/bin/
chmod +x hugo && mv hugo /usr/local/bin/hugo
Our installation is done. Confirm by checking the version by running command `hugo version`.
Now we will proceed with setting up a simple website.
Create a new Hugo site
Run the following command to bring a Hugo site with the name “hugosite”. Note that you can give any desired name to your site.
hugo new site hugosite
Initializing the Git repository
cd hugosite && git init
For the demo purpose, we will be using one of Hugo’s beautiful themes, Anake. There are many ways to set up Hugo’s theme. However, we will use a simple approach of adding a theme as “Git Submodule”. Perform the following steps to add “Anake” theme as Git submodule to our website repository and set the theme to configuration file.
cd hugosite && git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke && echo theme = \"ananke\" >> config.toml
Create your first blog post
It is quite easy to create a blog in Hugo. The `hugo new` command will create a blog post with a default template which we can modify as per our need. Run the following command to get started with your first blog post.
cd hugosite && hugo new posts/my-first-post.md
Now, edit the post via `vim` editor or with an IDE provided in this lab which can be opened after clicking on the button “Open IDE” on the right hand side of the page.
Now, start the Hugo Server.
hugo server -D -p 30000 --bind 0.0.0.0
By default Hugo application binds with the localhost (127.0.0.1), but to access this application from the internet we have to bind the Hugo application to all network interfaces i.e. 0.0.0.0.
Once the server is running, you can access your website through the `app-port-30000` URL on the right side of the page under the `lab-urls` section.
Hugo on Docker container
In the previous section, we have seen how to deploy a Hugo based website on a VM, now in this section, we will try to deploy the same website inside a Docker container.
For that, we will need to create a Dockerfile as below:
Following are few key points from the Dockerfile:
- Using ubuntu:latest as a base image.
- Running a docker container as a 'root' user.
- Updating the package lists and installing required packages.
- Installing Hugo from tarball.
- In the last command , we specify an instruction that is to be executed when a Docker container starts. The command will start the Hugo Server in the container at port 30000, and use the content and templates from the /root/hugosite directory to render a website.
Now, build the Docker image from the Dockerfile and start the container by performing following steps:
docker build -t ubuntu:hugo /root/. && docker run -dit -v /root/hugosite:/root/hugosite -p 30000:30000 --name hugo ubuntu:hugo
The above command will create a Docker container with name “hugosite” from the Docker image we have created in previous site. It will also mount the host directory(/root/hugosite) to the container directory and map the port 30000 of Hugo server to 30000 of our base VM. We can now use this port of the Base VM along with an IP address to connect to the Hugo Server.
Now you can access the Hugo application through app-port-30000 URL.
After accessing the website remove the container.
docker stop hugo && docker rm hugo
Setting Up Hugo on K8s
So far, we have seen how to deploy the Hugo website on Base VM and Docker containers. In this section we will deploy the website on Kubernetes.
One of the important questions that arises in the Kubernetes environment is “How can we serve the content and templates to the Hugo server that is running inside the pod?”
The solution to this problem is “Persistent Volume (PV)”.
Pod will use PersistentVolumeClaim to request physical storage. We will specify the hostpath as /root/hugosite ( a directory in the host machine) while creating PV . After installing the Hugo in the base VM, we will keep the contents and templates required for the website inside the /root/hugosite directory . By using PVC, pods can access the host directory. This way, the Hugo server which is running inside the container can access the content as well as templates and will render the web pages.
Create hostPath PersistentVolume
hostPath PersistentVolume uses a file or directory on the Node to emulate network-attached storage.
In the above yaml file, we have specified the hostPath as “/root/hugosite” which is the directory with contents and templates on the Base VM that is required by the Hugo Server to render a full HTML website.
Now, apply the above yaml file to create a PV and also verify in the list of persistent volumes.
kubectl apply -f pv.yaml && kubectl get pv
Create a PersistentVolumeClaim
The yaml file for PersistentVolumeClaim looks like below:
Two key points about above yaml file are:
- It requests a volume of at 1 gibibytes that can provide read-write access for at least one Node.
- This PVC is using the PV “task-pv” that we have created in the previous step.
Now, apply the above yaml file to create a PVC and also verify in the list of persistent volume claims.
kubectl apply -f pvc.yaml && kubectl get pvc
Creating a Deployment
The following is a yaml file for the deployment of our website.
Apply the above yaml file to create a deployment and verify it in the list of deployments.
kubectl apply -f deploy.yaml && kubectl get deployment
Now, wait for some time for the deployment to finish.
Once the deployment of the app is ready, create a service yaml file. In this file, we are asking the cluster load balancer that we want your service to expose to the public world so everyone can see the application running. For this use case we take the help of a NodePort. It exposes the service on each Node's IP.
Apply the above service yaml file to create a service and verify it in the list of services.
kubectl apply -f svc.yaml && kubectl get svc
Now, access the Hugo application through app-port-30000 URL. You will see the exact same web page as in previous cases while deploying in a base VM or Docker container.
Updating the Hugo Website
In this section, we will see how to update our website content. Create another markdown file with the name “my-second-post.md”.
Now add the new content to “my-second-post.md” file.
cat > my-second-post.md
Copy and paste the below content:
After copying the code use Shift + Insert to paste the code in the terminal. Lastly, use Ctrl + D to save the markdown file.
Verify the contents of markdown file as:
Now, if you open app-port-30000 URL, you will see the newer version of Hugo website with two blog posts.
In this hands-on-lab we have seen how to deploy websites using Hugo on Base VM, on Docker and on Kubernetes. We made changes in websites using markdown files and see the newer version of the website is being displayed.