Test
This section focuses on testing. The example in this section focuses on linting, but the same principles apply for other kinds of tests as well, such as unit tests. Code linting is a static analysis of code that helps you detect errors, style violations, and anti-patterns.
The exact steps for how to test your code can vary a lot depending on the
programming language or framework that you use. The example application used in
this guide is written in Go. You will add a build step that uses
golangci-lint
, a popular linters runner for Go.
Run tests
The golangci-lint
tool is available as an image on Docker Hub. Before you add
the lint step to the Dockerfile, you can try it out using a docker run
command.
$ docker run -v $PWD:/test -w /test \
golangci/golangci-lint golangci-lint run
You will notice that golangci-lint
works: it finds an issue in the code where
there’s a missing error check.
cmd/server/main.go:23:10: Error return value of `w.Write` is not checked (errcheck)
w.Write([]byte(translated))
^
Now you can add this as a step to the Dockerfile.
# syntax=docker/dockerfile:1
ARG GO_VERSION=1.20
+ ARG GOLANGCI_LINT_VERSION=v1.52
FROM golang:${GO_VERSION}-alpine AS base
WORKDIR /src
RUN --mount=type=cache,target=/go/pkg/mod/ \
--mount=type=bind,source=go.sum,target=go.sum \
--mount=type=bind,source=go.mod,target=go.mod \
go mod download -x
FROM base AS build-client
RUN --mount=type=cache,target=/go/pkg/mod/ \
--mount=type=bind,target=. \
go build -o /bin/client ./cmd/client
FROM base AS build-server
ARG APP_VERSION="0.0.0+unknown"
RUN --mount=type=cache,target=/go/pkg/mod/ \
--mount=type=bind,target=. \
go build -ldflags "-X main.version=$APP_VERSION" -o /bin/server ./cmd/server
FROM scratch AS client
COPY --from=build-client /bin/client /bin/
ENTRYPOINT [ "/bin/client" ]
FROM scratch AS server
COPY --from=build-server /bin/server /bin/
ENTRYPOINT [ "/bin/server" ]
FROM scratch AS binaries
COPY --from=build-client /bin/client /
COPY --from=build-server /bin/server /
+
+ FROM golangci/golangci-lint:${GOLANGCI_LINT_VERSION} as lint
+ WORKDIR /test
+ RUN --mount=type=bind,target=. \
+ golangci-lint run
The added lint
stage uses the golangci/golangci-lint
image from Docker Hub
to invoke the golangci-lint run
command with a bind-mount for the build
context.
The lint stage is independent of any of the other stages in the Dockerfile.
Therefore, running a regular build won’t cause the lint step to run. To lint the
code, you must specify the lint
stage:
$ docker build --target=lint .
Export test results
In addition to running tests, it’s sometimes useful to be able to export the results of a test to a test report.
Exporting test results is no different to exporting binaries, as shown in the previous section of this guide:
- Save the test results to a file.
- Create a new stage in your Dockerfile using the
scratch
base image. - Export that stage using the
local
exporter.
The exact steps on how to do this is left as a reader’s exercise :-)
Summary
This section has shown an example on how you can use Docker builds to run tests (or as shown in this section, linters).
Next steps
The next topic in this guide is multi-platform builds, using emulation and cross-compilation.