WIP
截至2026年7月5日的19.1.1版本,本文内容尚有效
以往都是在威联通NAS的LXD中部署自用的GitLab服务器用于管理个人代码。
最近换了绿联NAS,而绿联并不支持LXD,使用虚拟机又感觉太重了,所以就有了这个在Docker中部署GitLab EE的记录。
架构概要
我使用Compose进行部署,同时没有使用内置的数据库,而是连接了独立部署的PostgreSQL数据库。
不开放ssh功能,https连接通过nginx反向代理对外公开,外面套了Cloudflare的反向代理。
安装
我这次使用的是来自官方的EE版本的Docker镜像
https://hub.docker.com/layers/gitlab/gitlab-ee/latest
Gitlab安装
创建docker-compose.yaml,内容如下
存储挂载是我自己的配置,可酌情调整
services:
gitlab:
image: gitlab/gitlab-ee:18.8.4-ee.0
container_name: gitlab
restart: always
networks:
- compose
volumes:
- /volume1/docker-hdd1/gitlab/data/etc/gitlab:/etc/gitlab
- /volume1/docker-hdd1/gitlab/data/var/log/gitlab:/var/log/gitlab
- /volume1/docker-hdd1/gitlab/data/var/opt/gitlab:/var/opt/gitlab
mem_limit: 8g
networks:
compose:
external: true
Nginx反向代理配置
TODO
Cloudflare反向代理配置
TODO
Gitlab EE破解
生成密钥对和许可证
创建如下所示的ruby脚本,保存为license.rb
下面的脚本内容转载于这篇博客:https://blog.17lai.site/posts/29a820b3/
require "openssl"
require "gitlab/license"
key_pair = OpenSSL::PKey::RSA.generate(2048)
File.open("license_key", "w") { |f| f.write(key_pair.to_pem) }
public_key = key_pair.public_key
File.open("license_key.pub", "w") { |f| f.write(public_key.to_pem) }
private_key = OpenSSL::PKey::RSA.new File.read("license_key")
Gitlab::License.encryption_key = private_key
license = Gitlab::License.new
license.licensee = {
"Name" => "许可证显示的名字",
"Company" => "许可证显示的公司",
"Email" => "许可证显示的邮箱",
}
license.starts_at = Date.new(2020, 1, 1) # 开始时间
license.expires_at = Date.new(2050, 1, 1) # 结束时间
license.notify_admins_at = Date.new(2049, 12, 1)
license.notify_users_at = Date.new(2049, 12, 1)
license.block_changes_at = Date.new(2050, 1, 1)
license.restrictions = {
active_user_count: 10000,
}
puts "License:"
puts license
data = license.export
puts "Exported license:"
puts data
File.open("GitLabBV.gitlab-license", "w") { |f| f.write(data) }
public_key = OpenSSL::PKey::RSA.new File.read("license_key.pub")
Gitlab::License.encryption_key = public_key
data = File.read("GitLabBV.gitlab-license")
$license = Gitlab::License.import(data)
puts "Imported license:"
puts $license
unless $license
raise "The license is invalid."
end
if $license.restricted?(:active_user_count)
active_user_count = 10000
if active_user_count > $license.restrictions[:active_user_count]
raise "The active user count exceeds the allowed amount!"
end
end
if $license.notify_admins?
puts "The license is due to expire on #{$license.expires_at}."
end
if $license.notify_users?
puts "The license is due to expire on #{$license.expires_at}."
end
module Gitlab
class GitAccess
def check(cmd, changes = nil)
if $license.block_changes?
return build_status_object(false, "License expired")
end
end
end
end
puts "This instance of GitLab Enterprise Edition is licensed to:"
$license.licensee.each do |key, value|
puts "#{key}: #{value}"
end
if $license.expired?
puts "The license expired on #{$license.expires_at}"
elsif $license.will_expire?
puts "The license will expire on #{$license.expires_at}"
else
puts "The license will never expire."
end
执行上述脚本
ruby license.rb
可以看到生成了下面三个文件
GitLabBV.gitlab-licenselicense_keylicense_key.pub
修改Gitlab公钥
用上一个步骤生成的license_key.pub文件替换下面的文件
/opt/gitlab/embedded/service/gitlab-rails/.license_encryption_key.pub
修改Gitlab的PLAN判断处理
修改/opt/gitlab/embedded/service/gitlab-rails/ee/app/models/license.rb
文件的STARTER_PLAN为ULTIMATE_PLAN,如下图所示,约在327行。
def plan
restricted_attr(:plan).presence || STARTER_PLANULTIMATE_PLAN
end
应用上述修改
运行下面的命令,应用上面的修改。
gitlab-ctl restart
应用许可证
以管理员权限登录Gitlab网页管理后台,上传之前生成的GitLabBV.gitlab-license文件
许可证上传页面位置如下:
菜单->管理员->设置->通用->添加许可证(点击展开)->上传
.gitlab-license文件
效果如下图显示,破解成功,许可证应用成功。

备份和恢复
备份
主要数据的备份
进入gitlab容器,执行下列命令,创建一个备份
gitlab-backup create
该命令执行时间取决于数据量,可能会耗时较久
备份完成后。可以找到生成的备份文件,文件名格式如下
<unix_timestamp>_<YYYY>_<MM>_<DD>_<gitlab_version>[-ee|-ce]_gitlab_backup.tar
如下例所示,可查看生成的备份文件
root@12a71c1f583d:/# ls -l /var/opt/gitlab/backups/
total 26908488
-rw------- 1 git git 2520975360 Jul 5 11:51 1783251791_2026_07_05_18.8.4-ee_gitlab_backup.tar
-rw------- 1 git git 146 Jul 5 11:51 artifacts.tar.gz
-rw-r--r-- 1 git git 514 Jul 5 11:51 backup_information.yml
-rw------- 1 git git 147 Jul 5 11:51 builds.tar.gz
-rw------- 1 git git 146 Jul 5 11:51 ci_secure_files.tar.gz
drwxr-xr-x 2 git git 4096 Jul 5 11:43 db
-rw------- 1 git git 146 Jul 5 11:51 external_diffs.tar.gz
-rw------- 1 git git 525714 Jul 5 11:51 lfs.tar.gz
-rw------- 1 git git 146 Jul 5 11:51 packages.tar.gz
-rw------- 1 git git 155 Jul 5 11:51 pages.tar.gz
-rw------- 1 git git 294 Jul 5 11:51 registry.tar.gz
drwx------ 4 git git 4096 Jul 5 11:43 repositories
-rw------- 1 git git 146 Jul 5 11:51 terraform_state.tar.gz
-rw------- 1 git git 35044 Jul 5 11:51 uploads.tar.gz
gitlab.rb和gitlab-secrets.json文件的备份
手动备份下面的两个文件
/etc/gitlab/gitlab.rb
/etc/gitlab/gitlab-secrets.json
恢复
TODO
版本更新
如果使用了cloudflare的反向代理,在更新过程中,建议暂时关闭,等更新完成后再恢复原设置。
更新路径
使用官方提供的Upgrade Path工具,输入当前版本和更新后版本,可以得到更新过程中需要更新的中途版本。
https://gitlab-com.gitlab.io/support/toolbox/upgrade-path/
数据备份
按照上面备份部分的说明,为当前版本的应用创建一个备份。
更新程序
修改docker-compose.yaml文件,把版本号改为官方Update Path中所示的当前版本的下一个版本,如下例所示
services:
gitlab:
image: gitlab/gitlab-ee:18.8.11-ee.0
container_name: gitlab
restart: always
networks:
- compose
volumes:
- /volume1/docker-hdd1/gitlab/data/etc/gitlab:/etc/gitlab
- /volume1/docker-hdd1/gitlab/data/var/log/gitlab:/var/log/gitlab
- /volume1/docker-hdd1/gitlab/data/var/opt/gitlab:/var/opt/gitlab
mem_limit: 8g
networks:
compose:
external: true
通过compose重新部署Gitlab
容器启动后会自动进行Gitlab的更新,包括但不仅限于数据库表结构等,该流程可能耗时较长,待能够成功登录并使用Gitlab网页功能后,即为更新成功。
依次更新到目标版本
按照Upgrade Path提供的版本升级路径,依次更新版本到最终的目标版本
为了确保数据安全,建议每一次更新前都进行一次备份。
这样在某一次更新失败时,可以回退到最后一次升级成功的版本进行数据恢复。
踩坑记录
升级到19.1.1
升级到19.1.1版本时,遇到了下面的错误,无法顺利进行升级
Recipe: registry::database_migrations
* registry_database_migrations[registry] action run
================================================================================
Error executing action `run` on resource 'registry_database_migrations[registry]'
================================================================================
RuntimeError
------------
PostgreSQL did not respond before service checks were exhausted
Cookbook Trace: (most recent call first)
----------------------------------------
/opt/gitlab/embedded/cookbooks/cache/cookbooks/gitlab/libraries/helpers/pg_status_helper.rb:56:in `ready?'
/opt/gitlab/embedded/cookbooks/cache/cookbooks/gitlab/libraries/helpers/base_pg_helper.rb:28:in `is_ready?'
/opt/gitlab/embedded/cookbooks/cache/cookbooks/registry/libraries/registry_helper.rb:35:in `should_run_migrations?'
/opt/gitlab/embedded/cookbooks/cache/cookbooks/registry/recipes/database_migrations.rb:22:in `block (2 levels) in from_file'
Resource Declaration:
---------------------
# In /opt/gitlab/embedded/cookbooks/cache/cookbooks/registry/recipes/database_migrations.rb
20: registry_database_migrations 'registry' do
21: action :run
22: only_if { registry_helper.should_run_migrations? }
23: end
Compiled Resource:
------------------
# Declared in /opt/gitlab/embedded/cookbooks/cache/cookbooks/registry/recipes/database_migrations.rb:20:in `from_file'
registry_database_migrations("registry") do
action [:run]
default_guard_interpreter :default
declared_type :registry_database_migrations
cookbook_name "registry"
recipe_name "database_migrations"
only_if { #code block }
end
System Info:
------------
chef_version=18.3.0
platform=ubuntu
platform_version=24.04
ruby=ruby 3.3.11 (2026-03-26 revision 1f2d15125a) [x86_64-linux]
program_name=/opt/gitlab/embedded/bin/cinc-client
executable=/opt/gitlab/embedded/bin/cinc-client
原因和Container registry metadata database功能有关,解决方法是禁止registry的database,在gitlab.rb中添加如下配置,并重新启动容器即可解决这个报错,正常完成升级。
registry['database']['enabled'] = 'false'