Skip to content

Commit 231033a

Browse files
committed
guides: docker build github actions primer
Signed-off-by: David Karlsson <[email protected]>
1 parent 548f411 commit 231033a

File tree

2 files changed

+278
-1
lines changed

2 files changed

+278
-1
lines changed

content/guides/gha.md

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
---
2+
title: An Introduction to CI with Docker and GitHub Actions
3+
linkTitle: Docker and GitHub Actions
4+
params:
5+
tags: [devops]
6+
time: 10 minutes
7+
---
8+
9+
This guide provides an introduction to building CI pipelines using Docker and
10+
GitHub Actions. You'll learn how to automate Docker builds, run containerized
11+
tests, and optimize your workflows for enhanced security and efficiency.
12+
13+
You will learn how to:
14+
15+
- Use Docker's official GitHub Actions to test and build your application.
16+
- Run unit tests with multi-stage builds.
17+
- Extract metadata and automatically generate tags and annotations for your Docker images.
18+
- Configure your workflow to conditionally push images based on the event type (not pushing on pull requests).
19+
- Generate Software Bill of Materials (SBOM) and provenance attestations to enhance security and traceability.
20+
21+
By the end of the guide, you'll have a simple, functional GitHub Actions
22+
configuration for Docker builds. Use it as-is, or extend it further to fit your
23+
needs.
24+
25+
## Prerequisites
26+
27+
If you want to follow along with the guide, ensure you have the following:
28+
29+
- A Docker account.
30+
- Familiarity with Dockerfiles.
31+
- A GitHub repository with a Dockerized application.
32+
33+
This guide assumes basic knowledge of Docker concepts but provides explanations
34+
for using Docker in GitHub Actions workflows.
35+
36+
## Setting up your GitHub Actions workflow
37+
38+
GitHub Actions workflows define a series of steps to automate tasks, such as
39+
building and pushing Docker images, in response to triggers like commits or
40+
pull requests. In this guide, the workflow focuses on automating Docker builds
41+
and testing, ensuring your containerized application works correctly before
42+
publishing it.
43+
44+
Create a file named `docker-ci.yml` in the `.github/workflows/` directory of
45+
your repository. Start with the basic workflow configuration:
46+
47+
```yaml
48+
name: Build and Push Docker Image
49+
50+
on:
51+
push:
52+
branches:
53+
- main
54+
pull_request:
55+
```
56+
57+
This configuration runs the workflow on pushes to the main branch and on pull
58+
requests. By including both triggers, you can build and test your application
59+
on feature branches and ensure that only approved code is pushed to your
60+
container registry.
61+
62+
## Run tests
63+
64+
A key step in CI is validating your application. By integrating tests into your
65+
Docker image's build process, you ensure that the application behaves as
66+
expected in a containerized environment. This reduces the risk of errors caused
67+
by differences between development and production environments.
68+
69+
You'll use the `docker/build-push-action` to run tests as part of the image
70+
build. This involves adding a test stage to your Dockerfile that runs tests
71+
during the build process. If the tests pass, the workflow proceeds to build the
72+
production image and push it to your container registry.
73+
74+
### Using Docker Build to run tests
75+
76+
Aside from producing images, Docker builds provide isolated environments for
77+
running tests. For an application's unit tests, it's best practice to define a
78+
build stage in your Dockerfile that lets you run your tests in a containerized
79+
environment with a `docker build` invocation, such as:
80+
81+
```console
82+
$ docker build --target tests .
83+
```
84+
85+
For example, consider the following Dockerfile:
86+
87+
```dockerfile
88+
# builder installs dependencies and builds the app
89+
FROM node:lts-alpine AS builder
90+
WORKDIR /src
91+
COPY package*.json ./
92+
RUN npm ci
93+
COPY . .
94+
95+
# test runs the unit tests
96+
FROM builder AS tests
97+
RUN npm test
98+
99+
# production builds the final image
100+
FROM node:lts-alpine AS production
101+
WORKDIR /app
102+
COPY --from=builder /src .
103+
CMD ["npm", "start"]
104+
```
105+
106+
In this Dockerfile:
107+
108+
- The first stage, `builder`, installs dependencies and copies the app's source code.
109+
- The `tests` stage runs tests using the `npm test` command.
110+
- The `production` stage copies the application from the `builder` stage and
111+
sets the command to start the application.
112+
113+
### Run tests with GitHub Actions
114+
115+
In your workflow file (`docker-ci.yml`), configure the job to build and test
116+
your image using the `docker/build-push-action` by adding the following job:
117+
118+
```yaml
119+
jobs:
120+
build:
121+
runs-on: ubuntu-latest
122+
steps:
123+
- name: Test the app
124+
uses: docker/build-push-action@v6
125+
with:
126+
target: tests
127+
```
128+
129+
This configuration assumes that your Dockerfile contains a stage named `tests`
130+
that executes your unit tests. The `docker/build-push-action` builds the
131+
`tests` stage, and if the tests fail during the build, the action fails, and
132+
the workflow stops.
133+
134+
Since the action uses the Git context by default, you don't need to check out
135+
the repository explicitly. The `docker/build-push-action` [automatically detects](https://github.com/docker/build-push-action?tab=readme-ov-file#git-context)
136+
the Git reference of the GitHub Actions workflow and builds with that
137+
repository as its context.
138+
139+
## Extract metadata for tags and annotations
140+
141+
To automate the tagging and labeling of your Docker images, use the
142+
`docker/metadata-action`. This action extracts metadata from your Git
143+
repository, such as branch names and commit SHAs, and uses them to generate
144+
tags and labels for your images.
145+
146+
Add the metadata action to your workflow:
147+
148+
```yaml
149+
- name: Extract Docker image metadata
150+
id: meta
151+
uses: docker/metadata-action@v5
152+
with:
153+
images: my-dockerhub-user/my-image
154+
```
155+
156+
> [!NOTE]
157+
> Replace `my-dockerhub-user/my-image` in the `images` field with your image
158+
> repository name.
159+
160+
This step prepares the metadata for use in tagging and labeling your images
161+
during the build and push process.
162+
163+
- The `images` input defines the image repository and name to use for tags and
164+
annotations.
165+
- The `id` property assigns a referable ID for use in later steps to build with
166+
the extracted metadata values.
167+
168+
## Authenticate to your registry
169+
170+
Before you build the image, you'll want to authenticate to your registry.
171+
Authentication is required to push your built image to the registry.
172+
173+
To authenticate with Docker Hub, add the following step to your workflow.
174+
175+
```yaml
176+
- name: Log in to Docker Hub
177+
uses: docker/login-action@v3
178+
with:
179+
username: ${{ vars.DOCKER_USERNAME }}
180+
password: ${{ secrets.DOCKER_PASSWORD }}
181+
```
182+
183+
This assumes `DOCKER_USERNAME` is configured as a
184+
[variable](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables),
185+
and `DOCKER_PASSWORD` as a
186+
[secret](https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions),
187+
in the GitHub repository, containing the username and password for your Docker
188+
account.
189+
190+
## Build and push the image
191+
192+
Finally, build the final production image and push it to your registry. This
193+
example also configures the action to generate SBOM and provenance
194+
[attestations](/manuals/build/metadata/attestations/_index.md) at this stage.
195+
SBOM (Software Bill of Materials) provides a detailed list of components
196+
included in your image, while provenance documents where, when, and how your
197+
image was built. Adding these attestations is a best practice for improving
198+
security and ensuring software supply chain integrity.
199+
200+
```yaml
201+
- name: Build and push Docker image
202+
uses: docker/build-push-action@v6
203+
with:
204+
push: ${{ github.event_name != 'pull_request' }}
205+
tags: ${{ steps.meta.outputs.tags }}
206+
labels: ${{ steps.meta.outputs.labels }}
207+
provenance: true
208+
sbom: true
209+
```
210+
211+
In this configuration:
212+
213+
- `push: ${{ github.event_name != 'pull_request' }}` ensures that images are
214+
only pushed when the event is not a pull request. This way, the workflow
215+
builds and tests images for pull requests but only pushes images for commits
216+
to the main branch.
217+
- `provenance: true` and `sbom: true` enable the generation of provenance and
218+
SBOM attestations, enhancing the security and traceability of your images.
219+
- `tags` and `labels` use the outputs from the metadata action to apply
220+
consistent tagging and labeling.
221+
222+
## Conclusion
223+
224+
With all the steps outlined in the previous section, here's the full workflow
225+
configuration:
226+
227+
```yaml
228+
name: Build and Push Docker Image
229+
230+
on:
231+
push:
232+
branches:
233+
- main
234+
pull_request:
235+
236+
jobs:
237+
build:
238+
runs-on: ubuntu-latest
239+
steps:
240+
- name: Test the app
241+
uses: docker/build-push-action@v6
242+
with:
243+
target: tests
244+
245+
- name: Extract Docker image metadata
246+
id: meta
247+
uses: docker/metadata-action@v5
248+
with:
249+
images: my-dockerhub-user/my-image
250+
251+
- name: Log in to Docker Hub
252+
uses: docker/login-action@v3
253+
with:
254+
username: ${{ secrets.DOCKER_USERNAME }}
255+
password: ${{ secrets.DOCKER_PASSWORD }}
256+
257+
- name: Build and push Docker image
258+
uses: docker/build-push-action@v6
259+
with:
260+
push: ${{ github.event_name != 'pull_request' }}
261+
tags: ${{ steps.meta.outputs.tags }}
262+
labels: ${{ steps.meta.outputs.labels }}
263+
provenance: true
264+
sbom: true
265+
```
266+
267+
### Further reading
268+
269+
- Learn more about advanced configurations and examples in the [Docker Build
270+
GitHub Actions](/manuals/build/ci/github-actions/_index.md) section.
271+
- For more complex build setups, you may want to consider
272+
[Bake](/manuals/build/bake/_index.md). (See also the
273+
[Mastering Buildx Bake guide](/guides/bake/index.md).)
274+
- If your builds are slow or you're building multi-platform images, take a look
275+
at [Docker Build Cloud](/guides/docker-build-cloud/_index.md), a managed
276+
build service that easily integrates with both local and GitHub Actions
277+
workflows.

content/manuals/build/ci/github-actions/_index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: Introduction to GitHub Actions
2+
title: Docker Build GitHub Actions
33
linkTitle: GitHub Actions
44
description: Docker maintains a set of official GitHub Actions for building Docker images.
55
keywords: ci, github actions, gha, build, introduction, tutorial

0 commit comments

Comments
 (0)