Hugo + VSCode + Docker = ❤️
Setting up a devcontainer for VSCode to run Hugo
In a recent attempt to dockerize anything I can, I came across a new feature of VSCode Remote Containers.
Updates (20200710)
My pull request was accepted (Thanks Chuck!) and since then I’ve also created containers for bash script debugging and Vue.js development have also been merged, and should be available soon. To use these, open a folder in VSCode, open your Command Palette, and choose “Remote-Containers: Add Development Container Configuration Files”. From here you can choose “Show all Definitions…” and search through all available definitions.
Introduction
VSCode recently added a Remote extension to develop inside docker containers, called Visual Studio Code Remote - Containers. I took inspiration from my Hugo setup with gitlab pages to automatically build a static version of my site whenever I push to the repository, and saw an existing Jekyll remote container configuration, and thought, why not roll my own Hugo remote container.
Hugo Container
I looked at the container registry for the Hugo image I have configured with Gitlab CI to build my site. There I found a two stage dockerfile, the first stage builds from the golang:1.13-alpine image, downloads, verifies and extracts the prebuilt hugo binary from the Github releases, then uses muslstack to extend the default thread stack size to 8MB to work around segfault issues.
|
|
The second stage builds from the alpine:edge image, copies the hugo binary from the first (0) stage, builds the site with an image with minimal dependencies.
|
|
Jekyll Remote Container
Setting up a Jekyll remote container yields a few new files in the working folder:
- .devcontainer/devcontainer.json
- .devcontainer/Dockerfile
- .vscode/tasks.json
The devcontainer.json file contains some configuration settings for VScode and the tasks.json file defines some tasks that can be run from Terminal > Run Task or from the Command Palette using the command Tasks: Run Task
The dockerfile contained the configuration of a docker container for building a jekyll image. I found the parts of the dockerfile relevant to setting up a remote user:
|
|
The rest of the dockerfile installs git, openssh, less, ruby, bundler, jekyll and their dependencies, then cleaning up any install files.
Devcontainer Dockerfile
I created a new two stage dockerfile in .devcontainer that, first, installs some setup dependencies, then downloads the latest hugo_extended binary, and updates it with muslstack. It takes two build arguments to specify the hugo variant, and version number.
|
|
The second stage uses alpine:edge and copies over the hugo binary, installs libc, libstdc++, sudo, git, and openssh-client and sets up the vscode user, group and sudo access.
|
|
Devcontainer Json configuration
In the JSON configuration you can specify the build arguments for the Dockerfile, shell, any extensions to be installed, the ports to be forwarded, and the remote user to use instead of root.
|
|
Here the variant can be set to either ‘hugo’ or ‘hugo_extended’, and the version can be set to any valid version number, or ’latest’ to automatically get the most up to date release. Additionally this is where extensions for the container can be specified, personally I use the following extensions:
- David Anson’s vscode-markdownlint, because everything should be linted properly.
- Shuzo Iwasaki’s Table Formatter, because properly formatted markdown tables are beautiful.
- Street Side Software’s Code Spell Checker, because, spell checking…
These extensions can be added by updating the ’extensions’ section to the following:
|
|
Tasks File
The .vscode/tasks.json file contains some helpful tasks for interacting with hugo. The default ’test’ task, “Serve Drafts”, runs hugo in server mode with the -D
option, causing hugo to render any pages with draft: true
in the front matter. The default ‘build’ task simply runs the hugo
command, where hugo will build a static version of the site, and place it in the ./public
directory.
|
|
These tasks can be run from the Command Palette using the “Run Test Task” and “Run Build Task” respectively.
Update
After making my pull request Chuck Lantz made some suggestions for improvements. I switched the second stage of the dockerfile to use a more common (to remote containers) image: mcr.microsoft.com/vscode/devcontainers/base:alpine
, which allowed me to set the default shell to zsh. I also added a Better-TOML to the default extensions.
Conclusion
This template for a hugo docker container in vscode is currently available in my fork of the Microsoft/vscode-dev-containers, AarynSmith/vscode-dev-containers, and there is an open pull request here. Once this pull request is available you should be able to install the configuration using the following steps:
- Start VS Code and open your project folder.
- Press F1 select and Remote-Containers: Add Development Container Configuration Files… from the command palette.
- Select the Hugo definition.
Until then my template is available from my fork or from my repository https://github.com/AarynSmith/vscode-dev-container-hugo
- Clone the repository:
git clone https://github.com/AarynSmith/vscode-dev-containers.git
- Copy the contents of the folder in the cloned repository to the root of your project folder.
- Start VS Code and open your project folder.