最近把公司的 beta
環境作了容器化,目前達到的效果是代碼提交到 gitlab
,觸發 webhook
將代碼部署到測試服務器,而後就能夠根據先後端不一樣的分支組合的域名來訪問,從而省去了每次先後端代碼都合併到 master
分支才能測試的環節。php
nginx-proxy 是一個 Docker 容器, 是實現本文解決方案的神器,只需簡單的配置,即可實現爲多個容器路由的功能。前端
docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
假設有域名 foo.bar, 使用泛域名解析將 *.foo.bar解析到當前服務器便可。node
假設有一個運行 web 服務的容器,只須要在啓動的時候加上 -e VIRTUAL_HOST=web.foo.bar
,就能夠實現對該容器的訪問了。nginx
docker run -e VIRTUAL_HOST=web.foo.bar ...
注意:若是使用 docker-compose 管理多個容器的時候,docker-compose 會爲這些容器建立一個網橋,這樣會使得後來手動建立的容器無法被路由,因此這裏不建議使用 docker-compose 來管理。git
ui-for-docker 是一個基於 docker remote api 實現的 web 管理界面,雖然界面不怎麼樣,可是基本上經常使用的功能已經實現了,前端使用 angular 實現,能夠根據本身的需求做修改。github
clone 代碼web
npm install && bower installdocker
grunt run (更多操做可參看 gruntFile.js 文件)npm
使用 Gitlab 提供的 webhook 功能完成自動部署代碼,期間遇到一些問題:ubuntu
經過 webhook 的請求執行用戶是 www-data,若是要在 hook 腳本中進行文件的寫入操做是總會遇到權限問題,最暴力的辦法就是給目錄所有 777 或者在 Dockerfile 中將 www-data 用戶加入 sudo 組,而且無需輸入密碼。
echo " data-www ALL=NOPASSWD: ALL" >> /etc/sudoers
固然,正式的環境中須要對權限作嚴格控制,作到最小權限原則。
Gitlab 觸發 hook 請求以後會一直等待服務器返回 HTTP 200
的狀態碼,若是沒收到,會重複觸發 hook,若是 hook 腳本執行時間過長會致使 HTTP 請求超時,或者一次代碼提交觸發屢次部署請求,因此最後我選擇用異步的方式,hook 腳本只須要接受上線指令,寫入隊列,上線過程交給另一個腳原本完成。
爲了減小環境配置的麻煩,可使用文件隊列,php 可參考 Filefifo.php。
可將隊列目錄掛載到 webhook 容器上,便可實現容器內部寫入,主機讀取隊列(可以使用supervisor 來管理該進程),完成代碼部署的過程。
使用 supervisor 管理上線腳本進程,須要把日誌回顯到 web 界面,首先在 supervisor 的配置文件中配置好日誌路徑,而後建立一個 websocket 容器,將日誌目錄掛載到容器中,再tail 讀取日誌文件,實時顯示在 web 界面。
可參考 websocket。
下游容器將先後端環境作了分離,下降耦合度,在使用過程當中會減小一些麻煩。分離時會遇到瀏覽器同源策略的問題,可將先後端容器作互聯,而後後端容器反向代理到前端容器。
在部署代碼的時候可根據不一樣的分支將代碼部署到不一樣的目錄,而後建立容器的時候把不一樣的分支目錄掛載到不一樣的容器中,便可實現開發分支的隨意搭配。
對於一些服務,有時候只須要一個很是簡單的 web 容器就能夠,好比上面的前端容器,可是若是使用 ubuntu + nginx 的配置的時候會發現鏡像要幾百兆,很不划算,因此考慮精簡鏡像。
受這篇文章的啓發,打算本身用 go 實現一個簡單的 web 服務器,這樣 build 好的鏡像基本上只有十幾兆,可是因沒有作相關的測試,因此還不敢放在線上。
最後選擇了使用 alpine + nginx 的策略,build 以後的鏡像以後幾十兆,已經減小了不少冗餘的東西,具體可參考simple-nginx。
通過無數次踩坑和不停的折騰,終於能夠勉強使用了,固然還存在一些瑕疵,以後會慢慢修復。
感謝期間幫助過個人每一位同事。