Published on

Self-host GitLab with local runner and DockerHub

Authors
  • avatar
    Name
    PatharaNor
    Twitter

gitlab-local-runner-thumbnail

Requirements

  • gitlab-runner command (require)
  • docker command
  • DockerHub account
  • Project name (container name) in DockerHub

Note : please prepare your software or command based on your pipeline and service.

Preparation

On self-host GitLab, you need to do step below first :

  • Adding environment variables
  • Get registration token
  • Write your pipeline
  • Config your runner on local machine

Environment variables

In your project, go to Setting > CI/CD > Variables, set DockerHub account to variable below :

  • CI_REGISTRY : docker.io
  • CI_REGISTRY_IMAGE : index.docker.io/YOUR_USERNAME/YOUR_IMAGE_NAME
  • CI_REGISTRY_PASSWORD : personal access token for DockerHub's account
  • CI_REGISTRY_USER : YOUR_USERNAME

set-env-variable

Registration token

Get registration token from self-host GitLab UI (example https://SELF_HOST_URL/), go to Setting > CI/CD > Runners :

registration-token-of-gitlab-runner

GitLab pipeline

My pipeline start from :

  • Run unit test and export report to be an artifact.
  • Then build container image by using docker-in-docker(dind), for in-detail :
    • You need to specifig Docker version to prevent unknown error. In this case I used 19.03.12 (ver >18 has TLS issues).
    • To prevent the TLS issues, you need to add DOCKER_TLS_CERTDIR: "/certs" in variables.
    • You need to provide Docker service to handle your script. Your service based on container name but it must not have the same name with container image. So you just add -dind to your service.
    • I would like to build container image when run unittest success. So I set dependencies point to unittest(stageful).
    • To build container image, I need to login to my DockerHub account before run script.
    • My build script, build container image based on Dockerfile.prod file then set tag, the container version based on last hash commit and latest.
    • Push container image to DockerHub
    • Active when commit to branch main, develop.
  • Finally, in deploy stage, I just try to POC kubectl vsphere CLI only. You can custom this stage by yourself (Ref. https://github.com/patharanordev/dockerized-k8s-vsphere).
stages:
  - test
  - build
  - deploy

unittest:
  stage: test
  image: golang:latest
  script:
    - go get gotest.tools/gotestsum
    - go install gotest.tools/gotestsum
    - sh test-with-report.sh
  artifacts:
    when: always
    reports:
      junit: report.xml

build:
  stage: build
  image: docker:19.03.12
  variables:
    DOCKER_TLS_CERTDIR: '/certs'
  services:
    - docker:19.03.12-dind
  dependencies:
    - unittest
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
  script:
    - docker build -f Dockerfile.prod -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" .
    - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"
    - docker tag "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" "$CI_REGISTRY_IMAGE:latest"
    - docker push "$CI_REGISTRY_IMAGE:latest"
  only:
    - main
    - develop

deploy-job:
  stage: deploy
  image: docker:19.03.12
  dependencies:
    - build
  script:
    - echo "Preparing K8s vSphere CLI..."
    - docker run --rm -i --privileged patharanor/k8svsphere:latest kubectl vsphere --help

Ex. test result and report :

ex-unittest

Config Runner

On local machine, you can create config.toml via gitlab-runner CLI, the output file is in ~/.gitlab-runner.

In my example, I'm using docker CLI to start GitLab runner service, and adding more properties. The content should looks like this :

concurrent = 1
check_interval = 1

[session_server]
  advertise_address = "https://SELF_HOST_URL/"
  session_timeout = 1800

[[runners]]
  name = "go-runner"
  url = "https://SELF_HOST_URL/"
  id = RUNNER_ID_TYPE_NUMERIC
  token = "GENERATED_TOKEN"
  token_obtained_at = 2022-11-01T12:02:27Z
  token_expires_at = 0001-01-01T00:00:00Z
  executor = "docker"
  allowed_images = ["*/*:*"]
  allowed_services = ["*/*:*"]
  [runners.custom_build_dir]
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]
    [runners.cache.azure]
  [runners.docker]
    tls_verify = false
    image = "docker:19.03.12"
    privileged = true
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = [
      "/cache",
      "/certs/client",
      "/var/run/docker.sock:/var/run/docker.sock",
      "/YOUR_HOME_DIR/gitlab-runner/gitlab-runner/config:/etc/gitlab-runner",
      "/YOUR_HOME_DIR/.docker/daemon.json:/etc/docker/daemon.json:ro"
    ]
    shm_size = 0

For self-host GitLab, you must set advertise_address in session_server session in config.toml :

[session_server]
  advertise_address = "https://SELF_HOST_URL/"

Note:

  • To prevent
    • TLS issue, please adding /certs/client in volumes
    • Login to DockerHub issue, please adding /YOUR_HOME_DIR/.docker/daemon.json:/etc/docker/daemon.json:ro in volumes

Usage

Start GitLab container on local machine first :

$ sudo docker run -d \
--name gitlab-runner \
--restart always \
-v /YOUR_HOME_DIR/gitlab-runner/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /YOUR_HOME_DIR/.docker/daemon.json:/etc/docker/daemon.json:ro \
--privileged \
gitlab/gitlab-runner:latest

You should see your runner in Setting > CI/CD :

available-gitlab-runner

When you run pipeline via GitLab's UI :

deploy-success

your machine will execute task based on your pipeline :

$ docker logs gitlab-runner -f
Runtime platform                                    arch=amd64 os=linux pid=7 revision=0d4137b8 version=15.5.0
Starting multi-runner from /etc/gitlab-runner/config.toml...  builds=0
Running in system-mode.

Configuration loaded                                builds=0
listen_address not defined, metrics & debug endpoints disabled  builds=0
[session_server].listen_address not defined, session endpoints disabled  builds=0
Checking for jobs... received                       job=6095 repo_url=https://SELF_HOST_URL/YOUR_REPO.git runner=GENERATED_TOKEN
WARNING: Job failed: exit code 1
                   duration_s=24.2221757 job=6095 project=834 runner=GENERATED_TOKEN
WARNING: Failed to process runner                   builds=0 error=exit code 1 executor=docker runner=GENERATED_TOKEN
Checking for jobs... received                       job=6097 repo_url=https://SELF_HOST_URL/YOUR_REPO.git runner=GENERATED_TOKEN
Job succeeded                                       duration_s=25.8697165 job=6097 project=834 runner=GENERATED_TOKEN
Checking for jobs... received                       job=6098 repo_url=https://SELF_HOST_URL/YOUR_REPO.git runner=GENERATED_TOKEN
Job succeeded                                       duration_s=13.4668964 job=6098 project=834 runner=GENERATED_TOKEN

ui-compile-log

Ex. Log in build stage :

Running with gitlab-runner 15.5.0 (0d4137b8)
  on go-runner XXXXXXXX
Preparing the "docker" executor
00:40
Using Docker executor with image docker:19.03.12 ...
Starting service docker:19.03.12-dind ...
Health check container logs:
Service container logs:
YYYY-MM-DDT04:00:50.260842042Z Generating RSA private key, 4096 bit long modulus (2 primes)
YYYY-MM-DDT04:00:50.271755165Z .++++
YYYY-MM-DDT04:00:50.415336747Z ...............................++++
YYYY-MM-DDT04:00:50.415866150Z e is 65537 (0x010001)
YYYY-MM-DDT04:00:50.433703490Z Generating RSA private key, 4096 bit long modulus (2 primes)
YYYY-MM-DDT04:00:50.870233252Z ....................................................................................................++++
YYYY-MM-DDT04:00:51.129923733Z ...............................................................++++
YYYY-MM-DDT04:00:51.130399445Z e is 65537 (0x010001)
YYYY-MM-DDT04:00:51.156759413Z Signature ok
YYYY-MM-DDT04:00:51.156774411Z subject=CN = docker:dind server
YYYY-MM-DDT04:00:51.157073168Z Getting CA Private Key
YYYY-MM-DDT04:00:51.168255334Z /certs/server/cert.pem: OK
YYYY-MM-DDT04:00:51.191914706Z Signature ok
YYYY-MM-DDT04:00:51.191949288Z subject=CN = docker:dind client
YYYY-MM-DDT04:00:51.192151161Z Getting CA Private Key

...

*********
Pulling docker image docker:19.03.12 ...

...

$ docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY

...

Login Succeeded
$ docker build -f Dockerfile.prod -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" .
#1 [internal] load build definition from Dockerfile.prod
#1 ...
#19 DONE 0.1s
$ docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"
The push refers to repository ...
$ docker tag "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" "$CI_REGISTRY_IMAGE:latest"
$ docker push "$CI_REGISTRY_IMAGE:latest"
The push refers to repository ...
Cleaning up project directory and file based variables
00:00
Job succeeded

Ex. Log in deploy stage :

Running with gitlab-runner 15.5.0 (0d4137b8)
  on go-runner XXXXXXXX
Preparing the "docker" executor
00:05
Using Docker executor with image docker:19.03.12 ...
...
docker@sha256:d41efe7ad0df5a709cfd4e627c7e45104f39bbc08b1b40d7fb718c562b3ce135 ...
$ echo "Preparing K8s vSphere CLI..."
Preparing K8s vSphere CLI...
$ docker run --rm -i --privileged patharanor/k8svsphere:latest kubectl vsphere --help
vSphere Plugin for kubectl.
Usage:
  kubectl-vsphere [command]
Available Commands:
  help        Help about any command
  login       Authenticate user with vCenter Namespaces
  logout      Destroys current sessions with all vCenter Namespaces clusters.
  version     Prints the version of the plugin.
Flags:
  -h, --help                     help for kubectl-vsphere
      --request-timeout string   Request timeout for HTTP client.
  -v, --verbose int              Print verbose logging information.
Use "kubectl-vsphere [command] --help" for more information about a command.
Cleaning up project directory and file based variables
00:01
Job succeeded

Test report for GitLab

Ref. https://SELF_HOST_URL/help/ci/unit_test_reports

Issue

Enabled/Disabled TLS