寫在前面:
這兩天把公司的gitlab服務(wù)從老版本(7.12.0原茅,源碼版本)升級(jí)到了最新版(8.14.3澈蟆,docker化版本)翔忽。過(guò)程中遇到不少坑雾家,最后總算升級(jí)成功了铃彰。感覺(jué)光看官方文檔很難升級(jí)成功,還需要研究gitlab的一些實(shí)現(xiàn)機(jī)制芯咧,所以特此把過(guò)程總結(jié)記錄下來(lái)牙捉,以便日后查閱。
首先這次為什么要docker化而不采用傳統(tǒng)的升級(jí)方式敬飒,原因有兩個(gè):
第一邪铲,服務(wù)器上的老版本gitlab是通過(guò)源碼安裝的,光安裝配置的教程就有整整一頁(yè)无拗,步驟很繁瑣带到,也容易出錯(cuò)(參見(jiàn)這里)。如果哪天要換服務(wù)器英染,真不想從頭再重裝一次了揽惹。使用docker后,只需遷移數(shù)據(jù)部分到新機(jī)器上四康,再在新機(jī)器上了一鍵執(zhí)行docker-compose命令搪搏,就可以完成gitlab的遷移工作。
第二箭养,我查閱了官方文檔慕嚷,老版本升級(jí)到新版本,并沒(méi)有給出一步到位的方法,而是要一個(gè)版本一個(gè)版本的升級(jí)(參見(jiàn)這里)喝检⌒崂保看到這個(gè)列表瞬間放棄這種方式。
docker-gitlab文檔 建議先升級(jí)到8.0.5挠说,再升級(jí)到最新版澡谭,不然可能會(huì)遇到問(wèn)題。所以我的升級(jí)流程是這樣:源碼v7.14 —> docker-gitlab v8.0.5 —> docker-gitlab 最新版(8.14.3)损俭。
第一步蛙奖,備份數(shù)據(jù)
由于老版本gitlab的目錄的owner是git,需要切換到root杆兵,才有權(quán)限做備份雁仲。
[frank gitlab]$ sudo su - root
[root gitlab]$ sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
gitlab會(huì)將數(shù)據(jù)備份成一個(gè)tar文件,存放在目錄:/home/git/gitlab/tmp/backups/
第二步琐脏,將數(shù)據(jù)解壓縮到backup目錄
mkdir -p /mnt/docker/gitlab/backup
cd /mnt/docker/gitlab/backup
sudo tar xvf /home/git/gitlab/tmp/backups/1481629084_gitlab_backup.tar
會(huì)解壓出如下幾個(gè)目錄文件:
- db:存放數(shù)據(jù)庫(kù)備份文件database.sql
- repositories:存放每個(gè)git項(xiàng)目的倉(cāng)庫(kù)(repo)攒砖。每個(gè)repo被打包成為擴(kuò)展名為bundle的文件,其實(shí)質(zhì)上是個(gè)tar文件日裙。
- uploads:存放用戶上傳的圖片等文件吹艇。
- backup_information.yml:記錄了backup相關(guān)信息,數(shù)據(jù)庫(kù)昂拂,gitlab版本等受神。
如果使用gitlab提供的rake:backup:restore命令還原數(shù)據(jù),是不可行的格侯。原因比較多鼻听,首先在第一次啟動(dòng)gitlab時(shí),會(huì)做db migrate联四,但此時(shí)數(shù)據(jù)庫(kù)還沒(méi)有導(dǎo)入備份的數(shù)據(jù)庫(kù)數(shù)據(jù)呢精算。之后在做restore時(shí),db的備份文件已無(wú)法導(dǎo)入到migrate過(guò)的數(shù)據(jù)庫(kù)中了碎连,會(huì)報(bào)錯(cuò);另外repositories下git項(xiàng)目的存儲(chǔ)格式從v7.14到v8.0也發(fā)生了變化驮履,從.bundle
變成了.git
鱼辙,運(yùn)行restore的時(shí)候會(huì)提示文件格式錯(cuò)誤。
既然知道了備份的各個(gè)文件的作用玫镐,那么就可以手動(dòng)恢復(fù)倒戏。
第三步,新建并配置v8.0.5的docker-compose.yml文件
需要注意的一個(gè)問(wèn)題是恐似,docker-gitlab網(wǎng)站上并沒(méi)有8.0.5版本的tag杜跷,所以只能將docker-gitlab v8.0.4版本的docker-compose.yml文件下載下來(lái),再將文件內(nèi)gitlab image的版本修改成8.0.5-1。 docker-compose.yml文件內(nèi)配置了三個(gè)鏡像:redis
,postgresql
,gitlab
葛闷。
redis 需修改:
- volumes: 掛載的磁盤目錄憋槐,我的配置:
/mnt/docker/gitlab/redis:/var/lib/redis
postgresql需修改:
- volumes:掛載的磁盤目錄,我的配置:
/mnt/docker/gitlab/postgresql:/var/lib/postgresql
- DB_USER:數(shù)據(jù)庫(kù)名稱
- DB_PASS:數(shù)據(jù)庫(kù)密碼
gitlab需修改:
- volumes: 掛載的磁盤目錄淑趾,我的配置:
/mnt/docker/gitlab/gitlab:/home/git/data
- image:修改成 sameersbn/gitlab:8.0.5-1
- GITLAB_HOST:gitlab服務(wù)的ip地址或者域名阳仔,會(huì)顯示在gitlab的web頁(yè)面上。
- GITLAB_PORT:gitlab服務(wù)的端口號(hào)扣泊,會(huì)顯示在gitlab的web頁(yè)面上近范。填空的話是默認(rèn)值80。
- GITLAB_EMAIL等:發(fā)郵件時(shí)的顯示的一些信息延蟹。
- SMTP_ENABLED等:如果設(shè)置成true评矩,會(huì)啟用smtp郵件服務(wù)器。我使用的是qq企業(yè)郵箱阱飘,具體配置如下:
- SMTP_ENABLED=true
- SMTP_DOMAIN=qq.com
- SMTP_HOST=smtp.exmail.qq.com
- SMTP_PORT=25
- SMTP_USER=git@example.com
- SMTP_PASS=password
- SMTP_STARTTLS=true
- SMTP_AUTHENTICATION=plain
- GITLAB_BACKUPS斥杜,GITLAB_BACKUP_TIME:備份周期和備份時(shí)間。如果覺(jué)得daily周期太短俯萌,可以改成weekly果录。
- GITLAB_SECRETS_DB_KEY_BASE:64位密鑰。
第四步咐熙,數(shù)據(jù)庫(kù)恢復(fù)
將數(shù)據(jù)庫(kù)備份文件放到postgresql可訪問(wèn)到的位置:
cp /mnt/docker/gitlab/backup/db/database.sql /mnt/docker/gitlab/postgresql
database.sql注釋掉開(kāi)頭的兩行:
vi /mnt/docker/gitlab/postgresql/database.sql
// 注釋掉的語(yǔ)句
--CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
--COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
啟動(dòng)postgresql服務(wù)弱恒。
在docker-compose.yml所在目錄運(yùn)行
docker-compose up postgresql
進(jìn)入postgresql容器內(nèi):
docker exec -ti gitlab_postgresql_1 bash
運(yùn)行pgsql恢復(fù)數(shù)據(jù)庫(kù)
psql -U git -h 127.0.0.1 -d gitlabhq_production -f /var/lib/postgresql/database.sql
執(zhí)行exit
退出postgresql容器
至此,數(shù)據(jù)庫(kù)恢復(fù)完畢棋恼。
第五步返弹,將repositories目錄下的bundle文件解壓,放到以.git作為擴(kuò)展名的目錄下爪飘。
將repositories拷貝到gitlab掛載的數(shù)據(jù)目錄下义起。
mkdir /mnt/docker/gitlab/gitlab
cp -R backup/repositories /mnt/docker/gitlab/gitlab/
寫了個(gè)簡(jiǎn)單的腳本用來(lái)做bundle to .git的轉(zhuǎn)化:
#!bin/sh
if [ -d $1 ]; then
echo "begin to change .bundle to .git ..."
else
echo "$1 must be a dir"
exit 1
fi
function walk() {
echo "file path: $1"
for file in `ls $1`
do
file=$1/$file
echo $file
if test -d $file; then
walk ${file}
fi
if test -f $file && [ ${file##*.} = "bundle" ]; then
gitFile=${file%.*}".git"
echo gitFile: $gitFile
if [ ! -d $gitFile ]; then
echo "begin to unpack bundle file: $file"
echo "make dir: ${gitFile}"
mkdir -p $gitFile
tar xvf $file -C $gitFile/
echo "unpack bundle file: $file success!"
rm -rf $file
echo "bundle file removed"
fi
fi
done
}
walk $1
在repositories目錄下執(zhí)行該腳本。
cd /mnt/docker/gitlab/gitlab/repositories
sh bundle-to-git.sh
第六步师崎,拷貝uploads到gitlab數(shù)據(jù)目錄下
cp -R backup/uploads /mnt/docker/gitlab/gitlab/
第七步默终,運(yùn)行g(shù)itlab容器
docker-compose up (-d)
第八步,在瀏覽器中登錄gitlab犁罩,檢查是否一切ok齐蔽。
點(diǎn)擊項(xiàng)目,進(jìn)入詳情頁(yè)床估,如果出現(xiàn)“No repository”的提示含滴,很可能是repositories目錄下的owner和gitlab的不匹配。
運(yùn)行命令丐巫,將owner賦給gitlab的owner:
chown -R user:user repositories
如果依然有此提示谈况,需要清除一下緩存:
docker exec -ti gitlab bash
bundle exec rake cache:clear RAILS_ENV=production
另外勺美,你會(huì)發(fā)現(xiàn),項(xiàng)目概述中顯示的commit數(shù)量都為0碑韵,這顯然不正確赡茸。
修改方法是運(yùn)行更新commit數(shù)的命令:
docker exec -ti gitlab bash
bundle exec rake gitlab:update_commit_count RAILS_ENV=production
第九步,升級(jí)gitlab到最新版本(本文為8.14.3)
關(guān)閉gitlab v8.0.5容器
docker-compose stop
將docker-gitlab v8.14.3版本的docker-compose.yml模板文件下載下來(lái)泼诱,參考本文第三步進(jìn)行配置坛掠。
這里多了兩個(gè)需要配置的字段:GITLAB_SECRETS_SECRET_KEY_BASE
和GITLAB_SECRETS_OTP_KEY_BASE
, 值都必須是64位長(zhǎng)度的字符串。
啟動(dòng)gitlab v8.14.3
docker-compose up
其他問(wèn)題:
- 如果之前使用ssh的方式連接git服務(wù)治筒,更新后發(fā)現(xiàn)連接不上了屉栓,需要修改本地git的remote repo地址。這是因?yàn)閐ocker的宿主機(jī)上ssh服務(wù)一般都用的22端口耸袜,所以gitlab的ssh配置在了非22的端口上(在docker-compose.yml的GITLAB_SSH_PORT配置)友多,那么ssh的地址會(huì)多出來(lái)了“ssh://”和端口號(hào)“:10022”。如圖所示:
如果想跟原來(lái)的ssh地址保持一致堤框,除了修改docker-compose.yml的ssh端口號(hào)為22外(ports:"22:22"域滥,GITLAB_SSH_PORT不配置);還需要修改宿主機(jī)服務(wù)器端的ssh服務(wù)的端口號(hào)蜈抓,使用22以外的端口启绰。
- 使用ssh的方式拉取代碼,可能出現(xiàn)權(quán)限問(wèn)題沟使,需要在profile里將原來(lái)的ssh-key刪除再重新添加一次委可。
Cloning into 'mytest'...
Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
最后, 本文用到腳本和配置文件在我的github上可以獲取腊嗡。
--
Update 2016-12-15:
在v8.14.3版本上發(fā)現(xiàn)一個(gè)嚴(yán)重bug着倾,如果我是一個(gè)項(xiàng)目的“owner”, 往master
分支git push
會(huì)報(bào)錯(cuò)~
Franklin$ git push
Counting objects: 9, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (9/9), 4.34 KiB | 0 bytes/s, done.
Total 9 (delta 1), reused 0 (delta 0)
remote: GitLab: You are not allowed to force push code to a protected branch on this project.
To http://your.gitlab.com/proj.git
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'http://your.gitlab.com/proj.git'
查了一下燕少,原因是docker-gitlab v8.14.0之后的版本卡者,git版本升級(jí)到了2.11,而gitlab對(duì)此git版本上的git push的處理存在一些問(wèn)題客们。參見(jiàn):gitlab issue 和 docker-gitlab issue崇决。目前此問(wèn)題尚未解決,所以暫時(shí)的解決方法是把項(xiàng)目設(shè)置 protected branch
中的master的規(guī)則去掉底挫。
Update 2017-01-16:
上面的bug已經(jīng)在8.15.1以上的版本解決掉了嗽桩。撒花~