0%

【Docker】透過 Jenkins 重新部屬遠端機器 Container

/images/20190430/0.jpg

前言

公司慢慢在導入 Docker 等相關 Container 技術,但因為剛起步所以很多 CI/CD 流程都還在優化建構中,前幾天為了能讓 Jenkins 順利重新部屬新版 Container 搞得焦頭爛額,乾脆把這些過程記錄下來


部屬流程

/images/20190430/1.png

這個服務是由三個 Component 來組成,分開維護開發,換句話說如果有任何一個組件更新,整個服務都需要更新並重新部屬,目前的流程是各個 Component 更新後都會觸發 CD 流程將完成品打包放到 S3。

而我這次做得線就是 Docker Image 那條,當有任何 Component 更新了都會觸發,我會將 S3 的各個 Component 最新版抓下來後整理,接著再打包一版 Build Docker Image 會需要的原料放到 S3。

接著 Jenkins 接手將 Docker Image Artifact 抓下來開始 build => push => 換掉遠端機器正在跑的 Container。


設定權限

所以第一步是釐清 Jenkins 所使用的 user 是否有執行 docker 相關指令的權限,後面都簡稱這位使用者為 ciuser

因為 docker 為 service 等級的服務,預設是 admin 才能使用相關指令,所以理所當然地馬上卡關

/images/20190430/2.png

要讓使用者有執行 docker 相關指令的權限有兩種方法

  1. 賦予該 User Admin 的權限
  2. 開一個群組,並設定 docker daemon ,賦予該群組權限

顯然 (1) 不太可能(雖然最簡單),所以這邊採取 (2) 的方法

*** Windows 上右鍵 > Computer Management**

/images/20190430/3.png

*** Local Users and Groups >> Groups **

/images/20190430/4.png

*** New Group >> 建立一個群組 >> 將 ciuser 加進去**

/images/20190430/5.png

*** 到 C:\ProgramData\docker\config 修改 daemon.json 檔案**(如果沒有這個檔案,請自己建一個)

將剛剛的群組加進去

1
2
3
{
"group": "docker-users"
}

*** 重新啟動 docker service ** (這邊需要 admin 權限)

1
2
# Powershell
$ Restart-Service docker

做到這邊你在用 ciuser 下 docker command 應該就可以動了

/images/20190430/6.png

PS. 如果還不行,請先登出 ciuser 再登入,因為將使用者加入一個群組或賦予權限,重登才會生效

到這邊應該已經打通 ciuser 可以執行 docker command 的權限了,接著在 Jenkins 設定 build 、 push Image的流程測試會發現依然錯誤

error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.40/containers/json: open //./pipe/docker_engine: The system cannot find the file specified. In the default daemon configuration on Windows, the docker client must be run elevated to connect. This error may also indicate that the docker daemon is not running.

但同樣的指令不透過 Jenkins 執行,而是用遠端登入直接執行會過,這個問題想了很久還是搞不懂為什麼,明明使用的 User 相同 …

但找到了一篇文章也提到相同的事情並提供了解決方案,主要是需要調整 docker_engine ACL 設定,但因為過程太麻煩,作者很貼心的還提供了小套件可以使用

1
2
3
4
# Powershell
$ Install-Module -Name dockeraccesshelper
$ Import-Module dockeraccesshelper
$ Add-AccountToDockerAccess "ciuser"

再次執行 Jenkins 就真的成功了


設定 Jenkins

Build Image 、 Push Image 這些流程就直接省略了,重點是最後一步怎麼觸發遠端機器更新 Container 。

Docker Compose 提供 --host ,讓你可以操作遠端機器的 Container

/images/20190430/7.png

但前提是你必須先去該機器開啟 2376 port 的防火牆,還有設定 docker daemon config,跟上面那段一樣檔案,只是上次設定的是 jenkins 機器,這次是跑 Container 的機器

路徑 : C:\ProgramData\docker\config\daemon.json

1
2
3
{
"hosts": ["tcp://0.0.0.0:2376", "npipe://"]
}

都開好後回頭在 Jenkins 的流程中埋下最後一段

1
2
3
$ docker-compose -H machineIp:2376 pull

$ docker-compose -H machineIp:2376 up -d

結語

雖然只是短短的一篇,但是整個設定的過程其實卡很久,尤其是 windows 的權限不是很熟常常會把自己搞得很亂,但為了團隊能接手維運,這些過程又勢必有人需要去踩過一次,以前都覺得 DevOps 的 Dev 才是主力(自己大部分經歷也都是待在開發團隊),對於維運一直都沒有很深入去了解並感受他們的痛。

但當角色從 Developer 漸漸轉成 Infra ,不同的角度去看這些事情有了完全不同的感受,維運真的才是整個軟體生命週期佔最大的部分,一套系統你可能開發個 1 ~ 3 年,但產品的維運可能是數十年,怎麼讓一套機制落地,讓人為介入越少越好,要考慮的面向真的比過去單純開發差非常多,果然還有得學阿。