軟件環境:
- CentOS 7.0
- Docker 18.06.0-ce
以下爲採用docker鏡像
- Mysql 5.7
- Gerrit 2.15.3
- Nginx 1.15.2-alpine
假定當前服務器ip地址爲(以上3個軟件都在同一個服務器)
192.168.0.1
注:在使用docker鏡像時,強烈建議固定容器的鏡像版本號,不要用 lastest。
這樣可以保證在任何環境下都能正確運行,因爲不同版本的鏡像可能配置不一樣。此處本人也入坑良久。
本地目錄結構(包含 mysql gerrit nginx 3個軟件的配置目錄):
├── docker-compose.yml
├── gerrit
│ └── review_site
├── mysql
│ └── db
└── nginx
├── logs
└── nginx.conf
1. 配置 docker-compose.yml 文件:
首先配置 Gerrit 與 Mysql,Nginx稍後再配置:
version: "3"
services:
db:
image: "mysql:5.7"
ports:
- "3306:3306"
restart: always
volumes:
- /data/mysql/db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=XXXX
gerrit:
depends_on:
- db
image: "openfrontier/gerrit:2.15.3"
ports:
- "29418:29418"
- "8080:8080"
volumes:
- /data/gerrit/review_site:/var/gerrit/review_site
environment:
- AUTH_TYPE=HTTP
- WEBURL=http://192.168.0.1:8080
- DATABASE_TYPE=mysql
- DATABASE_HOSTNAME=db
- DATABASE_PORT=3306
- DATABASE_DATABASE=gerrit
- DATABASE_USERNAME=gerrit
- DATABASE_PASSWORD=gerrit
2. 優先啓動 db 數據庫容器:
此處必須要優先啓動 Mysql 數據庫,因爲需要創建 gerrit 數據庫以及操作 gerrit 數據庫的賬號
$ docker-compose up db
3. 配置數據庫:
數據庫容器啓動後先以root賬號進入容器:
$ docker-compose up db
容器名稱可以通過 docker-compose ps 查看
以root賬號進入mysql控制檯
root@d73a4491dba4:/# mysql -u root -p
創建 gerrit 數據庫並設置字符集 utf-8
mysql> CREATE database 數據庫名 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
創建 gerrit 賬號及密碼(名稱自己定義,主要爲gerrit數據庫訪問用)並設置訪問gerrit數據庫權限
此處,爲方便測試,我設置數據庫,賬號,密碼都爲 gerrit
mysql> grant all privileges on gerrit.* to gerrit@'%' identified by 'gerrit';
立即刷新權限
mysql> flush privileges;
新版本的 mysql , timestamp默認值的問題需要手動配置一下,本地測試如果不設置,gerrit創建表的時候總是報錯
Exception in thread "main" com.google.gwtorm.server.OrmException: Cannot apply SQL
CREATE TABLE account_group_members_audit (
added_by INT DEFAULT 0 NOT NULL,
removed_by INT,
removed_on TIMESTAMP NULL DEFAULT NULL,
account_id INT DEFAULT 0 NOT NULL,
group_id INT DEFAULT 0 NOT NULL,
added_on TIMESTAMP NOT NULL
,PRIMARY KEY(account_id,group_id,added_on)
)
at com.google.gwtorm.jdbc.JdbcExecutor.execute(JdbcExecutor.java:44)
at com.google.gwtorm.jdbc.JdbcSchema.createRelations(JdbcSchema.java:134)
at com.google.gwtorm.jdbc.JdbcSchema.updateSchema(JdbcSchema.java:104)
at com.google.gerrit.server.schema.SchemaCreator.create(SchemaCreator.java:81)
at com.google.gerrit.server.schema.SchemaUpdater.update(SchemaUpdater.java:108)
at com.google.gerrit.pgm.init.BaseInit$SiteRun.upgradeSchema(BaseInit.java:386)
at com.google.gerrit.pgm.init.BaseInit.run(BaseInit.java:143)
at com.google.gerrit.pgm.util.AbstractProgram.main(AbstractProgram.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.google.gerrit.launcher.GerritLauncher.invokeProgram(GerritLauncher.java:204)
at com.google.gerrit.launcher.GerritLauncher.mainImpl(GerritLauncher.java:108)
at com.google.gerrit.launcher.GerritLauncher.main(GerritLauncher.java:63)
at Main.main(Main.java:24)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Invalid default value for 'added_on'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
at com.mysql.jdbc.Util.getInstance(Util.java:408)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:943)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3909)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2527)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2680)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2497)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2455)
at com.mysql.jdbc.StatementImpl.executeInternal(StatementImpl.java:839)
at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:739)
at com.google.gwtorm.jdbc.JdbcExecutor.execute(JdbcExecutor.java:42)
... 15 more
此時可通過如下方式解決:使用 MySQL root 用戶登錄,設置 set global explicit_defaults_for_timestamp=1;,像下面這樣:
mysql> set global explicit_defaults_for_timestamp=1;
數據庫配置完成,退出
mysql> exit
4. 可以啓動gerrit了
$ docker-compose up gerrit
若出現以下字樣,則表示gerrit啓動成功
[main] INFO org.eclipse.jetty.server.Server : Started @22467ms
[main] INFO com.google.gerrit.pgm.Daemon : Gerrit Code Review 2.15.3 ready
5. 由於我們採用 HTTP 認證方式,因此需要配置反向代理:
a. 首先配置 docker-compose.yml 文件,在gerrit service下修改內容:
增加環境變量:HTTPD_LISTENURL=proxy-http://*:8080/
修改環境變量:WEBURL=http://192.168.0.1:8080 爲 WEBURL=http://192.168.0.1
即去掉端口號
如下:
version: "3"
services:
db:
...
gerrit:
...
environment:
- AUTH_TYPE=HTTP
- HTTPD_LISTENURL=proxy-http://*:8080/
- WEBURL=http://192.168.0.1
...
b. 然後準備 nginx.conf 文件
該文件是 Nginx 服務器的配置文件,可以從 nginx 容器中獲取默認的配置文件,然後修改:
以下是從 Nginx 官方docker鏡像網站上的方法
$ docker run --name tmp-nginx-container -d nginx:1.15.2-alpine
$ docker cp tmp-nginx-container:/etc/nginx/nginx.conf /host/path/nginx.conf
$ docker rm -f tmp-nginx-container
/host/path/nginx.conf 這個文件就是一個默認的配置文件,我們可以直接拿來修改:
在 http 段中添加 server (add start ----- add end 之間的內容):
...
http {
#add start
server {
listen *:80;
server_name gerrit;
location / {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/passwd;
proxy_pass http://gerrit:8080/;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
}
#add end
...
}
...
解釋幾個重要的地方:
- server_name gerrit;
- proxy_pass http://gerrit:8080/;
server_name 一般來說都是指定ip地址或者域名,但此處由於我們採用的是docker容器,並且是多個容器共同運行,容器之間互聯則直接採用 docker-compose.yml 中的services 名即可,所以此處用了 gerrit
這點尤其重要,本人之前一直用ip地址,gerrit一直無法正常訪問,掉坑2天。
- auth_basic_user_file /etc/nginx/passwd;
配置 HTTP 登陸時的認證文件,該文件保存用戶賬號密碼,由 htpasswd 命令創建。
nginx.conf 文件配置好後,就放入本地 /data/nginx/nginx.conf,參考本文最開始的目錄結構說明
d. 創建認證文件 passwd
$ htpasswd -c /data/gerrit/review_site/etc/passwd 姓名
回車後輸入密碼(htpasswd命令的具體用法可以自行百度)。
e. 啓動 Nginx 容器
在 docker-compose.yml 中增加 Nginx 容器配置代碼:
nginx:
depends_on:
- gerrit
image: "nginx:1.15.2-alpine"
ports:
- "80:80"
volumes:
- /data/nginx/nginx.conf:/etc/nginx/nginx.conf
- /data/gerrit/review_site/etc/passwd:/etc/nginx/passwd
此處的 passwd 文件由htpasswd創建並保存在本地,並且用 volumes 掛載到 Nginx 容器內
然後可以啓動 Nginx 容器了:
$ docker-compose up nginx
或者停止之前的 Gerrit/Mysql 容器,然後再整個啓動:
$ docker-compose down
$ docker-compose up
啓動過程沒有錯誤則搭建成功。
客戶端(另外的機器)訪問 http://192.168.0.1
首先由 Nginx 服務器獲取並彈出輸入用戶名密碼窗口,輸入賬號密碼(上面由 htpasswd 命令創建)後,就會被Nginx轉發到 http://192.168.0.1:8080
最後,在附上 docker-compose.yml nginx.conf 的完整配置(gerrit.config 其實不需要再單獨修改,因爲在該容器運行的時候,會被 docker-compose.yml 文件中的環境變量覆蓋):
docker-compose.yml:
version: "3"
services:
db:
image: "mysql:5.7"
ports:
- "3306:3306"
restart: always
volumes:
- /data/mysql/db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=XXX
gerrit:
depends_on:
- db
image: "openfrontier/gerrit:2.15.3"
ports:
- "29418:29418"
- "8080:8080"
volumes:
- /data/gerrit/review_site:/var/gerrit/review_site
environment:
- AUTH_TYPE=HTTP
- HTTPD_LISTENURL=proxy-http://*:8080/
- WEBURL=http://192.168.0.1
- DATABASE_TYPE=mysql
- DATABASE_HOSTNAME=db
- DATABASE_PORT=3306
- DATABASE_DATABASE=gerrit
- DATABASE_USERNAME=gerrit
- DATABASE_PASSWORD=gerrit
nginx:
depends_on:
- gerrit
image: "nginx:1.15.2-alpine"
ports:
- "80:80"
volumes:
- /data/nginx/nginx.conf:/etc/nginx/nginx.conf
- /data/gerrit/review_site/etc/passwd:/etc/nginx/passwd
nginx.conf:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
#add start
server {
listen *:80;
server_name gerrit;
location / {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/passwd;
proxy_pass http://gerrit:8080/;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
}
#add end
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
上面涉及到賬號,密碼,IP地址,文件路徑的,請根據自己實際情況修改。