Skip to main content

Getting Started with Hugo and Docker

Docker Container #

Pull the Docker container from the Docker Hub:

docker pull registry.gitlab.com/pages/hugo/hugo_extended:latest

Tag #

For convenience, let’s create an alias (tag) so we don’t have to refer to the full url for every Docker command.

docker tag registry.gitlab.com/pages/hugo/hugo_extended:latest hugo_extended

For more information see docker tag.

Creating a New Site #

We can begin using the Hugo container to create a new site:

docker run --rm -v ${PWD}:/src hugo_extended hugo new site quickstart
  • docker run Have Docker run (create a new container)
  • --rm tells Docker we want to clean up the container once it finishes executing.
  • -v ${PWD}:/src mounts the current directory on the host machine to a folder within the Hugo container at /site.
  • hugo_extended is the Hugo container we pulled earlier.
  • hugo new site <site_name> Execute the new site subcommands for Hugo. The Hugo container has already defined the primary entry point of the container to be the hugo command. The last argument is the name of the site we are creating.

After executing the command above you’ll see:

Congratulations! Your new Hugo site is created in /src/quickstart.

Just a few more steps and you're ready to go:

1. Download a theme into the same-named folder.
   Choose a theme from https://themes.gohugo.io/ or
   create your own with the "hugo new theme <THEMENAME>" command.
2. Perhaps you want to add some content. You can add single files
   with "hugo new <SECTIONNAME>/<FILENAME>.<FORMAT>".
3. Start the built-in live server via "hugo server".

Visit https://gohugo.io/ for quickstart guide and full documentation.
  1. We executed Hugo within the container; Hugo isn’t installed on the host.

  2. The resulting files (or artifacts) from running the hugo new site were persisted and available on the host even after the container was destroy because of the volume we mounted.

Adding a Theme #

Before we go add a theme let’s treat this as a real project:

cd quickstart
git init
git add .
git commit -m "initial commit"

Now that we have a git repository we an add a theme via submodule:

git submodule add https://github.com/calintat/minimal.git themes/minimal
git submodule init
git submodule update
echo 'theme = "minimal"' >> config.toml

If this theme isn’t to your liking feel free to browse https://themes.gohugo.io/ for more them options.

At this point we can bring up the site with:

docker run --rm -v ${PWD}:/src -p 1313:1313 hugo_extended hugo server --bind 0.0.0.0
  • docker run Have Docker run (create a new container)
  • --rm tells Docker we want to clean up the container once it finishes executing.
  • -v ${PWD}:/src mounts the current directory on the host machine to a folder within the Hugo container at /src.
  • -p 1313:1313 port forwards port 1313 on our host to 1313 on our container
  • hugo_extended is the Hugo container we pulled earlier.
  • hugo server --bind 0.0.0.0 Execute the hugo server subcommand. The additional bind option is required when running in a container otherwise you won’t be able to open the site locally in your browser.

You’ll get some output:

                   | EN
+------------------+----+
  Pages            |  7
  Paginator pages  |  0
  Non-page files   |  0
  Static files     |  3
  Processed images |  0
  Aliases          |  0
  Sitemaps         |  1
  Cleaned          |  0

Total in 42 ms
Watching for changes in /src/{content,data,layouts,static,themes}
Watching for config changes in /src/config.toml
Serving pages from memory
Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
Web Server is available at http://localhost:1313/ (bind address 0.0.0.0)
Press Ctrl+C to stop

Open a browser and navigate to http://localhost:1313.

Once your done looking press Ctrl+C in the Terminal to stop the running Hugo Docker container.

Commit your Changes #

git add .
git commit -m "add theme submodule"

Streamlining with Docker Compose #

Docker Compose provides us a mechanism to reduce our typing and get everything we need up and going. In this case there is just the one service, but imagine needing databases, logging services, key-value services, and API service. It is so much nicer to run one thing and have the system ready for me to jump right into it.

Another reason for this is our continuous integration and deployment. You’ll often here a lot of people talk about using Docker to maintain consistency between environments; what is running in dev is the same as integration, staging, prod only with configuration variances. While this is true the other powerful thing Docker Compose provides it a composable set of deployment commands. More on this later.

Create a docker-compose.yml in the project root with the following contents:

version: "3"
services:
  hugo:
    image: registry.gitlab.com/pages/hugo/hugo_extended:latest
    working_dir: /src
    ports:
      - "1313:1313"
    volumes:
      - ".:/src"
    command: server --bind 0.0.0.0

Starting Hugo #

docker-compose up -d hugo

Open a browser and navigate to http://localhost:1313.

Commit your Changes #

git add .
git commit -m "add docker-compose"