Using Gitlab Container Registry

Introduction⌗
After transitioning services to Go language, the first problem we encountered was how to deploy Go project binaries. After overcoming many challenges, we’ve summarized the following deployment methods:
- Directly copying binary executables to the target server, then managing service processes through Shell scripts
- Directly copying binary executables to the target server, using predefined Service configuration files to let Systemd manage service processes
- Using Docker Images, managing service processes on a single server with Docker CLI
- Using Docker Images, implementing canary releases through container orchestration and scheduling platforms
The advantage of the first three methods is that they don’t have many requirements for infrastructure, but the disadvantages are also obvious - it’s difficult to achieve code deployment without user awareness unless third-party service registration and discovery infrastructure like Consul or ETCD is integrated into the project code.
To smoothly transition to container orchestration and scheduling, the first thing we need to do is change from traditional binary distribution to Docker Image distribution, which requires a Docker Container Registry.
For teams using Self-Hosted Gitlab for code management, Gitlab Container Registry is a good choice as it’s already built into Gitlab and only needs to be enabled through configuration.
Configuration⌗
The Gitlab service configuration directory structure is as follows:
tree -a -I .git
.
├── .env
├── .gitignore
├── README.md
└── docker-compose.yml
1 directory, 5 files
The .env
configuration is as follows:
# Gitlab external access url
EXTERNAL_URL=https://gitlab.local
# Gitlab Pages external access url
PAGES_EXTERNAL_URL=https://pages.local
# Gitlab Container Registry external access url
REGISTRY_EXTERNAL_URL=https://registry.local
# The maximum size of the log before it is rolled. A positive integer plus a modifier representing the unit of measure (k, m, or g). Defaults to 20m.
GITLAB_CONTAINER_LOG_MAX_SIZE=1024m
# SSL Certificates
# SSL_CERTIFICATE=/etc/gitlab/ssl/fullchain.cer
# SSL_CERTIFICATE_KEY=/etc/gitlab/ssl/fullchain.key
# Email configuration
EMAIL_ENABLED=true
[email protected]
EMAIL_DISPLAY_NAME=Gitlab
[email protected]
# SMTP configuration. Related settings for other service providers please refer to https://docs.gitlab.com/omnibus/settings/smtp.html#example-configurations
SMTP_ENABLE=true
SMTP_ADDRESS=smtp.example.com
SMTP_PORT=465
[email protected]
[email protected]
SMTP_DOMAIN=smtp.example.com
SMTP_AUTHENTICATION=login
SMTP_ENABLE_STARTTLS_AUTO=false
SMTP_TLS=true
The docker-compose.yaml
configuration is as follows:
services:
gitlab:
image: 'gitlab/gitlab-ee:latest'
restart: no
logging:
options:
max-size: ${GITLAB_CONTAINER_LOG_MAX_SIZE}
hostname: gitlab
container_name: gitlab
networks:
- traefik
labels:
- traefik.enable=true
- traefik.http.routers.pages.tls=true
- traefik.http.routers.pages.rule=Host(`pages.local`)
- traefik.http.routers.pages.service=pages
- traefik.http.routers.pages.entrypoints=http,https
- traefik.http.routers.gitlab.tls=true
- traefik.http.routers.gitlab.rule=Host(`gitlab.local`)
- traefik.http.routers.gitlab.service=gitlab
- traefik.http.routers.gitlab.entrypoints=http,https
- traefik.http.routers.registry.tls=true
- traefik.http.routers.registry.rule=Host(`registry.local`)
- traefik.http.routers.registry.service=registry
- traefik.http.routers.registry.entrypoints=http,https
- traefik.http.services.pages.loadbalancer.server.port=80
- traefik.http.services.gitlab.loadbalancer.server.port=80
- traefik.http.services.registry.loadbalancer.server.port=5100
environment:
TZ: Asia/Shanghai
GITLAB_LOG_LEVEL: error
GITLAB_OMNIBUS_CONFIG: |
external_url '$EXTERNAL_URL';
nginx['enable'] = true;
nginx['listen_port'] = 80
nginx['listen_https'] = false
nginx['redirect_http_to_https'] = true
nginx['client_max_body_size'] = '1024m';
nginx['proxy_set_headers'] = {
"Host" => "$$http_host",
"Upgrade" => "$$http_upgrade",
"X-Real-IP" => "$$remote_addr",
"Connection" => "Upgrade",
"X-Forwarded-For" => "$$proxy_add_x_forwarded_for",
"X-Forwarded-Ssl" => "on",
"X-Forwarded-Proto" => "https"
};
registry['enable'] = true
registry_external_url '$REGISTRY_EXTERNAL_URL'
registry_nginx['listen_port'] = 5100
registry_nginx['listen_https'] = false
registry_nginx['redirect_http_to_https'] = true
registry_nginx['proxy_set_headers'] = {
"Host" => "$$http_host",
"X-Real-IP" => "$$remote_addr",
"X-Forwarded-For" => "$$proxy_add_x_forwarded_for",
"X-Forwarded-Ssl" => "on",
"X-Forwarded-Proto" => "https"
}
pages_external_url '$PAGES_EXTERNAL_URL';
gitlab_pages['enable'] = true;
gitlab_pages['listen_https'] = false;
gitlab_pages['inplace_chroot'] = true;
gitlab_pages['access_control'] = true;
pages_nginx['enable'] = true;
pages_nginx['listen_port'] = 80
pages_nginx['listen_https'] = false
pages_nginx['redirect_http_to_https'] = true
gitlab_rails['time_zone'] = 'Asia/Shanghai';
gitlab_rails['lfs_enabled'] = true;
gitlab_rails['gitlab_email_enabled'] = true;
gitlab_rails['gitlab_email_from'] = '$EMAIL_FROM';
gitlab_rails['gitlab_email_display_name'] = '$EMAIL_DISPLAY_NAME';
gitlab_rails['gitlab_email_reply_to'] = '$EMAIL_REPLY_TO';
gitlab_rails['smtp_enable'] = $SMTP_ENABLE;
gitlab_rails['smtp_address'] = '$SMTP_ADDRESS';
gitlab_rails['smtp_port'] = $SMTP_PORT;
gitlab_rails['smtp_user_name'] = '$SMTP_USER_NAME';
gitlab_rails['smtp_password'] = '$SMTP_PASSWORD';
gitlab_rails['smtp_domain'] = '$SMTP_DOMAIN';
gitlab_rails['smtp_authentication'] = '$SMTP_AUTHENTICATION';
gitlab_rails['smtp_enable_starttls_auto'] = $SMTP_ENABLE_STARTTLS_AUTO;
gitlab_rails['smtp_tls'] = $SMTP_TLS;
ports:
- "0.0.0.0:22:22"
volumes:
- gitlab-conf:/etc/gitlab
- gitlab-logs:/var/log/gitlab
- gitlab-data:/var/opt/gitlab
volumes:
gitlab-conf:
external: true
gitlab-logs:
external: true
gitlab-data:
external: true
networks:
traefik:
external: true
- Lines 12-32
labels
are used for registering reverse proxies with Traefik. - Lines 54-64 contain the configuration for enabling Gitlab Container Registry and configuring Nginx reverse proxy.
All domains I set up locally use the
.local
TLD.
Starting the Service⌗
docker compose up -d
Testing⌗
Access the Container Registry page in a Gitlab project:
Login⌗
docker login registry.local
Username: [email protected]
Password:
Login Succeeded
Note: If the domain is not publicly resolvable, you need to set up DNS or configure the
Docker Daemon
Proxy to log in normally! Replaceregistry.local
with your own domain.
Push Image⌗
Here I’ll directly tag Traefik’s official image and push it to the Gitlab Container Registry:
docker tag traefik:latest registry.local/devops/traefik:latest
docker push registry.local/devops/traefik:latest
The push refers to repository [registry.local/devops/traefik]
ef79cc9bf4db: Pushed
684de1f4a5df: Pushed
7f5495899e4d: Pushed
5f4d9fc4d98d: Pushed
latest: digest: sha256:4d7c60c1d882dafc8f0148231d836f7d1e2fef0d732daf1cd16f37d711afe689 size: 1157
Then let’s look at the Container Registry in the project, and we can see the image we just pushed:
Summary⌗
This is just the first step in service containerization. To better deploy services, we need more powerful orchestration and scheduling systems!
I hope this is helpful, Happy hacking…