GitLab and GitLab-Runner Docker Deployment

Get your own repository and CI/CD tool

GitLab and GitLab-Runner Docker Deployment

1. Background

  • The GitLab Docker images are monolithic images of GitLab running all the necessary services in a single container.
  • GitLab Runner is an application that works with GitLab CI/CD to run jobs in a pipeline.
    Recently I have some needs to automate certain build, test, and deployment pipelines. So those two services are the best options for me.

2. Pre-Requisites

  • Linux server, whether it’s AMD64 or ARM64. Note that GitLab does not have an official docker image for ARM64, but since it does have a stable alternative.
  • Docker and docker-compose installed
curl -sSL https://get.docker.com/ | sh
systemctl enable docker
curl -L https://github.com/docker/compose/releases/download/1.29.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
  • Git installed
sudo apt install git
  • Since my server is of high performance and I consider it quite a waste to make it dedicated to Gitlab and Gitlab Runner only. In this case, in this article I will show you how to have multiple services running on the same server simultaneously. The web server will be Nginx and the extra service will be Sshwifty Web SSH & Telnet Client. You can have as many services as you want. This is just for demo purpose and it’s practical.

4. Nginx Configuration

4.1 nginx.conf

We will have multiple services running ports and use Nginx reverse proxy to listen port 443 with SNI feature

cd /etc/nginx
nano nginx.conf
  • Add a stream block at the bottom of nginx.conf
stream {
        map $ssl_preread_server_name $example_multi {
               	ssh.example.com ssh;
		git.henrywithu.com gitlab;
        }
        upstream ssh {
                server 127.0.0.1:20001;
        }
        upstream gitlab {
                server 127.0.0.1:20002;
        }
        server {
                listen 443      reuseport;
                listen [::]:443 reuseport;
                proxy_pass      $example_multi;
                ssl_preread     on;
        }
}

Then create two conf file for the services

4.2 ssh.conf

cd /etc/nginx/conf.d
nano ssh.conf

Sshwifty Web SSH & Telnet Client will serve on local port 127.0.0.1:20003, and monitored by Nginx on local port 127.0.0.1:20001

server {
  listen 127.0.0.1:20001 ssl http2;

  ssl_certificate       /your/path/keys/fullchain.pem;
  ssl_certificate_key   /your/path/keys/privkey.pem;
#ssl_dhparam          /your/path/dhparams.pem; #optional
#Authenticated Origin Pull is optional. Please refer to https://developers.cloudflare.com/ssl/origin/authenticated-origin-pull/
#ssl_client_certificate  /etc/ssl/origin-pull-ca.pem;
#ssl_verify_client on;
  ssl_session_timeout 1d;
  ssl_session_cache shared:MozSSL:10m;
  ssl_session_tickets off;

  proxy_read_timeout 300;
  proxy_connect_timeout 300;
  proxy_send_timeout 300;

  client_max_body_size 50G; # define your max_upload_file_size

  ssl_protocols         TLSv1.2 TLSv1.3;
  ssl_ciphers           ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
  ssl_prefer_server_ciphers off;

  server_name           ssh.example.com;
    add_header Content-Security-Policy upgrade-insecure-requests;
  location / {
    proxy_redirect off;
    proxy_pass http://127.0.0.1:20003; 
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

4.3 gitlab.conf

cd /etc/nginx/conf.d
nano gitlab.conf

Gitlab will serve on local port 127.0.0.1:20004, and monitored by Nginx on local port 127.0.0.1:20002

server {
  listen 127.0.0.1:20002 ssl http2;

  ssl_certificate       /your/path/keys/fullchain.pem;
  ssl_certificate_key   /your/path/keys/privkey.pem;
#ssl_dhparam          /your/path/dhparams.pem; #optional
#Authenticated Origin Pull is optional. Please refer to https://developers.cloudflare.com/ssl/origin/authenticated-origin-pull/
#ssl_client_certificate  /etc/ssl/origin-pull-ca.pem;
#ssl_verify_client on;
  ssl_session_timeout 1d;
  ssl_session_cache shared:MozSSL:10m;
  ssl_session_tickets off;

  proxy_read_timeout 300;
  proxy_connect_timeout 300;
  proxy_send_timeout 300;

  client_max_body_size 50G; # define your max_upload_file_size

  ssl_protocols         TLSv1.2 TLSv1.3;
  ssl_ciphers           ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
  ssl_prefer_server_ciphers off;

  server_name           gitlab.example.com;
    add_header Content-Security-Policy upgrade-insecure-requests;
  location / {
    proxy_redirect off;
    proxy_pass http://127.0.0.1:20004; 
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

4.4 httpsredirect.conf

We will only open the service port on 80, and let Nginx do the rest.

cd /etc/nginx/conf.d
nano httpsredirect.conf
server {
        listen 80;
        server_name ssh.example.com;
        if ($host = ssh.example.com) {
                return 301 https://$host$request_uri;
        }
        server_name gitlab.example.com;
        if ($host = gitlab.example.com) {
                return 301 https://$host$request_uri;
        }
        return 404;
}

4.5 Restart Nginx

nginx -t
systemctl restart nginx
systemctl enable nginx

5. Sshwifty Web SSH & Telnet Client

cd /your/path/
mkdir sshwifty && cd sshwifty
nano docker-compose.yml
version: '3.8'

services:
  sshwifty:
    image: niruix/sshwifty
    network_mode: bridge
    environment:
      - SSHWIFTY_SHAREDKEY=$$$abc123  # This is your authentication. Please do write it down
    ports:
      - 127.0.0.1:20003:8182
    restart: always
docker-compose up -d

6. GitLab

cd /your/path/
mkdir gitlab && cd gitlab
nano docker-compose.yml
version: '3.8'
services:
  web:
    image: 'yrzr/gitlab-ce-arm64v8:latest'
    restart: always
    hostname: 'gitlab.example.com'
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'http://gitlab.example.com'
        # Add any other gitlab.rb configuration here, each on its own line
    ports:
      - '127.0.0.1:20004:80'
#      - '443:443'
#      - '22:22'
    volumes:
      - './config:/etc/gitlab'
      - './logs:/var/log/gitlab'
      - './data:/var/opt/gitlab'
    shm_size: '256m'
docker-compose up -d

Now you can visit https://gitlab.example.com
You may notice that the new registration needs approval from the admin. You can get the root credential via the following:

  • Go inside the container
docker ps -a # Find the container_id of GitLab
docker exec -it <container_id> bash
cat /etc/gitlab/initial_root_password

It will show something like this:

# WARNING: This value is valid only in the following conditions
#          1. If provided manually (either via `GITLAB_ROOT_PASSWORD` environment variable or via `gitlab_rails['initial_root_password']` setting in `gitlab.rb`, it was provided before database was seeded for the first time (usually, the first reconfigure run).
#          2. Password hasn't been changed manually, either via UI or via command line.
#
#          If the password shown here doesn't work, you must reset the admin password following https://docs.gitlab.com/ee/security/reset_user_password.html#reset-your-root-password.

Password: 3WabcdefgrRC5+1Wgx4Ltj1234567ZE/fBRDCT1M=

# NOTE: This file will be automatically deleted in the first reconfigure run after 24 hours.

Note: Change the password once you login as root.

7. GitLab Runner

cd /your/path
mkdir gitlab-runner && cd gitlab-runner
nano docker-compose.yml
version: '3.8'
services:
  gitlab-runner:
    image: 'gitlab/gitlab-runner:latest'
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./config:/etc/gitlab-runner
    restart: unless-stopped
docker-compose up -d

8. Test GitLab Runner

  • Assume you already have a project created. Go to Your_Project -> Settings -> CI/CD -> Runners -> Expand -> Project Runners
  • Write down the value of Register the runner with this URL: and registration token.
    Note: The reason why I didn’t put the URL and API token directly in the docker-compose.yml as environment variables is: It feels better to bring up the container successfully first. Otherwise if the URL or token is invalid, you will have to restart the container.
  • Register the GitLab Runner
docker ps -a # Get the container_id
docker exec -it <container_id> gitlab-runner register --url https://gitlab.example.com/ --registration-token GR1234567uYfe9DcsdABCDEFGvJKG

Note: Here we will use https instead of http since we redirected port 80 to 443 in Nginx.

  • You can just hit enter (empty value) all the way down. Don’t forget to choose an executor as you like. Or you can type specific parameters yourself.
    If it is successful, you will receive message like this:
Runtime platform                                    arch=arm64 os=linux pid=407 revision=dcfb4b66 version=15.10.1
Running in system-mode.

Enter the GitLab instance URL (for example, https://gitlab.com/):
[https://gitlab.example.com/]:
Enter the registration token:
[GR1234567uYfe9DcsdABCDEFGvJKG]:
Enter a description for the runner:
[c22f4add3d1b]:
Enter tags for the runner (comma-separated):

Enter optional maintenance note for the runner:

WARNING: Support for registration tokens and runner parameters in the 'register' command has been deprecated in GitLab Runner 15.6 and will be replaced with support for authentication tokens. For more information, see https://gitlab.com/gitlab-org/gitlab/-/issues/380872
Registering runner... succeeded                     runner=GR1234561uYfe9Dcs
Enter an executor: parallels, instance, kubernetes, custom, docker, docker-ssh, docker+machine, docker-ssh+machine, shell, ssh, virtualbox:
shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

Configuration (with the authentication token) was saved in "/etc/gitlab-runner/config.toml"
  • Check the pipeline. Go to Your_Project -> CI/CD -> Pipelines. Then you can check the status.

Enjoy!

Ref:
GitLab Runner Commands


Copyright statement: Unless otherwise stated, all articles on this blog adopt the CC BY-NC-SA 4.0 license agreement. For non-commercial reprints and citations, please indicate the author: Henry, and original article URL. For commercial reprints, please contact the author for authorization.