Skip to main content

GitLab Setup: GitLab & GitLab Registry Kubernetes Deployment, GitLab Runner Kubernetes Deployment, GitLab Shell Configuration, CoreDNS Configuration, Enable GitLab Pages; Example CI Pipeline with K8s based GitLab Runner

2414 words·
GitLab Kubernetes GitLab Registry GitLab Runner GitLab Pages GitLab Shell SCI Longhorn
Table of Contents

Overview
#

Kubernetes Setup
#

In this tutorial I’m using the following Kubernetes cluster, deployed with Kubeadm:

# Kubernetes cluster:
NAME      STATUS   ROLES           AGE   VERSION    INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
ubuntu1   Ready    control-plane   28m   v1.29.11   192.168.30.10   <none>        Ubuntu 24.04.1 LTS   6.8.0-49-generic   containerd://1.7.23
ubuntu2   Ready    worker          22m   v1.29.11   192.168.30.11   <none>        Ubuntu 24.04.1 LTS   6.8.0-49-generic   containerd://1.7.23
ubuntu3   Ready    worker          21m   v1.29.11   192.168.30.12   <none>        Ubuntu 24.04.1 LTS   6.8.0-49-generic   containerd://1.7.23
ubuntu4   Ready    worker          20m   v1.29.11   192.168.30.13   <none>        Ubuntu 24.04.1 LTS   6.8.0-49-generic   containerd://1.7.23

192.168.30.14 # Ubuntu 24 based deployment server with Docker platform installed

Longhorn CSI StorageClass
#

I’m using the following Longhorn CSI based StorageClass named longhorn-rwo-retain:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: longhorn-rwo-retain
provisioner: driver.longhorn.io
allowVolumeExpansion: true
parameters:
  numberOfReplicas: "2"
  staleReplicaTimeout: "2880" # 48 hours in minutes
  fromBackup: ""
  fsType: "ext4"
volumeBindingMode: Immediate
reclaimPolicy: Retain
# List StorageClasses
kubectl get sc

# Shell output:
NAME                  PROVISIONER          RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
longhorn (default)    driver.longhorn.io   Delete          Immediate           true                   32m
longhorn-rwo-retain   driver.longhorn.io   Retain          Immediate           true                   22m
longhorn-static       driver.longhorn.io   Delete          Immediate           true                   32m



GitLab Helm Repository
#

Add Helm Repository
#

# Add GitLab Helm repository
helm repo add gitlab https://charts.gitlab.io/ &&
helm repo update

List Available Helm Charts
#

# Optional: List the available Helm Charts
helm search repo gitlab

# Shell output:
NAME                            CHART VERSION   APP VERSION     DESCRIPTION
gitlab/gitlab                   8.6.0           v17.6.0         GitLab is the most comprehensive AI-powered Dev...
gitlab/gitlab-agent             2.9.0           v17.6.0         GitLab Agent for Kubernetes is a way to integra...
gitlab/gitlab-omnibus           0.1.37                          GitLab Omnibus all-in-one bundle
gitlab/gitlab-operator          1.7.0           1.7.0           The GitLab operator aims to manage the full lif...
gitlab/gitlab-runner            0.71.0          17.6.0          GitLab Runner
gitlab/gitlab-zoekt             1.4.2           0.8.5           A Helm chart for deploying Zoekt as a search en...
gitlab/kubernetes-gitlab-demo   0.1.29                          GitLab running on Kubernetes suitable for demos
gitlab/apparmor                 0.2.0           0.1.0           AppArmor profile loader for Kubernetes
gitlab/auto-deploy-app          0.8.1                           GitLab's Auto-deploy Helm Chart
gitlab/elastic-stack            3.0.0           7.6.2           A Helm chart for Elastic Stack
gitlab/fluentd-elasticsearch    6.2.8           2.8.0           A Fluentd Helm chart for Kubernetes with Elasti...
gitlab/knative                  0.10.0          0.9.0           A Helm chart for Knative
gitlab/plantuml                 0.1.17          1.0             PlantUML server

Helm Chart Master Values
#

The Helm chart master values look like this:

# GitLab vlaues
https://gitlab.com/gitlab-org/charts/gitlab/-/blob/master/values.yaml?ref_type=heads

# GitLab Runner values
https://gitlab.com/gitlab-org/charts/gitlab-runner/-/blob/main/values.yaml?ref_type=heads

GitLab Installation
#

Create Namespace
#

# Create a namespace with the name "gitlab"
kubectl create ns gitlab

Kubernetes TLS Certificate Secret
#

  • In this setup I’m using a Let’s Encrypt wildcard certificate.

  • The same certificate is used for GitLab, GitLab Pages & the GitLab Shell, it includes the follwoign domain names *.gitlab-pages.jklug.work and *.jklug.work.

# Create a Kubernetes secret for the TLS certificate
kubectl create secret tls gitlab-tls --cert=./fullchain.pem --key=./privkey.pem -n gitlab

Adapt Helm Chart Values
#

# Create a configuration for the Helm chart values
vi gitlab-values.yaml
global:
  edition: ce  # GitLab Cummunity Edition
  hosts:
    domain: jklug.work
    https: true
    externalIP: 192.168.30.200  # Nginx Ingress / MetalLB virtual IP
    gitlab:
      name: gitlab.jklug.work
      https: true
    ssh:
      name: 192.168.30.201  # Set the SSH LoadBalancer IP
      port: 22              # Default SSH port
    registry:
      name: gitlab-registry.jklug.work
      https: true
    pages:
      name: gitlab-pages.jklug.work
      https: true
      externalHttps: 443
      localStore:
        enabled: true
    ssh: gitlab-shell.jklug.work
  pages:
    enabled: true  # Enable GitLab Pages
    tls:
      enabled: true
      secretName: gitlab-tls  # Kubernetes TLS Certificate Secret
  # Nginx Ingress Configuration
  ingress:
    configureCertmanager: false
    useNewIngressForCerts: false
    provider: nginx
    class: "nginx"
    annotations: {}
    enabled: true
    tls:
      enabled: true
      secretName: gitlab-tls  # Kubernetes TLS Certificate Secret
    path: /
    pathType: Prefix
  # Enable MinIO
  minio:
    enabled: true

certmanager:
  install: false
nginx-ingress:
  enabled: false  # If an NGINX Ingress is already installed in the cluster
redis:
  install: true
  master:
    persistence:
      storageClass: longhorn-rwo-retain
      size: 2Gi
prometheus:
  install: false
postgresql:
  install: true
  persistence:
    storageClass: longhorn-rwo-retain
    size: 2Gi
gitlab-runner:
  install: false
registry:
  enable: true
minio:
  persistence:
    storageClass: longhorn-rwo-retain
    size: 2Gi
gitlab:
  gitaly:
    persistence:
      storageClass: longhorn-rwo-retain
      size: 10Gi
  gitlab-shell:
    service:
      type: LoadBalancer  # LoadBalancer
      externalPort: 22  # Expose on port 22

Install GitLab
#

# Dry-run
helm install --dry-run --debug gitlab gitlab/gitlab \
  --namespace gitlab \
  -f gitlab-values.yaml
# Install GitLab
helm upgrade --install gitlab gitlab/gitlab \
  --namespace gitlab \
  --timeout 400s \
  -f gitlab-values.yaml
  • --timeout If no value is specified, Helm uses a default timeout of 5 minutes (300s).
# Shell output
NAME: gitlab
LAST DEPLOYED: Sat Nov 23 18:31:27 2024
NAMESPACE: gitlab
STATUS: deployed
REVISION: 1
NOTES:
=== CRITICAL
The following charts are included for evaluation purposes only. They will not be supported by GitLab Support
for production workloads. Use Cloud Native Hybrid deployments for production. For more information visit
https://docs.gitlab.com/charts/installation/index.html#use-the-reference-architectures.
- PostgreSQL
- Redis
- Gitaly
- MinIO

=== NOTICE
The minimum required version of PostgreSQL is now 14. See https://docs.gitlab.com/charts/installation/upgrade.html for more details.
Help us improve the installation experience, let us know how we did with a 1 minute survey:https://gitlab.fra1.qualtrics.com/jfe/form/SV_6kVqZANThUQ1bZb?installation=helm&release=17-6

Verify Installation
#

Pods & Services
#

Wait around 10 min will all the pods are running, the first initialization takes a while:

# List pods in "gitlab" namespace
kubectl get pod -n gitlab

# Shell output:
NAME                                          READY   STATUS      RESTARTS        AGE
gitlab-gitaly-0                               1/1     Running     0               8m32s
gitlab-gitlab-exporter-69975567f7-4576l       1/1     Running     0               8m32s
gitlab-gitlab-shell-846d8778b8-hf5vs          1/1     Running     0               8m17s
gitlab-gitlab-shell-846d8778b8-qvdd7          1/1     Running     0               8m32s
gitlab-kas-87dc5588b-4xgsk                    1/1     Running     0               8m17s
gitlab-kas-87dc5588b-n2xm4                    1/1     Running     3 (6m58s ago)   8m32s
gitlab-migrations-5184639-xsshc               0/1     Completed   0               8m32s
gitlab-minio-56dd57d56c-kvp7m                 1/1     Running     0               8m32s
gitlab-minio-create-buckets-ad38ebb-4pc24     0/1     Completed   0               8m32s
gitlab-postgresql-0                           2/2     Running     0               8m32s
gitlab-redis-master-0                         2/2     Running     0               8m32s
gitlab-registry-54647d9684-f8ctn              1/1     Running     1 (7m4s ago)    8m32s
gitlab-registry-54647d9684-l9224              1/1     Running     0               8m17s
gitlab-sidekiq-all-in-1-v2-77dd6c77dc-kj2c2   1/1     Running     0               8m32s
gitlab-toolbox-6f44fffb5b-x9fxh               1/1     Running     0               8m32s
gitlab-webservice-default-6b4f5977cf-hlrz6    2/2     Running     1 (90s ago)     8m17s
gitlab-webservice-default-6b4f5977cf-jv7fv    2/2     Running     1 (93s ago)     8m32s
# List services in "gitlab" namespace
kubectl get svc -n gitlab

# Shell output:
NAME                          TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)                               AGE
gitlab-gitaly                 ClusterIP      None             <none>           8075/TCP,9236/TCP                     10m
gitlab-gitlab-exporter        ClusterIP      10.108.71.200    <none>           9168/TCP                              10m
gitlab-gitlab-pages           ClusterIP      10.107.120.19    <none>           8090/TCP                              10m
gitlab-gitlab-pages-metrics   ClusterIP      10.100.108.254   <none>           9235/TCP                              10m
gitlab-gitlab-shell           LoadBalancer   10.108.202.37    192.168.30.201   22:32137/TCP                          10m
gitlab-kas                    ClusterIP      10.109.238.202   <none>           8150/TCP,8153/TCP,8154/TCP,8151/TCP   10m
gitlab-minio-svc              ClusterIP      10.111.1.146     <none>           9000/TCP                              10m
gitlab-postgresql             ClusterIP      10.111.94.138    <none>           5432/TCP                              10m
gitlab-postgresql-hl          ClusterIP      None             <none>           5432/TCP                              10m
gitlab-postgresql-metrics     ClusterIP      10.104.19.244    <none>           9187/TCP                              10m
gitlab-redis-headless         ClusterIP      None             <none>           6379/TCP                              10m
gitlab-redis-master           ClusterIP      10.108.27.163    <none>           6379/TCP                              10m
gitlab-redis-metrics          ClusterIP      10.111.198.178   <none>           9121/TCP                              10m
gitlab-registry               ClusterIP      10.111.220.128   <none>           5000/TCP                              10m
gitlab-webservice-default     ClusterIP      10.98.28.130     <none>           8080/TCP,8181/TCP,8083/TCP            10m
# List Ingress in "gitlab" namespace
kubectl get ing -n gitlab

# Shell output:
NAME                        CLASS   HOSTS                        ADDRESS          PORTS     AGE
gitlab-kas                  nginx   kas.jklug.work               192.168.30.200   80, 443   10m
gitlab-minio                nginx   minio.jklug.work             192.168.30.200   80, 443   10m
gitlab-registry             nginx   gitlab-registry.jklug.work   192.168.30.200   80, 443   10m
gitlab-webservice-default   nginx   gitlab.jklug.work            192.168.30.200   80, 443   10m

PVC & PV
#

# List PersistentVolumeClaims
kubectl get pvc -n gitlab

# Shell output:
NAME                               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          VOLUMEATTRIBUTESCLASS   AGE
data-gitlab-postgresql-0           Bound    pvc-28b8b127-993a-4831-91b9-fdc54eede401   8Gi        RWO            longhorn              <unset>                 104s
gitlab-minio                       Bound    pvc-4c758be0-314b-4f3c-8946-afa8a3a4007b   2Gi        RWO            longhorn-rwo-retain   <unset>                 104s
redis-data-gitlab-redis-master-0   Bound    pvc-d4985dcd-da7d-46b5-b94c-b14c6e799b49   2Gi        RWO            longhorn-rwo-retain   <unset>                 104s
repo-data-gitlab-gitaly-0          Bound    pvc-62ec7432-7132-429a-8088-81f49c83b4da   10Gi       RWO            longhorn-rwo-retain   <unset>                 104s
# List PersistentVolumes
kubectl get pv

# Shell output:
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                     STORAGECLASS          VOLUMEATTRIBUTESCLASS   REASON   AGE
pvc-28b8b127-993a-4831-91b9-fdc54eede401   8Gi        RWO            Delete           Bound    gitlab/data-gitlab-postgresql-0           longhorn              <unset>                          113s
pvc-4c758be0-314b-4f3c-8946-afa8a3a4007b   2Gi        RWO            Retain           Bound    gitlab/gitlab-minio                       longhorn-rwo-retain   <unset>                          113s
pvc-62ec7432-7132-429a-8088-81f49c83b4da   10Gi       RWO            Retain           Bound    gitlab/repo-data-gitlab-gitaly-0          longhorn-rwo-retain   <unset>                          113s
pvc-d4985dcd-da7d-46b5-b94c-b14c6e799b49   2Gi        RWO            Retain           Bound    gitlab/redis-data-gitlab-redis-master-0   longhorn-rwo-retain   <unset>                          113s

GitLab Webinterface & Shell
#

DNS Entries for GitLab & GitLab Shell
#

# Add DNS entries for GitLab and the GitLab Shell
192.168.30.200 gitlab.jklug.work
192.168.30.201 gitlab-shell.jklug.work

Fetch Root Password
#

# Output the random generated GitLab root password
kubectl get secret gitlab-gitlab-initial-root-password -n gitlab -o jsonpath="{.data.password}" | base64 --decode ; echo

# Shell output:
lk68RxYgb3hoplbQLmOSSaewZrurIih53z9KRJ9oA7ino09D3mpCvbnmNcox2OXo

Open Webinterface
#

# Open the GitLab webinterface
https://gitlab.jklug.work/users/sign_in
# Default user:
root

# Password:
lk68RxYgb3hoplbQLmOSSaewZrurIih53z9KRJ9oA7ino09D3mpCvbnmNcox2OXo

Clone Repository via GitLab Shell
#

Use the GitLab Shell domain name to clone GitLab repositories:

# Example: Clone a GitLab repository
git clone git@gitlab-shell.jklug.work:root/example-k8s-deployment.git



CoreDNS DNS Entry
#

Edit CoreDNS ConfigMap
#

# Adopt the CoreDNS ConfigMap / configuration
kubectl edit cm coredns -n kube-system

Original

# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
data:
  Corefile: |
    .:53 {
        errors
        health {
           lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
           pods insecure
           fallthrough in-addr.arpa ip6.arpa
           ttl 30
        }
        prometheus :9153
        forward . /etc/resolv.conf {
           max_concurrent 1000
        }
        cache 30
        loop
        reload
        loadbalance
    }
kind: ConfigMap
metadata:
  creationTimestamp: "2024-11-23T11:51:59Z"
  name: coredns
  namespace: kube-system
  resourceVersion: "253"
  uid: 7780f5a2-09c9-418c-b139-43231097afe7

Add DNS entries for GitLab and the GitLab Registry:

# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
data:
  Corefile: |
    .:53 {
        errors
        health {
           lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
           pods insecure
           fallthrough in-addr.arpa ip6.arpa
           ttl 30
        }
        hosts {
            192.168.30.200 gitlab.jklug.work # Add hosts entry
            192.168.30.200 gitlab-registry.jklug.work # Add hosts entry
            fallthrough
        }
        prometheus :9153
        forward . /etc/resolv.conf {
           max_concurrent 1000
        }
        cache 30
        loop
        reload
        loadbalance
    }
kind: ConfigMap
metadata:
  creationTimestamp: "2024-11-23T11:51:59Z"
  name: coredns
  namespace: kube-system
  resourceVersion: "253"
  uid: 7780f5a2-09c9-418c-b139-43231097afe7

Test DNS Resolution
#

# Run a busybox pod and test the GitLab DNS resolution
kubectl run -i --tty --rm debug --image=busybox --restart=Never -- nslookup gitlab.jklug.work

# Shell output:
Server:         10.96.0.10
Address:        10.96.0.10:53


Name:   gitlab.jklug.work
Address: 192.168.30.200

pod "debug" deleted



GitLab Runner Installation
#

Namespace
#

# Create a "gitlab-runner" namespace for the GitLab Runner
kubectl create ns gitlab-runner

Create Runner Token
#

  • Go to: (Admin area) “CI/CD” > Runners

  • Click “New instance runner”

  • Flag the “Run untagged jobs” option

  • Add a runner description like K8s-Runner-01

  • Click “Create runner”

  • Copy the token glrt-t1_JsLwvj7nzFbAczz9CMjf


Helm Chart Values
#

# Create a configuration for the GitLab Runner values
vi runner-values.yaml
# Define GitLab URL
gitlabUrl: https://gitlab.jklug.work/
runnerRegistrationToken: glrt-t1_JsLwvj7nzFbAczz9CMjf  # Paste token
replicas: 2
runners:
  config: |
    [[runners]]
      name = "shared-runner"
      executor = "kubernetes"
      [runners.kubernetes]
        namespace = "gitlab-runner"  # Define the GitLab Runner namespace
        privileged = true
# RBAC Settings
rbac:  # Create RBAC for the GitLab Runner
  create: true
serviceAccount:  # Create a ServiceAccount
  create: true
  name: gitlab-runner

Install GitLab Runner
#

# Dry-run
helm install --dry-run --debug gitlab-runner gitlab/gitlab-runner \
  --namespace gitlab-runner \
  -f runner-values.yaml
# Install GitLab Runner
helm install gitlab-runner gitlab/gitlab-runner \
  --namespace gitlab-runner \
  -f runner-values.yaml
# Shell output:
NAME: gitlab-runner
LAST DEPLOYED: Sat Nov 23 20:56:34 2024
NAMESPACE: gitlab-runner
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Your GitLab Runner should now be registered against the GitLab instance reachable at: "https://gitlab.jklug.work/"

Runner namespace "gitlab-runner"  # Define GitLab Runner namespace was found in runners.config template.

Verify Installation
#

List Runner Pods
#

# List GitLab Runner pod
kubectl get pods -n gitlab-runner

# Shell output: (Wait till ready)
NAME                             READY   STATUS    RESTARTS   AGE
gitlab-runner-66c7845bd8-2bcbv   1/1     Running   0          3m2s
gitlab-runner-66c7845bd8-bcrhm   1/1     Running   0          3m2s
# Optional, verify the RBAC service account
kubectl describe pod gitlab-runner-66c7845bd8-2bcbv -n gitlab-runner | grep "Service Account"

# Shell output:
Service Account:  gitlab-runner

RBAC Role & RoleBinding
#

# Describe the created RBAC Role
kubectl describe role gitlab-runner -n gitlab-runner

# Shell output:
Service Account:  gitlab-runner
ubuntu@ubuntu1:~$ kubectl describe role gitlab-runner -n gitlab-runner
Name:         gitlab-runner
Labels:       app=gitlab-runner
              app.kubernetes.io/managed-by=Helm
              chart=gitlab-runner-0.71.0
              heritage=Helm
              release=gitlab-runner
Annotations:  meta.helm.sh/release-name: gitlab-runner
              meta.helm.sh/release-namespace: gitlab-runner
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  *          []                 []              [*]
# List RoleBinging
kubectl get rolebinding -n gitlab-runner

# Shell output:
gitlab-runner   Role/gitlab-runner   3m37s
# Describe the RoleBinding
kubectl describe rolebinding gitlab-runner -n gitlab-runner

# Shell output:
Name:         gitlab-runner
Labels:       app=gitlab-runner
              app.kubernetes.io/managed-by=Helm
              chart=gitlab-runner-0.71.0
              heritage=Helm
              release=gitlab-runner
Annotations:  meta.helm.sh/release-name: gitlab-runner
              meta.helm.sh/release-namespace: gitlab-runner
Role:
  Kind:  Role
  Name:  gitlab-runner
Subjects:
  Kind            Name           Namespace
  ----            ----           ---------
  ServiceAccount  gitlab-runner  gitlab-runner

GitLab Webinterface
#

Verify the GitLab Runner is online:



Example Deployment Pipeline
#

This GitLab repository demonstrates the deployment of an Nginx container to an Ubuntu-based Linux server with Docker installed at IP address 192.168.30.14

The setup serves as a simple test to ensure that both GitLab and its Runner are functioning as expected.


Deployment Server
#

Create a User for the Container Deployment
#

On the deployment servers, create a new user “gitlab-deployment” for the GitLab CI pipeline:

# Create user for the GitLab deployment
sudo adduser gitlab-deployment

# Add the user to the Docker group
sudo usermod -aG docker gitlab-deployment

GitLab Registry DNS Entry
#

Make sure the deployment server is able to resolv the domain name of the GitLab registry:

# Add the following DNS entry
192.168.30.200 gitlab.jklug.work gitlab-registry.jklug.work



Controller Node
#

Create SSH Key Pair
#

Create a SSH key pair on the controller node:

# Create SSH key pair
ssh-keygen -t rsa -b 2048

Copy SSH Key
#

Copy the public SSH key from the previously created SSH key pair to the authorized_keys file of the gitlab-deployment user on the deployment server:

# Copy the public SSH key: Specific key
ssh-copy-id -i ~/.ssh/id_rsa.pub gitlab-deployment@192.168.30.14

SSH into the deployment servers to add the fingerprint:

# SSH into deployment server
ssh gitlab-deployment@192.168.30.14

# Exit the SSH session
exit



GitLab Repository
#

File & Folder Structure
#

The file and folder structure of the GitLab repository looks like this:

GitLab-Repository
├── Dockerfile
├── .gitlab-ci.yml
├── README.md
└── website
    └── index.html

CI/CD Variable
#

Add the private SSH key from the previously created SSH key pair as variable to the GitLab repository:

  • Go to: (Project) “Settings” > “CI/CD”

  • Expand the “Variables” section

  • Click “Add variable”

  • Select “Type”: “File”

  • Unflag “Protect variable”

  • Key: ID_RSA

  • Past the private SSH key into the “Value” box (Add empty paragraph after the key)

  • Click “Add variable”


CI Pipeline Manifest
#

  • .gitlab-ci.yml
stages:
  - build
  - deploy


### Build Job
build:
  stage: build
  image: docker:20.10.16
  services:
    - name: docker:20.10.16-dind
      command:
        - "--tls=false"  # Disable TLS for Docker-in-Docker
  variables:
    DOCKER_HOST: tcp://localhost:2375
    DOCKER_TLS_CERTDIR: ""
  script:
    - docker info
    - docker build -t $CI_REGISTRY_IMAGE:latest .
    - docker tag $CI_REGISTRY_IMAGE:latest $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
    - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME

### Deploy Job
deploy_production:
  stage: deploy
  image: alpine:latest
  variables:
    IP: "192.168.30.14"
    USER: "gitlab-deployment"
  before_script:
    - apk update && apk add openssh-client
    - if [ -f "$ID_RSA" ]; then chmod og= $ID_RSA; fi
  script:
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no $USER@$IP "docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY"
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no $USER@$IP "docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME"
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no $USER@$IP "docker container rm -f website-preview || true"
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no $USER@$IP "docker run -d -p 80:80 --restart=unless-stopped --name website-preview $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME"

  only:
    - main

Dockerfile
#

FROM nginx:1.18

COPY website/index.html /usr/share/nginx/html

HTML File
#

  • website/index.html
<!DOCTYPE html>
<html>

<head>
        <title>jklug.work</title>
</head>

<body>
  <h1>Deploy from K8s based GitLab</h1>
  <p>Nginx Container</p>
</body>

</html>