../zola-deployment

Other language:
ja

Deploying Zola

Published:

technology Zola Kubernetes Argo CD Docker

About the Structure of This Site

This site is hosted on a Kubernetes cluster at my home. Additionally, it is built using Zola. I write in Markdown locally, and when I push to GitHub, it is automatically deployed to the Kubernetes cluster. In this article, I will discuss this structure in detail.

Building a Japanese Blog with Zola

By default, Zola does not support indexing in Japanese. Therefore, you need to build the Zola executable with the --features indexing-ja flag. However, the Docker image provided by the Zola is built without the --features indexing-ja option, necessitating the creation of your own Zola Docker image.

Creating a Japanese-Supported Zola Image

  1. Git clone Zola from the repository.
  2. Create a Dockerfile with the following content:
FROM rust:slim AS builder

RUN apt-get update -y && \
  apt-get install -y make g++ libssl-dev && \
  rustup target add x86_64-unknown-linux-gnu

WORKDIR /app
COPY . .

RUN cargo build --release --target x86_64-unknown-linux-gnu --features indexing-ja

FROM gcr.io/distroless/cc-debian12:latest
COPY --from=builder /app/target/x86_64-unknown-linux-gnu/release/zola /bin/zola
ENTRYPOINT [ "/bin/zola" ]
  1. Then build.
docker build -t zola:1.0.0 .
  1. Later, for use with GitHub Actions, upload the image to ghcr.io. Proceed assuming that the login process has been completed.
docker tag zola:1.0.0 ghcr.io/<GITHUB_ID>/zola:1.0.0
docker push ghcr.io/<GITHUB_ID>/zola:1.0.0
  1. Go to https://github.com/users/<GITHUB_ID>/packages/container/zola/settings and add your Zola repository to Manage Actions access.

With these steps completed, the Zola image for building is now ready.

Building the Site

  1. Place the following Dockerfile directly under your blog's directory:
FROM ghcr.io/<GITHUB_ID>/zola:1.0.0 as zola

COPY . /project
WORKDIR /project
RUN ["zola", "build"]

FROM ghcr.io/static-web-server/static-web-server:2
WORKDIR /
COPY --from=zola /project/public /public
  1. Perform a trial build:
docker build -t blog:1.0.0 .

With these steps, you can create a Docker image for your blog.

Automating Builds with GitHub Actions

Write the following content into .github/workflows/build.yaml within the blog repository. Please modify the content as needed.

on:
  push:
    branches:
      - main
  workflow_dispatch:

permissions:
  id-token: write
  contents: write

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

    steps:
      - name: Check out the repository
        uses: actions/checkout@v2

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1

      - name: Login to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract version from tags
        id: get_version
        run: |
          git fetch --prune --unshallow
          latest_tag=$(git describe --tags $(git rev-list --tags --max-count=1) 2>/dev/null || echo "v0.0.0")
          version="${latest_tag/v/}"
          echo "::set-output name=version::${version}"

      - name: Increment version
        id: inc_version
        run: |
          version="${{ steps.get_version.outputs.version }}"
          major=$(echo $version | cut -d. -f1)
          minor=$(echo $version | cut -d. -f2)
          patch=$(echo $version | cut -d. -f3)
          new_version="$major.$minor.$((patch + 1))"
          echo "New version: $new_version"
          echo "::set-output name=new_version::${new_version}"

      - name: Build and push Docker image
        uses: docker/build-push-action@v2
        with:
          context: .
          push: true
          tags: |
            ghcr.io/${{ github.actor }}/blog/blog:${{ steps.inc_version.outputs.new_version }}
            ghcr.io/${{ github.actor }}/blog/blog:latest

      - uses: rickstaa/action-create-tag@v1
        id: "tag_create"
        with:
          tag: ${{ steps.inc_version.outputs.new_version }}
          tag_exists_error: false
          message: ${{ steps.inc_version.outputs.new_version }}
          github_token: ${{ secrets.GITHUB_TOKEN }}

With this setup, any push to GitHub will automatically trigger a Zola build, and the version tag will be incremented.

Automatic Deployment with Argo CD Image Updater

We will be using version 0.12.2 of Argo CD Image Updater. Assume that the Kubernetes cluster and Argo CD are already set up.

  1. Install Argo CD Image Updater:
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-image-updater/v0.12.2/manifests/install.yaml
  1. Create files for deploying with Argo CD. Construct the following directory structure and I provide the examples for blog.yml, kustomization.yml, and service.yml. Please write ingress.yml according to your own environment.
apps/
├─ blog/
│  ├─ base/
│  │  ├─ blog.yml
│  │  ├─ ingress.yml
│  │  ├─ kustomization.yml
│  │  ├─ service.yml
│  ├─ overlays/
│  │  ├─ kustomization.yml
# apps/blog/base/blog.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: blog
  labels:
    app: blog
spec:
  selector:
    matchLabels:
      app: blog
  replicas: 1
  template:
    metadata:
      labels:
        app: blog
    spec:
      containers:
        - image: ghcr.io/<GITHUB_ID>/blog/blog:latest
          imagePullPolicy: Always
          name: blog
# apps/blog/base/kustomization.yml
resources:
  - blog.yml
  - ingress.yml
  - service.yml
# apps/blog/base/service.yml
apiVersion: v1
kind: Service
metadata:
  name: blog
  namespace: blog
spec:
  type: LoadBalancer
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  selector:
    app: blog
# apps/blog/overlays/kusotmization.yml
bases:
  - ../base
  1. Write the Application manifest for Argo CD.
# blog.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: blog
  namespace: argocd
  annotations:
    argocd-image-updater.argoproj.io/image-list: "blog=ghcr.io/<GITHUB_ID>/blog/blog:latest"
    argocd-image-updater.argoproj.io/write-back-method: "argocd"
    argocd-image-updater.argoproj.io/blog.update-strategy: "latest"
    argocd-image-updater.argoproj.io/blog.allow-tags: "regexp:^\\d+\\.\\d+\\.\\d+$"
spec:
  project: default
  source:
    repoURL: '<ArgoCD git Repository>'
    path: 'apps/blog/overlays'
    kustomize:
      namePrefix: blog-
  destination:
    server: 'https://kubernetes.default.svc'
    namespace: 'blog'
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
  1. deploy
kubectl apply -n argocd -f blog.yaml

If all the above steps have been carried out correctly, deployment should occur automatically.