The blog based on Hugo deployed on GitHub Pages with Github Actions.
To create a Hugo site, the first thing you should install Hugo. To avoid installing Hugo on the PC, Docker is a good choice which allows users to package the application with all of its dependencies into inside container.
- creating a
docker-compose.ymlfile with the configurations below, and create a new emptyhugodirectory
version: "3"
services:
server:
image: klakegg/hugo:0.93.2-ext-ubuntu-onbuild
container_name: hugo-server
# uncomment this when first run
# command: new site /src
command: server
volumes:
- "./hugo:/src"
ports:
- "1313:1313"
- uncomment the line
command: new site /srcand comment the linecommand: serverin thedocker-compose.ymlfile - run
docker-compose up - comment the line
command: new site /srcand uncomment the linecommand: serverin thedocker-compose.ymlfile - run
docker-compose upagain, then you can see an empty site inlocalhost:1313address by browser
The configure file of docker-compose.yml as the below shown:
version: "3"
services:
server:
image: klakegg/hugo:0.93.2-ext-ubuntu-onbuild
container_name: hugo-server
# uncomment this when first run
# command: new site /src
command: server
volumes:
- "./hugo:/src"
ports:
- "1313:1313"
Let me explain the details of the configurations:
- image: The server create container based an image from a public repository in Docker Hub, which is recommended by Hugo. As for the tags, you can use other as you like, but
-extis recommended since some theme may use additional tools. - command: The default entrypoint of the container is
hugo, when we setcommand: [option], it will runhugo [option]inside container. However, thehugo servercommand will fail with an errorhugo-server | Error: Unable to locate config file or config directory. Perhaps you need to create a new site.when we build a website firstly since we have nothing in current workspace. To solve the problem, we can uncommentcommand: new site /srcand commentcommand: server, which will create a create a new Hugo site in current workspace. - volumes: The key mounts the project directory(
./hugo) on the host to the path('/src') inside the container. Using./hugoinstead of current directory is because an errorhugo-server | Error: /src already exists and is not empty. See --force.will occur if the initial directory is not empty. Another way to solve the problem is using--forceflag. - ports: The key binds the container and the host machine to the same port
1313.
Since there is no docker-compose.yml, we can create a website in current directory.
- If you have no hugo website, run
docker run --rm -it -v ${pwd}:/src klakegg/hugo:0.93.2-ext-ubuntu-onbuild new site .to create a new Hugo site. - run server:
docker run --rm -it -v ${pwd}:/src -p 1313:1313 klakegg/hugo:0.93.2-ext-ubuntu-onbuild server, then you can see an empty site inlocahost:1313
There are so many beautiful themes for Hugo, we can select one in the Hugo Themes. Here I use zozo theme(fork from hugo-theme-zozo) to show how to apply a theme for our site.
since changing theme opeation just related to git operation and file change, so we can change theme by two approaches, inside or outside container.
If we want to upload the docker-compose.yml to your github repository, the method is recommended.
- using
zozoas submodule with
git submodule add --depth=1 https://github.com/nicolgo/hugo-theme-zozo.git hugo/themes/zozo
git submodule update --init --recursive # needed when you reclone your repo (submodules may not get cloned automatically)
- Updating the theme:
git submodule update --remote --merge
- Setting in
config.toml:
theme: "zozo"
- enter continer with:
docker exec -it hugo-server /bin/bash
- Using theme as submodule with
git init
git submodule add --depth=1 https://github.com/nicolgo/hugo-theme-zozo.git themes/zozo
git submodule update --init --recursive # needed when you reclone your repo (submodules may not get cloned automatically)
- Updating the theme:
git submodule update --remote --merge
- Setting in
config.tomlwith:
echo theme = \"zozo\" >> config.toml
- start container by docker-compose or docker command.
There are two ways to publish your website.
- using two repositories. one is a private repository to store file. another is a public repository named
username.github.io, which store the static pages generated in the./publicdirectory by Hugo. - only use one repository but two branches. one is the main branch with original files, another branch used to store static pages generated by Hugo. The repository can be public or private.
Here we use one public repository to store our blog files and deployed the pages to
username.github.iowith GitHub Actions automatically.
- create a new public repository follow the guide.
- upload blog file to the repository.
- create a file in
.github/workflows/gh-pages.yml - if you did not create a
Hugoto store your file, you just follow the guide to write thegh-pages.yml. The details is:
name: github pages
on:
push:
branches:
- main # Set a branch to deploy
pull_request:
jobs:
deploy:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
with:
submodules: true # Fetch Hugo themes (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: 'latest'
# extended: true
- name: Build
run: hugo --minify
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
if: github.ref == 'refs/heads/main'
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public
if you use a isolated Hugo directory, you should change the file as below:
name: github pages
on:
push:
branches:
- main # Set a branch to deploy
pull_request:
jobs:
deploy:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
with:
submodules: true # Fetch Hugo themes (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: 'latest'
# extended: true
- name: Build
working-directory: ./hugo
run: hugo --minify
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
if: ${{ github.ref == 'refs/heads/main' }}
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./hugo/public
- rename
baseURLinconfig.tomlwith the valuehttps://<USERNAME>.github.ioand upload it. - In the repository profile, going Settings->Pages, change the source branch to
gh-pages. Congratulation, your site created successfully!
see GitHub Action
- enter the docker container with:
docker exec -it hugo-server /bin/bash
- using
hugocommand to generate a content file base on templates inArchethypesfolder
hugo new posts/first-blog.md
or create a content by Leaf Bundle way:
hugo new posts/first-blog/index.md
There are two ways to group your images: Static Files or Page Bundles.
- create a
static/directory in site directory - adding a file
static/image.png, then include it in markdown file with
- create a content with the command below,
index.mdis a must.
hugo new posts/first-blog/index.md
- add an image to
posts/first-blog/image.pngThe file structure will like this:
- posts
- first-blog
- index.md
- image.png
- first-blog
- include the image in markdown file with

[3] How to use Develop Jekyll (and GitHub Pages) locally using Docker containers