Skip to main content

Docker images & Helm charts

Before setting up the Kubernetes cluster, I need to prepare the Docker images and Helm charts.
To save the resource, I planned to use external services like GitHub as much as possible.

Therefore, I decided to use GitHub Packages to store the Docker images.
The Docker images will be built in GitHub Actions, and it automatically updates the image tag to the Helm chart if the build is successful.

This process looks quite simple, but there's one important thing to consider. Docker build process needs to be configured in GitHub Actions, and it is mainly held on Ubuntu runner, which is AMD64 architecture.
However, my home server is running on macOS, so the architecture is different (ARM64).
Therefore, I need to configure additional steps to build the Docker images on ARM64 architecture.

  1. Rust is a compiled language, so I need to compile the application for ARM64 architecture.
    I tried many references, and finally followed this blog.
  2. After compiling the application, I need to build the Docker image.
    Because the compiled application is for ARM64 architecture, the Docker image should be also for ARM64 architecture.
    Also, we don't need to store the dependencies in the Docker image anymore. So I implemented the multi-stage build in Dockerfile. After building the application, I moved only the application binary to the Distroless image.

This process was not easy, I tried with other references like multi-arch build in GitHub Actions, but failed many times.
Finally, I succeeded, and this is the final Dockerfile.

Dockerfile
FROM rust:latest AS builder
WORKDIR /app

COPY Cargo.toml .
RUN mkdir src
COPY src src
RUN apt update && apt upgrade -y
RUN apt install -y g++-aarch64-linux-gnu libc6-dev-arm64-cross

RUN rustup target add aarch64-unknown-linux-gnu
RUN rustup toolchain install stable-aarch64-unknown-linux-gnu

ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \
CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc \
CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++
RUN cargo build --release --target aarch64-unknown-linux-gnu


FROM gcr.io/distroless/cc-debian12:latest-arm64 AS release
WORKDIR /app
COPY --from=builder /app/target/aarch64-unknown-linux-gnu/release/file-server-rust .

EXPOSE 8080

CMD ["./file-server-rust"]

After writing the Dockerfile, I needed to configure the GitHub Actions workflow.
Because I configured the ARM64 architecture in the Dockerfile, I didn't need to configure the extra steps in GitHub Actions.

  1. Checkout the repository and build the Docker image.
  2. Push the Docker image to GitHub Packages, and extract the image tag.
  3. Checkout the Helm chart repository and update the image tag using yq.
docker-build.yml
name: Build file server Docker image

on:
# Your condition
workflow_dispatch:

jobs:
build-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: <your-token>

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=sha

- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

- name: Checkout helm chart private repo
uses: actions/checkout@v4
with:
repository: <your-helm-chart-repo>
token: <your-token>

- name: Change values.yaml
uses: mikefarah/yq@master
with:
cmd: yq -i '.image.tag = "${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}"' file-server/values.yaml

- name: Push to main branch
uses: cpina/github-action-push-to-another-repository@main
# ...

Helm charts are basically made with helm create, and I just modified the values.yaml file and templates from the default.


There are some other things that I suffered from.

  • You need to grant right permissions to the personal access token.
  • You need to grant personal access token to access organization repositories.