簡單介紹
禪道是國產的開源項目管理軟件,專注研發項目管理,內置需求管理、任務管理、bug管理、缺陷管理、用例管理、計划發布等功能,可以實現軟件的完整生命周期管理,我個人還是覺得很不錯的。
禪道提供了多樣化的一鍵安裝包,可以減少很多工作。我之前因為有其他的項目共存,並沒有使用一鍵安裝包,而選擇的是源碼部署。雖然配置也是簡單方便,但還是本着能懶就懶得原則,我在升級禪道的時候選擇使用 docker 的形式部署,便於之后管理。
Docker 使用 Go 語言編寫,並利用 Linux 內核的幾個特性來提供其功能。Docker 使用容器技術來提供沙箱環境,運行多個容器時,各個容器之間不受影響,安全性較高。可適用於自動化測試、打包、持續繼承和發布應用程序等多種場景。
Docker 版的 禪道內置了數據庫、 Apache 和 PHP 等運行環境,可以拿來就能用。這次也是趁着這個機會,記錄部署的經過,以便自己或看這篇文章的你有用到的時候能夠提供一點點幫助。
獲取禪道鏡像
此步驟可以省略
如果你的電腦或者服務器上已經安裝好了 Docker,可以直接使用命令行拉取禪道的 Docker 鏡像,
格式為 docker pull easysoft/zentao:[標簽]
例如拉取開源15.7.1版:
docker pull easysoft/zentao:15.7.1
標簽對應的就是禪道的版本號,具體和可以查看禪道的官網,或者 Docker Hub ( hub.docker.com/r/easysoft/zentao/tags) 所羅列出來標簽。
docker run 設置鏡像和標簽后,會先找本地是否有對應的鏡像和標簽,如果找不到會自動到 hub.docker.com 獲取鏡像回來,所以這個步驟可以省略,在直接看 運行禪道 中的命令即可。
運行禪道鏡像
等待下載完成就可以運行鏡像,也可以直接運行下面的命令:(請根據自身實際情況修改)
docker run --name [容器名] -p [主機端口]:80 -v [主機禪道目錄]:/www/zentaopms \
-v [主機mysql目錄]:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=[數據庫密碼] -d easysoft/zentao:[鏡像標簽]
- 容器名:啟動的容器名字,可隨意指定;
- 主機端口:主機端口為web訪問端口;
- 主機禪道目錄:可以不指定,但是為了方便禪道代碼、附件等數據的持久化,強烈建議指定。非升級情況需指定空目錄;
- 主機mysql目錄:可以不指定,但是為了方便禪道數據持久化,強烈建議指定。非升級情況需指定空目錄;
- 數據庫密碼: 容器內置 MySQL 用戶名為 root,默認密碼 123456,如果不修改可以不指定該變量,如果想更改密碼可以設置 MYSQL_ROOT_PASSWORD 變量來更改密碼;
- 鏡像標簽:禪道版本。
例如:
docker run --name pm -p 10086:80 -v /home/wenhsing/pm:/www/zentaopms \
-v /home/wenhsing/db:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=password -d easysoft/zentao:15.7.1
等待鏡像完成運行,會提示一串哈希值,表示鏡像已經成功運行,這個時候其實就可以訪問禪道了。
如果沒有反向代理的需求或者只是在本地部署測試之類的話,可以選擇僅 Docker 的方式運行,跳過 Nginx 的相關配置。
僅 Docker 的方式運行可以通過 IP 加端口號的形式訪問,IP 即為 Docker 所在的電腦或者服務器的 IP,端口號即為運行鏡像時設置的主機端口。
要是只部署一個禪道項目在服務器上,可以直接將主機的80端口綁定容器上,這樣可以直接使用禪道容器中已經安裝好的 Apache 提供網頁服務。
如果想要通過域名的形式訪問,先在域名商處配置域名指向 Docker 所在的主機公網 IP,接着在服務器上運行禪道鏡像時將 主機端口 設置為 80 端口,最后進入容器配置一下 Apache 的域名,應用設置后就可以通過域名的形式訪問了。
配置 Nginx
因為我自己的還有其他項目在服務器上運行,所以我繼續使用了 Nginx 的反向代理,有一說一是真的方便(_)。
這里提供簡單的 Nginx 配置示例,將數據轉發到 docker 對應的端口上,這里指定的是 10086,實際情況根據你自己設置的修改。
注意要設置轉發的請求頭信息,否則禪道無法獲取這些信息,無法進行安裝,無限重復跳轉到第一步安裝上。
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://127.0.0.1:10086;
# Fixed can not be install
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 443 ssl;
server_name localhost;
ssl on;
ssl_certificate "/cert.pem";
ssl_certificate_key "/cert.key";
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:10086;
# Fixed can not be install
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Fixed login failed
proxy_set_header REFERER $http_referer;
}
}
完成禪道安裝
很開心你能看到這里,說明你已經進入禪道安裝的尾聲了。如果你不是全新安裝的話,建議查看如何升級禪道,跳過這段,節省時間。
首先通過瀏覽器訪問禪道,如果你是僅 Docker 的方式運行禪道,就根據你自己的情況訪問 IP加端口號(80 端口的話可以省略)或者域名。如果設置了 Nginx 反向代理,訪問的地址根據 Nginx 設置的來。
禪道會檢測是否安裝,若沒有安裝會自動跳轉安裝頁面。
同意協議以及通過系統檢查之后,進入配置文件生成頁面。填寫數據庫的相關配置,注意數據庫的密碼就是 Docker 運行的時候指定的數據庫密碼,其他可以根據自身情況填寫。
確認配置信息后就到賬號相關的設置了,填寫公司名稱、管理員賬號密碼等,保存之后提示安裝成功,后面的不用我說你也知道可以登錄系統了。
問題及解決方案
Q:無法安裝,配置數據庫信息后無法進入下一步,無限跳轉到第一步安裝步驟頁面。
發現這個問題的時候,一開始是直接在容器中查看,發現沒有日志、沒有寫入文件,導致無法排查問題。
后來在本地直接運行容器,居然一路暢通無阻的完成了安裝,至此判斷了問題是在 Nginx 的轉發上。
從源碼上看,是因為 $_POST 獲取的參數為空,所以直接跳轉了安裝頁,也證實了 Nginx 的配置需要調整。
找到問題的原因之后,開始解決問題。
解決方法很簡單,在 Nginx 的端口轉發配置里面設置下面三行設置,將請求的參數一並轉發給 Docker 就好了。
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
Q: 部署的禪道在 http 下可以正常登錄,但 https 無法登錄
我其他的項目都用了 Nginx 反向代理,通過 Nginx 提供 https 服務,所以我就 cp 了一份配置文件修改成禪道的反向代理設置,結果頁面訪問到了,但是卻無法登錄。
在排查的過程中發現才發現了 http 可以使用,但是 https 無法訪問,放棄治療的我只能先用 http 的形式登錄禪道,這個問題也被我拖了一段時間,直到 N 天后的我看着域名不是 https 實在難受,於是又再次花時間看了這個問題。
經過半天的調試,查看了代碼之后發現是 禪道的 CSRF 相關問題。
對應的文件是: framework/base/router.class.php
對應的方法是: public function setSuperVars() 設置超級變量
/* Change for CSRF. */
if($this->config->framework->filterCSRF)
{
$httpType = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') ? 'https' : 'http';
if(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) and strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https') $httpType = 'https';
if(isset($_SERVER['REQUEST_SCHEME']) and strtolower($_SERVER['REQUEST_SCHEME']) == 'https') $httpType = 'https';
$httpHost = zget($_SERVER, 'HTTP_HOST', '');
$apiMode = (defined('RUN_MODE') && RUN_MODE == 'api') || isset($_GET[$this->config->sessionVar]);
if(!$apiMode && (empty($httpHost) or strpos($this->server->http_referer, "$httpType://$httpHost") !== 0)) $_FILES = $_POST = array();
}
可以看到代碼的最后最后面判斷了 HTTP 請求的 referer,如果不符合會被重置為空。
解決方法:
方法一:設置 Nginx 轉發配置
在 Nginx 轉發設置 referer 字段,將瀏覽器的 referer 傳遞給 Docker。
proxy_set_header REFERER $http_referer;
這個方法不用修改源代碼,設置好后重啟 Nginx即可,簡單方便快捷。
方法二:關閉禪道 CSRF 驗證
以交互式命令進入 Docker 容器:
docker exec -it pm /bin/bash
切換到禪道應用目錄下:
cd /var/www/zentaopms/
在 config/my.php 文件中添加:
$config->framework->filterCSRF = false;
這個方法關閉了禪道的 CSRF 驗證,相對應的會有風險,所以這個方案不是很推薦。
方法三:修改 Docker 中的禪道源代碼
打開 framework/base/router.class.php
文件
找到 CSRF 相關代碼,將最后一行注釋
// if(!$apiMode && (empty($httpHost) or strpos($this->server->http_referer, "$httpType://$httpHost") !== 0)) $_FILES = $_POST = array();
這個方法改動了源代碼,如果之后項目升級,需要重新修改,並且對應的 CSRF 驗證會受到影響。
大功告成~