How-To: GitLab CI/CD → Build Docker, Push to Registry, Helm Deploy to RKE2
Updated: 2025-08-24
Overview
Set up a GitLab pipeline that builds a container image, pushes it to a private GitLab Container Registry, and deploys to RKE2 via Helm. This edition includes an expanded Kaniko section with practical executor flags and templates.
Dockerfile (multi-stage, Go example; swap for your stack):
# syntax=docker/dockerfile:1
FROM golang:1.22 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app
FROM gcr.io/distroless/base-debian12
WORKDIR /app
COPY --from=build /src/app ./app
USER 65532:65532
ENTRYPOINT ["./app"]
Create imagePullSecret (run once per namespace):
kubectl create secret docker-registry regcred --docker-server=gitlab.local:5050 --docker-username=<deploy_user_or_token_name> --docker-password=<deploy_token_or_pat> --docker-email=none@example.com -n <namespace>
.gitlab-ci.yml (Docker-in-Docker build):
stages: [build, deploy]
variables:
IMAGE: "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"
build:
stage: build
image: docker:26
services: [docker:26-dind]
script:
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
- docker build -t "$IMAGE" .
- docker push "$IMAGE"
only: [branches]
deploy:
stage: deploy
image: alpine/helm:3.14.4
before_script:
- apk add --no-cache curl bash
- mkdir -p ~/.kube && echo "$KUBECONFIG_CONTENTS" > ~/.kube/config
script:
- helm upgrade --install myapp ./helm/myapp -n <namespace> --create-namespace --set image.repository="$CI_REGISTRY_IMAGE" --set image.tag="$CI_COMMIT_SHORT_SHA" --set imagePullSecrets[0].name="regcred"
only: [branches]
Kaniko build (no DinD) — Expanded Options
This job shows common flags you’ll actually use: multiple destinations (SHA + latest), cache repo, build args, labels, TLS toggles, and artifacts like digest/tar.
build_kaniko:
stage: build
image:
name: gcr.io/kaniko-project/executor:v1.23.2-debug # pick a pinned version
entrypoint: [""] # allow running /kaniko/executor directly
variables:
IMAGE_REPO: "$CI_REGISTRY_IMAGE" # e.g. gitlab.local:5050/group/project
IMAGE_TAG: "$CI_COMMIT_SHORT_SHA"
IMAGE_LATEST_TAG: "latest"
DOCKERFILE: "Dockerfile"
CONTEXT: "$CI_PROJECT_DIR"
CACHE_REPO: "$CI_REGISTRY_IMAGE/cache" # registry path to store the cache layers
# Optional extras:
KANIKO_EXTRA_ARGS: "--snapshotMode=redo --use-new-run --verbosity=info"
script:
# Auth: use CI-provided credentials
- mkdir -p /kaniko/.docker
- >
echo "{"auths":{"$CI_REGISTRY":{"username":"$CI_REGISTRY_USER",
"password":"$CI_REGISTRY_PASSWORD"}}}" > /kaniko/.docker/config.json
# Build and push to SHA tag and 'latest'
- >
/kaniko/executor
--context $CONTEXT
--dockerfile $DOCKERFILE
--destination $IMAGE_REPO:$IMAGE_TAG
--destination $IMAGE_REPO:$IMAGE_LATEST_TAG
--build-arg GIT_SHA=$CI_COMMIT_SHA
--build-arg VERSION=${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA}
--label org.opencontainers.image.revision=$CI_COMMIT_SHA
--label org.opencontainers.image.source=$CI_PROJECT_URL
--cache=true
--cache-repo $CACHE_REPO
--cache-ttl=168h # 7d cache
--digest-file $CI_PROJECT_DIR/image-digest.txt
$KANIKO_EXTRA_ARGS
artifacts:
when: always
paths: [image-digest.txt]
only: [branches]
Using CI_JOB_TOKEN instead of CI_REGISTRY_PASSWORD
# GitLab’s built-in token (works on same GitLab instance)
echo "{"auths":{"$CI_REGISTRY":{"username":"gitlab-ci-token","password":"$CI_JOB_TOKEN"}}}" > /kaniko/.docker/config.json
Pinning your image name explicitly
# If you want a different repo path than $CI_REGISTRY_IMAGE:
variables:
IMAGE_REPO: "gitlab.local:5050/local/your-service"
IMAGE_TAG: "$CI_COMMIT_SHORT_SHA"
# Then use --destination $IMAGE_REPO:$IMAGE_TAG
Security Notes
- Mask and protect registry credentials; use deploy/CI tokens with least privilege.
- Sign images after push (Cosign) and verify at admission.
- Avoid pushing ':latest' from feature branches unless you truly want it.
- Keep your Dockerfile free of secrets; use build args only for non-sensitive data.
Meme idea
“It works on my machine” — Kaniko: *cool story, push the layers.*
Taylor Swift
“You can aim for my heart, go for blood / But you would still miss me in your bones.” — I Did Something Bad
Comments
Post a Comment