Learning Golang: Running Go in a container

Share on:

This is part 8 of my journey learning Golang.

Reproducible build & run environments

Over the years, it is not uncommon that different projects in the same language will have different requirements about the versions of the tools and libraries that they require.

For instance, I learned that there are differences in the behavior of the GO111MODULE environment variable across Go versions 1.12 and 1.13.

That’s why when I start a repository for a new project, one of the first things I do is to set up scripts for building and running the code in a reproducible way.

Docker containers are a very effective tool for that. So when I created a GitHub repo for my learning-go project, I set up a quick script to run the code. This way I know I’ll be able to run it years from now without any special setup other than having Docker installed.

I wish this was a general practice for open source projects. Getting their build requirements installed can be a chore, particularly when there are version conflicts with other projects.

Running Go in a Docker container

This is the script that I’m using for running my first Go programs:

 1#!/bin/bash
 2#
 3# Runs Go.
 4#
 5set -o nounset -o errexit -o pipefail                     # Abort the script on errors
 6
 7SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)  # Absolute directory where this script is stored
 8BASE_DIR=$(cd "$SCRIPT_DIR/.." && pwd)                    # Parent directory of this script
 9GO_VERSION="1.15-buster"                                  # Docker image tag of the Go version that will be used
10
11mkdir -p "$BASE_DIR/.cache"                               # Create .cache directory under base directory
12
13docker run                       `# Run a Docker container                               ` \
14  --rm                           `# Remove the container when the command exits          ` \
15  -it                            `# Set an interactive terminal                          ` \
16  -v "$BASE_DIR":"$BASE_DIR"     `# Mount base directory with same name in the container ` \
17  -v "$BASE_DIR/.cache":/.cache  `# Mount .cache directory under the container's root    ` \
18  -w "$BASE_DIR"                 `# Set base directory as the current working directory  ` \
19  --user $(id -u):$(id -g)       `# Use same user ID inside the container as on the host ` \
20  golang:$GO_VERSION             `# Use Go's docker image with the specified tag         ` \
21  go $@                          `# Run go with the provided command line arguments      `

Source: learning-go/bin/go

Essentially, this script will run Go in a Docker container, with the command-line arguments that are provided to it. For example:

1bin/go run ascii-art/main.go

See the inline comments for details on how it works. I am sure that I will evolve this script over time as required (e.g. for cross-platform builds).

How about you? What’s your preferred technique for reproducible build & run environments? And specifically for Go, do you have any hints?


comments powered by Disqus