Docker 部署禪道及 Nginx 反向代理設置


簡單介紹

禪道是國產的開源項目管理軟件,專注研發項目管理,內置需求管理、任務管理、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 驗證會受到影響。


大功告成~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM