This article is a howto install of the official docker gitlab-ce (GitLab Community Edition). GitLab maintains a docker image in the Docker registry and this is the best way to install GitLab.
In this article you are going to learn how:
- to install the GitLab CE in docker
- to enable HTTPS (SSL) web support to your GitLab
- to enable the docker registry functionality of GitLab
To install GitLab docker image in your Linux distribution all you need is a working docker environment and started docker daemon. As you know, installing software with docker will allow you to keep your main system clean and let you use a fined tuned installation from the official developer (creator). As mentioned already, the GitLab maintains an official GitLab image in the Docker Registry so you may expect everything to work smoothly and better than if you make an installation in a clean Linux distribution like CentOS, Ubuntu and so on. In this article, we will include the most important docker commands to control and configure the GitLab docker container and even if you are not familiar with the Docker software they are simple enough to use them and prefer this method over GitLab normal installation.
GitLab has integrated the Docker Container Registry in GitLab Container Registry and now with GitLab you can have a local Docker registry containing all project’s docker images!
Just to note, the Docker Registry is the place for the Docker (aka Linux) images.
Using GitLab Container Registry with CI/CD (continuous integration and continuous delivery) you can create automatically test, staging, development and production docker images.
STEP 1) Install and run docker.
Install and run docker service for your Linux distribution.
STEP 2) Download and run the GitLab Docker image
It’s a simple command:
sudo docker run --detach \ --hostname gitlab.mydomain.com \ --publish 443:443 --publish 80:80 --publish 1022:22 --publish 4567:4567 \ --name gitlab \ --restart always \ --volume /srv/gitlab/config:/etc/gitlab \ --volume /srv/gitlab/logs:/var/log/gitlab \ --volume /srv/gitlab/data:/var/opt/gitlab \ gitlab/gitlab-ce:latest
The docker will try to find the gitlab-ce latest version (marked with tag latest is always the latest stable GitLab release). First, it will download the official Docker GitLab image and then will run it in a new container with name “gitlab”.
- –hostname gitlab.mydomain.com – sets the hostname of the container. The hostname should point to the server hosting the docker container.
- –publish 443:443 –publish 80:80 –publish 1022:22 — publish 4567:4567 – Maps the host server ports to the docker container. So when someone access the port 80 (plain web), 443 (ssl web), 22 (ssh, used to access the git, 22 is used for the host openssh server, so we map another unused port as 1022), 4567 (docker registry) using the IP of the host server he will be redirected to the services in the docker, which listen on these posts. These ports are really difficult to change (add or remove!), so it is important to include them at frist start of this command!
- –name gitlab – the name of the docker. Each docker container has ID and name
- –volume /srv/gitlab/config:/etc/gitlab –volume /srv/gitlab/logs:/var/log/gitlab –volume /srv/gitlab/data:/var/opt/gitlab – Maps directories from the host to the docker root directory. If you remove the docker these directories will not be deleted because they are not part of the docker “root file system”.
- gitlab/gitlab-ce:latest – the docker image and the tag (aka version) in the official Docker Registry, which you want to download and run as a container in your host. Your docker will contact the offcial Docker Registry to download the image if it exists. “run” command will make a container based on this image and start the container. Here it is the offcial GitLab-ce Docker image – https://hub.docker.com/r/gitlab/gitlab-ce. Always use ONLY offcial images due to security reasons! All versions you could install are here: https://hub.docker.com/r/gitlab/gitlab-ce/tags – just replace the word “latest” from the above command with the version you like from the URL. Here we use latest and at present it points to “12.4.2-ce.0”, so all configurations and install are valid for this version (and probably for future versions, but there might be changes).
myuser@my-server-pc:~# sudo docker run --detach \ > --hostname gitlab.mydomain.com \ > --publish 443:443 --publish 80:80 --publish 1022:22 --publish 4567:4567 \ > --name gitlab \ > --restart always \ > --volume /srv/gitlab/config:/etc/gitlab \ > --volume /srv/gitlab/logs:/var/log/gitlab \ > --volume /srv/gitlab/data:/var/opt/gitlab \ > gitlab/gitlab-ce:latest Unable to find image 'gitlab/gitlab-ce:latest' locally latest: Pulling from gitlab/gitlab-ce e80174c8b43b: Pull complete d1072db285cc: Pull complete 858453671e67: Pull complete 3d07b1124f98: Pull complete 1abbbf4783f5: Pull complete 38a43d00563b: Pull complete 8bbea5a60f40: Pull complete 176bd574f7c7: Pull complete a8646c9c80ee: Pull complete 089fe821c806: Pull complete Digest: sha256:88f1bcc39aa9917ac4b19022af441b64265d50e1f0c0fa2616d29a2cb82fb41a Status: Downloaded newer image for gitlab/gitlab-ce:latest 5d025e7f93a45a50dbbaa87c55d7cdbbf6515bbe1d45ff599074f1cdcf320a0c
There is no locally copy of the needed image so it is downloaded and then a container is created with the ID=5d025e7f93a45a50dbbaa87c55d7cdbbf6515bbe1d45ff599074f1cdcf320a0c. If no error is shown in the command line output the container is successfully running. Check it with command:
myuser@my-server-pc:~# sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5d025e7f93a4 gitlab/gitlab-ce:latest "/assets/wrapper" 5 minutes ago Up 5 minutes (healthy) 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:4567->4567/tcp, 0.0.0.0:1022->22/tcp gitlab
And may take a while before the GitLab answer to querries. You can monitor the progress with
myuser@my-server-pc:~# sudo docker logs -f gitlab ..... ..... ==> /var/log/gitlab/gitlab-rails/production.log <== Started GET "/-/metrics" for 127.0.0.1 at 2019-11-11 00:18:11 +0000 Processing by MetricsController#index as HTML Completed 200 OK in 21ms (Views: 1.2ms | ActiveRecord: 0.0ms | Elasticsearch: 0.0ms) ==> /var/log/gitlab/gitlab-rails/sidekiq_exporter.log <== [2019-11-11T00:18:12.367+0000] 127.0.0.1 - - [11/Nov/2019:00:18:12 UTC] "GET /metrics HTTP/1.1" 200 11108 "-" "Prometheus/2.12.0"
STEP 3) Login as Administrator.
On the first load of http://gitlab.mydomain.com/ (OR use the IP of the host server), the GitLab web interface will offer you to change the administrator’s password. Change the password and log in with username “root” and the new password you’ve just set. The administrator’s name is “root”.
Because in many cases the gitlab.mydomain.com (or the domain you set) is not a valid domain, the SSL may not be working, open the web without the SSL – HTTP. The next step is going to install a manual singed certificate.
SCREENSHOT 1) Change the administrator’s password on first login. The default GitLab administrator’s username is “root”.
Write your new password and click on “Change your password”.
SCREENSHOT 2) Login as an administrator (use “root” for administrator’s name).
SCREENSHOT 3) This is the GitLab Welcome page.
Main activies are “Create a project”, “Create a group”, “Add people” and “Configure Gitlab”.
STEP 3) Install SSL certificate to enable HTTPS.
It is absolutely mandatory to enable and use only SSL connections to your repository. Gitlab is fully integrated with Let’s Encrypt SSL certificates, but because it is easier and in most cases, you cannot use it in an internal (closed) network or test machines and so on we preferred to show how to install manual certificate here. To install manually a certificate edit the configuration file “/etc/gitlab/gitlab.rb” with
docker exec -it gitlab editor /etc/gitlab/gitlab.rb
which will open a text editor (nano) to edit the file. Set the domain you want to use for the GitLab installation:
..... external_url "https://gitlab.mydomain.com" ..... letsencrypt['enable'] = false ..... nginx['redirect_http_to_https'] = true nginx['redirect_http_to_https_port'] = 80 ..... nginx['ssl_certificate'] = "/etc/gitlab/ssl/gitlab.mydomain.com.crt" nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/gitlab.mydomain.com.key"
Note “external_url” expect the
The line probably is commented so remove the leading “#” and set your domain. Save the configuration.
Put the private key and the certificate in /etc/gitlab/ssl/ or generate them manually with:
myuser@my-server-pc:~# sudo docker exec -it gitlab /bin/bash root@gitlab:/# . /etc/profile root@gitlab:/# mkdir /etc/gitlab/ssl/ root@gitlab:/# cd /etc/gitlab/ssl/ root@gitlab:/etc/gitlab/ssl# openssl genrsa -out gitlab.mydomain.com.key 2048 Generating RSA private key, 2048 bit long modulus (2 primes) ........................................................................................................................................................................+++++ ...............................+++++ e is 65537 (0x010001) root@gitlab:/etc/gitlab/ssl# openssl req -new -key ./gitlab.mydomain.com.key -out ./gitlab.mydomain.com.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:New York Locality Name (eg, city) []:New York Organization Name (eg, company) [Internet Widgits Pty Ltd]:Internet Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []:gitlab.mydomain.com Email Address []:admin@gitlab.mydomain.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: root@gitlab:/etc/gitlab/ssl# openssl x509 -req -days 365 -in ./gitlab.mydomain.com.csr -signkey ./gitlab.mydomain.com.key -out ./gitlab.mydomain.com.crt Signature ok subject=C = US, ST = New York, L = New York, O = Internet, CN = gitlab.mydomain.com.key, emailAddress = admin@gitlab.mydomain.com Getting Private key root@gitlab:/etc/gitlab/ssl# chmod 400 gitlab.mydomain.com.* root@gitlab:/etc/gitlab/ssl# ls -al total 20 drwxr-xr-x 2 root root 4096 Nov 11 00:36 . drwxrwxr-x 4 root root 4096 Nov 11 00:33 .. -r-------- 1 root root 1330 Nov 11 00:36 gitlab.mydomain.com.crt -r-------- 1 root root 1062 Nov 11 00:35 gitlab.mydomain.com.csr -r-------- 1 root root 1679 Nov 11 00:34 gitlab.mydomain.com.key exit
Reconfigure the GitLab instance with
myuser@my-server-pc:~# sudo docker exec -it gitlab gitlab-ctl reconfigure
After a while you’ll see some screens of information what is doing the reconfiguration:
root@my-server-pc:~# sudo docker exec -it gitlab gitlab-ctl reconfigure Starting Chef Client, version 14.13.11 resolving cookbooks for run list: ["gitlab"] Synchronizing Cookbooks: - gitlab (0.0.1) - package (0.1.0) - postgresql (0.1.0) - redis (0.1.0) - monitoring (0.1.0) - registry (0.1.0) - mattermost (0.1.0) - consul (0.1.0) - nginx (0.1.0) - runit (4.3.0) - acme (4.0.0) - gitaly (0.1.0) - praefect (0.1.0) - crond (0.1.0) - letsencrypt (0.1.0) Installing Cookbook Gems: Compiling Cookbooks... ...... ...... Recipe: monitoring::grafana * runit_service[grafana] action enable * ruby_block[restart_service] action nothing (skipped due to action :nothing) * ruby_block[restart_log_service] action nothing (skipped due to action :nothing) * ruby_block[reload_log_service] action nothing (skipped due to action :nothing) * directory[/opt/gitlab/sv/grafana] action create (up to date) * template[/opt/gitlab/sv/grafana/run] action create (up to date) * directory[/opt/gitlab/sv/grafana/log] action create (up to date) * directory[/opt/gitlab/sv/grafana/log/main] action create (up to date) * template[/opt/gitlab/sv/grafana/log/run] action create (up to date) * template[/var/log/gitlab/grafana/config] action create (up to date) * ruby_block[verify_chown_persisted_on_grafana] action nothing (skipped due to action :nothing) * directory[/opt/gitlab/sv/grafana/env] action create (up to date) * ruby_block[Delete unmanaged env files for grafana service] action run (skipped due to only_if) * template[/opt/gitlab/sv/grafana/check] action create (skipped due to only_if) * template[/opt/gitlab/sv/grafana/finish] action create (skipped due to only_if) * directory[/opt/gitlab/sv/grafana/control] action create (up to date) * link[/opt/gitlab/init/grafana] action create (up to date) * file[/opt/gitlab/sv/grafana/down] action delete (up to date) * directory[/opt/gitlab/service] action create (up to date) * link[/opt/gitlab/service/grafana] action create (up to date) * ruby_block[wait for grafana service socket] action run (skipped due to not_if) (up to date) Recipe: <Dynamically Defined Resource> * service[unicorn] action restart - restart service service[unicorn] * service[sidekiq] action restart - restart service service[sidekiq] Recipe: gitlab::gitlab-rails * execute[clear the gitlab-rails cache] action run^[[B - execute /opt/gitlab/bin/gitlab-rake cache:clear Recipe: <Dynamically Defined Resource> * service[nginx] action restart - restart service service[nginx] * service[grafana] action restart - restart service service[grafana] Running handlers: Running handlers complete Chef Client finished, 14/663 resources updated in 46 seconds gitlab Reconfigured!
There are no errors and the reconfiguration is successful. Now you may use GitLab with HTTPS. If you try to load the page with HTTP you are going to be redirected to the external URL you set before https://gitlab.mydomain.com. You can use the GitLab interface by IP, too, just use the HTTPS to be sure no redirection will happen.
STEP 4*) Enable Container Registry in the GitLab docker installation.
If you do not need Registry Container (or do not know what is it) skip this step. The port for our Docker Conatiner Registry is 4567 (the default is 5000).
Edit the GitLab configuration with:
docker exec -it gitlab editor /etc/gitlab/gitlab.rb
And change the line:
..... registry_external_url 'https://gitlab.mydomain.com:4567' ..... registry_nginx['ssl_certificate'] = "/etc/gitlab/ssl/gitlab.mydomain.com.crt" registry_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/gitlab.mydomain.com.key"
Add the last two lines if they are missing. Save the file and exit. Reconfigure the GtiLab instance with:
myuser@my-server-pc:~# sudo docker exec -it gitlab gitlab-ctl reconfigure
You should see no errors and last lines such as:
..... ..... Recipe: <Dynamically Defined Resource> * service[unicorn] action restart - restart service service[unicorn] * service[sidekiq] action restart - restart service service[sidekiq] Recipe: gitlab::gitlab-rails * execute[clear the gitlab-rails cache] action run - execute /opt/gitlab/bin/gitlab-rake cache:clear Recipe: <Dynamically Defined Resource> * service[nginx] action restart - restart service service[nginx] * service[registry] action restart - restart service service[registry] Running handlers: Running handlers complete Chef Client finished, 38/737 resources updated in 49 seconds gitlab Reconfigured!
Login in the Container Registry to see if everything is working. Because we use self-signed certificate:
myuser@my-server-pc:~# sudo mkdir -p "/etc/docker/certs.d/gitlab.mydomain.com:4567" myuser@my-server-pc:~# sudo cp /srv/gitlab/config/ssl/gitlab.mydomain.com.crt /etc/docker/certs.d/gitlab.mydomain.com\:4567/ca.crt myuser@my-server-pc:~# docker login gitlab.mydomain.com:4567 Username: root Password: WARNING! Your password will be stored unencrypted in /root/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded
Now you have your own Docker Registry you may use for your private images.
*Note: using self-signed certificate may require system-level trust, so in these cases, you should execute:
for Ubuntu:
update-ca-certificates
for Red Hat / CentOS:
update-ca-trust
Restart the Docker GitLab instance
myuser@my-server-pc:~# sudo docker restart gitlab gitlab myuser@my-server-pc:~# sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5d025e7f93a4 gitlab/gitlab-ce:latest "/assets/wrapper" 2 hours ago Up 4 seconds (health: starting) 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:4567->4567/tcp, 0.0.0.0:1022->22/tcp gitlab
You may use the container name “gitlab” or the ID (short – 5d025e7f93a4 or the full – 5d025e7f93a45a50dbbaa87c55d7cdbbf6515bbe1d45ff599074f1cdcf320a0c)
OS Information
This release of GitLab (GitLab Community Edition 12.4.2) uses Ubuntu 16.04.6 LTS:
myuser@my-server-pc:~# sudo docker exec -it gitlab /bin/bash root@gitlab:/# cat /etc/*release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=16.04 DISTRIB_CODENAME=xenial DISTRIB_DESCRIPTION="Ubuntu 16.04.6 LTS" NAME="Ubuntu" VERSION="16.04.6 LTS (Xenial Xerus)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 16.04.6 LTS" VERSION_ID="16.04" HOME_URL="http://www.ubuntu.com/" SUPPORT_URL="http://help.ubuntu.com/" BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/" VERSION_CODENAME=xenial UBUNTU_CODENAME=xenial root@gitlab:/#
Up and running GitLab-CE
Here is what you can expect to have in the Docker container with Ubuntu 18 LTS host.
root@my-server-pc:~# pstree systemd─┬─accounts-daemon───2*[{accounts-daemon}] ├─agetty ├─atd ├─containerd─┬─containerd-shim─┬─dumb-init───gitlab-runner───16*[{gitlab-runner}] │ │ └─10*[{containerd-shim}] │ ├─containerd-shim─┬─wrapper─┬─bundle─┬─6*[bundle───9*[{bundle}]] │ │ │ │ └─2*[{bundle}] │ │ │ ├─gitlab-ctl───omnibus-ctl───sh───xargs───tail │ │ │ └─runsvdir─┬─runsv─┬─sshd │ │ │ │ └─svlogd │ │ │ ├─runsv─┬─redis-server───2*[{redis-server}] │ │ │ │ └─svlogd │ │ │ ├─runsv─┬─bundle───42*[{bundle}] │ │ │ │ └─svlogd │ │ │ ├─runsv─┬─gitlab-unicorn-───sleep │ │ │ │ └─svlogd │ │ │ ├─runsv─┬─gitlab-workhors───11*[{gitlab-workhors}] │ │ │ │ └─svlogd │ │ │ ├─runsv─┬─gitaly-wrapper─┬─gitaly─┬─2*[ruby───39*[{ruby}]] │ │ │ │ │ │ └─16*[{gitaly}] │ │ │ │ │ └─8*[{gitaly-wrapper}] │ │ │ │ └─svlogd │ │ │ ├─runsv─┬─postgres───18*[postgres] │ │ │ │ └─svlogd │ │ │ ├─runsv─┬─postgres_export───7*[{postgres_export}] │ │ │ │ └─svlogd │ │ │ ├─runsv─┬─registry───10*[{registry}] │ │ │ │ └─svlogd │ │ │ ├─runsv─┬─nginx───5*[nginx] │ │ │ │ └─svlogd │ │ │ ├─runsv─┬─gitlab-exporter───5*[{gitlab-exporter}] │ │ │ │ └─svlogd │ │ │ ├─runsv─┬─gitlab-logrotat───sleep │ │ │ │ └─svlogd │ │ │ ├─runsv─┬─grafana-server───15*[{grafana-server}] │ │ │ │ └─svlogd │ │ │ ├─runsv─┬─alertmanager───12*[{alertmanager}] │ │ │ │ └─svlogd │ │ │ ├─runsv─┬─prometheus───13*[{prometheus}] │ │ │ │ └─svlogd │ │ │ └─runsv─┬─redis_exporter───9*[{redis_exporter}] │ │ │ └─svlogd │ │ └─10*[{containerd-shim}] │ └─18*[{containerd}] ├─cron ├─dbus-daemon ├─dockerd─┬─docker-proxy───6*[{docker-proxy}] │ ├─docker-proxy───7*[{docker-proxy}] │ ├─2*[docker-proxy───5*[{docker-proxy}]] │ └─26*[{dockerd}] ├─irqbalance───{irqbalance} ├─lvmetad ├─lxcfs───3*[{lxcfs}] ├─networkd-dispat───{networkd-dispat} ├─polkitd───2*[{polkitd}] ├─rsyslogd───3*[{rsyslogd}] ├─snapd───17*[{snapd}] ├─sshd───sshd───sshd───bash───sudo───su───bash───pstree ├─systemd───(sd-pam) ├─systemd-journal ├─systemd-logind ├─systemd-network ├─systemd-resolve ├─systemd-timesyn───{systemd-timesyn} ├─systemd-udevd └─unattended-upgr───{unattended-upgr}