GoReleaser build multi arch Docker Images
GoReleaser is a release automation tool for Go projects. The goal is to simplify the build, release and publish steps while providing variant customization options for all steps.
GoReleaser is built with CI tools in mind, you only need to download and execute it in your build script. Of course, you can still install it locally if you want.
Your release process can be customized through a .goreleaser.yaml file.
Once you set it up, every time you want to create a new release, all you need to do is tag and run goreleaser release
I recently learned about goreleaser and immediately became fond of the tool. It’s easy to use and simplifies the deployment process immensely.
Pre requirements
- GoReleaser (tested this with version 1.5.0)
- Docker Buildx installed
On some operations systems Docker’s Buildx is not included and we have to install it subsequently, you can test it with the commanddocker buildx
.
Create a Git Repository
First of all we are going to create a Git Repository. So that we can use Git Tags, goreleaser uses the tags to create the container image tag.
mkdir goreleaser-test
cd goreleaser-test
git init
Create a Dockerfile
Now that we have a working git environment, we are going to create a minimal Dockerfile in our working environment for our Builds. We (goreleaser) will copy the Build Binary into the Container, the ENTRYPOINT
will run our Binary when the Container starts.
FROM alpine:3.15.0# copy over the binary from the first stage
COPY helloworld /helloworld/helloworldWORKDIR “/helloworld”
ENTRYPOINT [ “/helloworld/helloworld” ]
Create some Go
We will create a minimal Go binary that outputs Hello World, the operating system, and the processor architecture. So create the file in ./helloworld/helloworld.go
package mainimport (
"fmt"
"runtime"
)func main() {
fmt.Println("Hello World")
fmt.Println(runtime.GOOS, runtime.GOARCH)
}
Create .goreleaser.yaml
The next step is to prepare our .goreleaser.yaml
for the release. We put it in the main path.
# https://goreleaser.com
project_name: helloworld
before:
# https://goreleaser.com/customization/hooks/
hooks:
# tidy up
- go mod tidy
builds:
# https://goreleaser.com/customization/build/
- main: ./helloworld
binary: helloworld
env:
- CGO_ENABLED=0
goos:
- linux
goarch:
- amd64
- arm
- arm64
goarm:
- 6
- 7
mod_timestamp: "{{ .CommitTimestamp }}"
dockers:
# https://goreleaser.com/customization/docker/
- use: buildx
goos: linux
goarch: amd64
image_templates:
- "0hlov3s/{{ .ProjectName }}:{{ .Version }}-amd64"
- "0hlov3s/{{ .ProjectName }}:latest-amd64"
build_flag_templates:
- "--platform=linux/amd64"
- "--label=org.opencontainers.image.created={{.Date}}"
- "--label=org.opencontainers.image.title={{.ProjectName}}"
- "--label=org.opencontainers.image.revision={{.FullCommit}}"
- "--label=org.opencontainers.image.version={{.Version}}"
- use: buildx
goos: linux
goarch: arm64
image_templates:
- "0hlov3s/{{ .ProjectName }}:{{ .Version }}-arm64v8"
- "0hlov3s/{{ .ProjectName }}:latest-arm64v8"
build_flag_templates:
- "--platform=linux/arm64/v8"
- "--label=org.opencontainers.image.created={{.Date}}"
- "--label=org.opencontainers.image.title={{.ProjectName}}"
- "--label=org.opencontainers.image.revision={{.FullCommit}}"
- "--label=org.opencontainers.image.version={{.Version}}"
- use: buildx
goos: linux
goarch: arm
goarm: 6
image_templates:
- "0hlov3s/{{ .ProjectName }}:{{ .Version }}-armv6"
- "0hlov3s/{{ .ProjectName }}:latest-armv6"
build_flag_templates:
- "--platform=linux/arm/v6"
- "--label=org.opencontainers.image.created={{.Date}}"
- "--label=org.opencontainers.image.title={{.ProjectName}}"
- "--label=org.opencontainers.image.revision={{.FullCommit}}"
- "--label=org.opencontainers.image.version={{.Version}}"
- use: buildx
goos: linux
goarch: arm
goarm: 7
image_templates:
- "0hlov3s/{{ .ProjectName }}:{{ .Version }}-armv7"
- "0hlov3s/{{ .ProjectName }}:latest-armv7"
build_flag_templates:
- "--platform=linux/arm/v7"
- "--label=org.opencontainers.image.created={{.Date}}"
- "--label=org.opencontainers.image.title={{.ProjectName}}"
- "--label=org.opencontainers.image.revision={{.FullCommit}}"
- "--label=org.opencontainers.image.version={{.Version}}"
docker_manifests:
# https://goreleaser.com/customization/docker_manifest/
- name_template: 0hlov3s/{{ .ProjectName }}:{{ .Version }}
image_templates:
- 0hlov3s/{{ .ProjectName }}:{{ .Version }}-amd64
- 0hlov3s/{{ .ProjectName }}:{{ .Version }}-arm64v8
- 0hlov3s/{{ .ProjectName }}:{{ .Version }}-armv6
- 0hlov3s/{{ .ProjectName }}:{{ .Version }}-armv7
- name_template: 0hlov3s/{{ .ProjectName }}:latest
image_templates:
- 0hlov3s/{{ .ProjectName }}:latest-amd64
- 0hlov3s/{{ .ProjectName }}:latest-arm64v8
- 0hlov3s/{{ .ProjectName }}:latest-armv6
- 0hlov3s/{{ .ProjectName }}:latest-armv7
checksum:
# https://goreleaser.com/customization/checksum/
name_template: 'checksums.txt'
snapshot:
# https://goreleaser.com/customization/snapshots/
name_template: "{{ incpatch .Version }}-SNAPSHOT"
source:
# https://goreleaser.com/customization/source/
enabled: true
git commit & tag
git add .
git commit -m ‘Initial Commit’
git tag v0.0.1
Run a Test release
Since we have everything set up, we can do a test release. So when we run goreleaser wit--snapshot
, we will build the Container Images locally and goreleaser won’t push them to a registry.
goreleaser release — rm-dist — snapshot
Checkout your Container image
No that we successfully created the Container images, we can test them on our local Maschine. So we are going to checkout which images were build.
❯ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
0hlov3s/helloworld 0.0.2-SNAPSHOT-armv6 a613a22f467a 35 hours ago 6.04MB
0hlov3s/helloworld latest-armv6 a613a22f467a 35 hours ago 6.04MB
0hlov3s/helloworld 0.0.2-SNAPSHOT-amd64 7058d357c075 35 hours ago 6.79MB
0hlov3s/helloworld latest-amd64 7058d357c075 35 hours ago 6.79MB
0hlov3s/helloworld 0.0.2-SNAPSHOT-armv7 d8e9a147bdd4 35 hours ago 5.06MB
0hlov3s/helloworld latest-armv7 d8e9a147bdd4 35 hours ago 5.06MB
0hlov3s/helloworld 0.0.2-SNAPSHOT-arm64v8 1bf6fe199d86 35 hours ago 6.64MB
0hlov3s/helloworld latest-arm64v8 1bf6fe199d86 35 hours ago 6.64MB
Since we figured out, what Images we have, we can run them with the docker run
command.
❯ docker run 0hlov3s/helloworld:0.0.2-SNAPSHOT-amd64
Hello World
Helpful Links
Don‘t trust me
The author does not assume liability for errors contained in or for damages arising from the use of the Information.
And do not hesitate to ask me questions or send me suggestions for improvement.
#go #go/goreleaser