GitLab is a web-based platform used to host Git repositories. This tool supports software development using the Continuous Delivery(CD) and Continuous Integration(CI) processes. The GitLab Enterprise Edition builds on top of Git with extra features such as LDAP group sync, multiple roles, and audit logs. It also includes authorization integration with deeper authentication.
The amazing features associated with GitLab are:
- Easy integration with Jenkins, Docker, Slack, Kubernetes, JIRA, LDAP e.t.c
- Code Quality (Code Climate)
- On-premise or cloud-based installations
- Development Analytics
- Performance monitoring
- Rich API
- Integration with IDEs like Eclipse, Visual Studio, Koding, and IntelliJ
- Issue management, bug tracking, and boards
- Repository mirroring and high availability (HA)
- Hosting static websites (GitLab Pages)
- ChatOp tool (Mattermost)
- Code Review functionality and Review Apps tool
- Service Desk (ticketing system)
The GitLab system is made up of several distinct components and dependencies. When installing GitLab directly on your system, these components are installed as well. They include Redis, Gitaly, PostgreSQL, and the GitLab application itself. To avoid these components from being populated into your environment, using Docker containers is the preferred installation method. This ensures that all the components live within a single container away from the filesystem of the host.
In this guide, we will walk through how to run GitLab in Docker Containers using Docker Compose.
Setup Pre-requisites
For this guide you need the following:
- 1GB or more of available RAM on the host
- Docker and Docker-compose
- A fully Qualified Domain name(For SSL certificates)
But before you begin, update your system and install the required tools:
## On Debian/Ubuntu
sudo apt update && sudo apt upgrade
sudo apt install curl vim git
## On RHEL/CentOS/RockyLinux 8
sudo yum -y update
sudo yum -y install curl vim git
## On Fedora
sudo dnf update
sudo dnf -y install curl vim git
#1. Install Docker and Docker Compose on Linux
Begin by installing the Docker engine on your system. Below is a dedicated guide to help you install docker on your system
Once docker has been installed, start and enable the service.
sudo systemctl start docker && sudo systemctl enable docker
Add your system user to the docker group.
sudo usermod -aG docker $USER
newgrp docker
Now proceed and install Docker compose with aid of the below guide.
Another easy way of installing Docker Dev release is with the docker.sh
script below:
sudo apt update && sudo apt install curl uidmap -y
curl -fsSL get.docker.com -o get-docker.sh
sudo sh get-docker.sh
dockerd-rootless-setuptool.sh install
#2. Provisioning the GitLab Container
We will begin by pulling the docker-compose.yml file for the deployment.
wget https://raw.githubusercontent.com/sameersbn/docker-gitlab/master/docker-compose.yml
You need to generate 3 random strings at least 64 characters long to be used for:
- GITLAB_SECRETS_OTP_KEY_BASE: this is used to encrypt 2FA secrets in the database
- GITLAB_SECRETS_DB_KEY_BASE: used for CI secret variables encryption and importing variables into the database.
- GITLAB_SECRETS_SECRET_KEY_BASE: it is used for password reset links as well as other ‘standard’ auth features.
These strings can be generated using pwgen installed as with the commands:
##On Debian/Ubuntu
sudo apt install -y pwgen
##On RHEL/CentOS/RockyLinux 8
sudo yum install epel-release -y
sudo yum install pwgen -y
## On Fedora
sudo dnf install -y pwgen
Generate random strings with the command:
pwgen -Bsv1 64
Edit the file and add the strings appropriately, the deployment file has 3 containers i.e Redis, PostgreSQL, and GitLab. Open the file for editing.
vim docker-compose.yml
Make the below changes as desired.
- PostgreSQL container
Configure your database as preferred. You need to set the database password.
......
postgresql:
restart: always
volumes:
- postgresql-data:/var/lib/postgresql:Z
environment:
- DB_USER=gitlab
- DB_PASS=StrongDBPassword
- DB_NAME=gitlab_production
- DB_EXTENSION=pg_trgm,btree_gist
......
- GitLab Container
Proceed and provide database details, and set the health check appropriately in the GitLab container.
gitlab:
restart: always
image: sameersbn/gitlab:14.10.2
depends_on:
- redis
- postgresql
ports:
- "10080:80"
- "10022:22"
volumes:
- gitlab-data:/home/git/data:Z
healthcheck:
test: curl http://localhost/-/health || exit 1
interval: 1m
timeout: 10s
retries: 3
start_period: 1m
environment:
- DEBUG=false
- DB_ADAPTER=postgresql
- DB_HOST=postgresql
- DB_PORT=5432
- DB_USER=gitlab
- DB_PASS=StrongDBPassword
- DB_NAME=gitlab_production
......
Also update Timezone variables
- TZ=Africa/Nairobi
- GITLAB_TIMEZONE=Nairobi
Under the GitLab container, you can add HTTPS support by making the below settings. If you do not have an FQDN, enable self-signed certificates as well.
- GITLAB_HTTPS=true
....
If you are using self-signed certificates, you need to enable this as well.
- SSL_SELF_SIGNED=true
Proceed and provide the random strings. Remember to set the GITLAB_HOST and remove the GITLAB_PORT. This is done because we will configure reverse proxy later.
- GITLAB_HOST=gitlab.geeksforgeeks.org
- GITLAB_PORT=
- GITLAB_SSH_PORT=10022
- GITLAB_RELATIVE_URL_ROOT=
- GITLAB_SECRETS_DB_KEY_BASE=long-and-random-alphanumeric-string
- GITLAB_SECRETS_SECRET_KEY_BASE=long-and-random-alphanumeric-string
- GITLAB_SECRETS_OTP_KEY_BASE=long-and-random-alphanumeric-string
Set the GitLab user email and password.
- GITLAB_ROOT_PASSWORD=StrongPassw0rd
- GITLAB_ROOT_EMAIL=[email protected]
You can also enable SMTP support by making the desired settings.
- SMTP_ENABLED=true
- SMTP_DOMAIN=www.example.com
- SMTP_HOST=smtp.gmail.com
- SMTP_PORT=587
- [email protected]
- SMTP_PASS=password
- SMTP_STARTTLS=true
- SMTP_AUTHENTICATION=login
There are many other configurations you can make to this container. These settings include the Timezone, OAUTH, IMAP e.t.c
#3. Configure Persistent Volumes
For data persistent, we have to map the volumes appropriately. The docker-compose.yml file has 3 volumes. Here, we will use a secondary disk mounted on our system for data persistence.
Identify the disk.
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 40G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 39G 0 part
├─rl-root 253:0 0 35G 0 lvm /
└─rl-swap 253:1 0 4G 0 lvm [SWAP]
sdb 8:16 0 10G 0 disk
└─sdb1 8:17 0 10G 0 part
Ensure the disk is formatted before you proceed to mount it as shown.
sudo mkdir /mnt/data
sudo mount /dev/sdb1 /mnt/data
Confirm if the disk has been mounted on the desired path.
$ sudo mount | grep /dev/sdb1
/dev/sdb1 on /mnt/data type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
Create the 3 volumes in the disk.
sudo mkdir -p /mnt/data/redis
sudo mkdir -p /mnt/data/postgresql
sudo mkdir -p /mnt/data/gitlab
Set the appropriate file permissions.
sudo chmod 775 -R /mnt/data
sudo chown -R $USER:docker /mnt/data
On Rhel-based systems, you need to configure SELinux as below for the paths to be accessible.
sudo setenforce 0
sudo sed -i 's/^SELINUX=.*/SELINUX=permissive/g' /etc/selinux/config
Now create the docker volumes for the containers.
- Redis
docker volume create --driver local \
--opt type=none \
--opt device=/mnt/data/redis \
--opt o=bind redis-data
- PostgreSQL
docker volume create --driver local \
--opt type=none \
--opt device=/mnt/data/postgresql \
--opt o=bind postgresql-data
- GitLab
docker volume create --driver local \
--opt type=none \
--opt device=/mnt/data/gitlab \
--opt o=bind gitlab-data
Once created, list the volumes with the command:
$ docker volume list
DRIVER VOLUME NAME
local gitlab-data
local postgresql-data
local redis-data
Now in the YAML file, add these lines at the bottom.
$ vim docker-compose.yml
.......
volumes:
redis-data:
external: true
postgresql-data:
external: true
gitlab-data:
external: true
#4. Bringing up GitLab.
After the desired configurations have been made, bring up the containers with the command:
docker-compose up -d
Sample execution output:
[+] Running 23/28
⠇ gitlab Pulling 33.9s
⠿ d5fd17ec1767 Pull complete 8.0s
⠿ 2cbc1a21dc95 Pull complete 9.3s
⠿ e3cf021c7259 Pull complete 25.0s
⠿ c55daad7c782 Pull complete 25.2s
.....
⠿ redis Pulled 24.4s
⠿ 1fe172e4850f Pull complete 17.6s
⠿ 6fbcd347bf99 Pull complete 18.1s
⠿ 993114c67627 Pull complete 18.9s
⠿ 2a560260ca39 Pull complete 20.5s
⠿ b7179886a292 Pull complete 20.8s
....
⠿ postgresql Pulled 21.4s
⠿ 23884877105a Pull complete 2.6s
⠿ bc38caa0f5b9 Pull complete 2.8s
⠿ 2910811b6c42 Pull complete 3.1s
⠿ 36505266dcc6 Pull complete 3.5s
........
Verify if the containers are running:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f5e238c85afb sameersbn/gitlab:14.10.2 "/sbin/entrypoint.sh…" 2 minutes ago Up 2 minutes (healthy) 443/tcp, 0.0.0.0:10022->22/tcp, :::10022->22/tcp, 0.0.0.0:10080->80/tcp, :::10080->80/tcp ubuntu-gitlab-1
c4113ccccc8a sameersbn/postgresql:12-20200524 "/sbin/entrypoint.sh" 2 minutes ago Up 2 minutes 5432/tcp ubuntu-postgresql-1
a352f63cdea5 redis:6.2.6 "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 6379/tcp ubuntu-redis-1
#5. Secure GitLab with SSL Certificates.
We need to secure the site with SSL so as to prevent unauthorized access to your data. With the GITLAB_HTTPS option enabled, you can generate certificates for your domain name. Normally, the container looks for the certificates in the volume that belongs to the GitLab container.
However, in this guide, we will configure the Nginx reverse proxy for HTTPS. First, install Nginx on your system.
##On RHEL/CentOS/Rocky Linux 8
sudo yum install nginx
##On Debian/Ubuntu
sudo apt install nginx
Create a virtual host file as shown.
sudo vim /etc/nginx/conf.d/gitlab.conf
Add the below lines to the file.
server {
listen 80;
server_name gitlab.computinforgeeks.com;
client_max_body_size 0;
chunked_transfer_encoding on;
location / {
proxy_pass http://localhost:10080/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Ssl on;
proxy_buffering off;
proxy_request_buffering off;
}
}
Save the file, restart and enable Nginx.
sudo systemctl restart nginx
sudo systemctl enable nginx
Option1 – Using Self Signed Certificate
The certificate pair is generated using openSSL
. Begin by generating the private key.
openssl genrsa -out gitlab.key 2048
Create a certificate signing request(CSR).
openssl req -new -key gitlab.key -out gitlab.csr
Sign the certificate using the CSR and private key.
openssl x509 -req -days 3650 -in gitlab.csr -signkey gitlab.key -out gitlab.crt
After this, you will have a self-signed certificate generated. For more security, you need to create more robust DHE parameters.
openssl dhparam -out dhparam.pem 2048
Now you will have 3 files, gitlab.key, gitlab.crt and dhparam.pem. Copy these files to the certificates directory.
sudo cp gitlab.crt /etc/ssl/certs/gitlab.crt
sudo mkdir -p /etc/ssl/private/
sudo cp gitlab.key /etc/ssl/private/gitlab.key
sudo cp dhparam.pem /etc/ssl/certs/dhparam.pem
Now edit your Nginx config to accommodate the certificates.
server {
server_name gitlab.geeksforgeeks.org;
client_max_body_size 0;
chunked_transfer_encoding on;
location / {
proxy_pass http://localhost:10080/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Ssl on;
proxy_buffering off;
proxy_request_buffering off;
}
listen 443 ssl;
ssl_certificate /etc/ssl/certs/gitlab.crt;
ssl_certificate_key /etc/ssl/private/gitlab.key;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
}
server {
if ($host = gitlab.geeksforgeeks.org) {
return 301 https://$host$request_uri;
}
listen 80;
server_name gitlab.geeksforgeeks.org;
return 404;
}
To establish trust with the server, the client needs to copy the gitlab.crt to the list of trusted certificates. Normally at /usr/local/share/ca-certificates/ for Ubuntu and /etc/pki/ca-trust/source/anchors/ for CentOS. Once done, update the certificates:
##On Ubuntu/Debian
sudo update-ca-certificates
##On CentOS/Rocky Linux
sudo update-ca-trust extract
This is done to avoid the error below during git clone on the client.
$ git clone https://gitlab.geeksforgeeks.org/gitlab-instance-dbda973a/my-android-project.git
Cloning into 'my-android-project'...
fatal: unable to access 'https://gitlab.geeksforgeeks.org/gitlab-instance-dbda973a/my-android-project.git/': SSL certificate problem: self signed certificate
Option 2 – Using Let’s Encrypt
This requires one to have a Fully Qualified Domain Name(FQDN). Here, we will use a reverse proxy(Nginx) Begin by installing the required packages.
##On RHEL 8/CentOS/Rocky Linux 8/Fedora
sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
sudo dnf install certbot python3-certbot-nginx
##On Debian/Ubuntu
sudo apt install certbot python3-certbot-nginx
Generate SSL certificates for your domain name using the command:
sudo certbot --nginx
Proceed and issue certificates for the domain name.
........
Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: gitlab.geeksforgeeks.org
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1
Requesting a certificate for gitlab.geeksforgeeks.org
Performing the following challenges:
http-01 challenge for bitwarden.example.com
Waiting for verification...
Cleaning up challenges
....
Restart Nginx.
sudo systemctl restart nginx
#6. Access GitLab Web UI.
Now proceed and access GitLab via HTTPS. If you have a firewall enabled, allow the port/service through it.
##For UFW
sudo ufw allow 443/tcp
##For Firewalld
sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --add-service=https --permanent
sudo firewall-cmd --reload
Now proceed and access the page using the URL https://domain_name
Login using the created credentials. On successful login, you will see this dashboard.
Set if you want the account to be used by everyone or for personal use by setting who to register for an account. Once configured, proceed and create a new project by clicking on “New Project“.
Here, I will deploy a project from a template as shown.
Once created, the project will appear as shown.
You can proceed and add SSH keys for easier management. To confirm if everything is set up accordingly, we will try and git clone the repository. Click on clone to obtain the desired URL. Since I do not have SSH keys, I will proceed to use HTTPS as shown.
Voila!
That verifies that the GitLab installation is working as preferred.
#7. Cleanup
To remove the GitLab installation and all the persistent data, use the command:
$ docker-compose down -v
[+] Running 4/4
⠿ Container admin-gitlab-1 Removed 13.5s
⠿ Container admin-redis-1 Removed 0.7s
⠿ Container admin-postgresql-1 Removed 0.5s
⠿ Network admin_default Removed 0.4s
Closing Thoughts.
We have triumphantly walked through how to run GitLab in Docker Containers using Docker Compose. Now you have a GitLab installation from which you can host Git repositories. I hope this was significant.
See more:
Resolve “Url is blocked: Requests to the local network are not allowed” GitLab Error
Migrating GitLab from RHEL 6 TO RHEL 7/CentOS 7