Rails 線上持續整合部署(CI) 使用-Docker架構

docker-logoDocker

Docker

Docker的優點相信很多人都知道了, 並也開始導入Docker, 我們大約在半年前開始將所有的線上環境全部Docker化

早期在部署應用程式環境的時候, 並不是簡單的安裝一個程式或是相關套件等等, 才能完整的安裝一可以上線的正式環境 但是問題是並不是每次安裝都能夠順利, 例如:版本的相依問題, 等等等….

例外如果當初的應用程式是安裝在早期的作業系統上開發的 如果時過境遷, 作業系統已經升級, 相關套件也已經升級, 因為應用程式和當初開發時的一些套件都有相依性 這時要將當初的應用程式跑在當初的環境下, 會比安裝全新的更加不容易 但是如果當初將整個設定和應用程式的版號,作業系統等和相關套件做成一個Docker 這樣之後只需要執行這個Docker就可以重現當初的整個環境了 應用程式頁能正確運作了

所以發展出來的Ansibe和chef這種自動換安裝的伺服器相關套件的解決方案 但是這個個人覺得還有有一些局限性, 例如:作業系統平台不一樣 都還需要再做一些修正

Docker的出現解決了很多問題, 例如任何的作業系統只要有安裝Docker, 跑起來的結果是一樣的 代表不用再局限於安裝目標的作業系統和作業系統版本, 目前Mac,Linux和Windows都已經可以在上面運作Docker 了

他有別於以前作業系統的虛擬化,他是應用程式的虛擬化, 他在裡面包了一個很簡易的Linux的核心, 讓你感覺不出來的他和原生的應用程式跑在作業系統上有什麼差別, 因此在Docker裡面就可以將當初已經安裝的作業系統版本包含在裡面了, 例如:ubuntu14.04 LTS, 如果這個Docker 跑在CentOS上面, 其實他的整個運作就像是跑在ubuntu14.04 LTS上一樣, 因此才能做到完整的跨平台的運作

CI(Continuous integration, CI) 持續整合 CI是為了提高程式碼的品質,維持系統或是網站的穩定性, 他的核心理念就是, 當有新的程式碼被提交時, 就會自動進行一連串的自動化步驟:編譯,測試,和部署 等

如果是Compile語言的話, 就會先進行編譯看是否程式碼可以通過自動化編譯 再來就是最重要的自動化測試, 當一個新功能完成, 或是新的程式碼提交後, 很難保證 網站或是系統可以所以的功能都是在事先預料的情況下運作, 如果只是進行人工驗證, 通常會有預想不到且沒有驗證到的情況發生, 而造成網站出現沒事先預料的錯誤

因此做自動化測試將所有應該要驗證的功能都透過自動化去驗證一遍 自動化測試包含:測試每個class或是method的正確性的單元測試, 測試API是否正確運作, 整合測試等

線上Rails的Production環境, 且所有的服務都是運作在Docker上面, 該怎麼架設CI環境呢?

簡述如下: 有時間再補足

GitLab

Git版本控制是CI環境的核心

Jenkins

Jenkins && GitLab Plugins

GitLab有和Jenkins整合的Plugins 當有新的程式碼被commit時, 會自動Triger Jenkins執行自動化測試的動作

Capistrano && Docker

Capistrano是Rails的常用的自動化部屬工具

利用Capistrano自動將遠端的最新的Rails Code build一個最新的Docker

然後跑起來, 如果有自己架設 Docker registry 可以直接運行 速度會快很多

Jenkins && Capistrano 自動化部屬

利用Jenkins去呼叫Capistrano做自動化部屬

Run Auto Tesing in a clear Docker

在做自動化測試有一個很重要的要注意的地方, 就是要使用乾淨的環境進行測試 利用Jenkins Build一個乾淨且專門用於跑自動化測試的環境

[SEO]將網站改為https增加SEO和使用者的安全性

網站由於安全的意識抬頭 現在Google特別地將https提升搜尋引擎的排名 且如果是電子商務網站的站 建議還是要加上https

由於網站的整個傳輸過程都是加密的,所以會增加伺服器的加密和解密的效能負荷 但是我覺得進行這個投資還是值得

如果原先的網站是http的,但是原來的網站不想去做特別的更動設定 像說我原來的網站是用Docker架設的 但是不想去更動原來的Docker設定 要改成https的話 分享一個我覺得不錯的辦法

就是在網站前面架設一個Reverse Proxy 利用這個Reverse Proxy去做https的加密和解密

[Nginx]的ssl Reverse Proxy做法 可以參考這一篇文章 https://www.digitalocean.com/community/tutorials/how-to-configure-nginx-with-ssl-as-a-reverse-proxy-for-jenkins 這樣原先的網站就不用去做設定

如果原來的網站是用Wordpress架設的 要加上一個語法到wp-config.php

define('FORCE_SSL_ADMIN', true); // in some setups HTTP_X_FORWARDED_PROTO might contain // a comma-separated list e.g. http,https // so check for https existence if (strpos($\_SERVER['HTTP\_X_FORWARDED_PROTO'], 'https') !== false) $_SERVER['HTTPS']='on';

參考: https://codex.wordpress.org/Administration_Over_SSL

不然網站會一直進入無窮跳轉 原因是:

Reverse Proxy進來的流量轉成http進入第二層網站伺服器 但是網站伺服器的wordpress應用程式判斷目前並不是https的加密協定 因此進行跳轉到https, 然後https的流量進入Reverse Proxy之後 又轉成http進入了網站伺服器,所以繼續進行跳轉

所以上面那段語法是說明如果透過網路的http header的資料發現Reverse Proxy的那段是https的話 自動將的http轉成https,進行模擬網站伺服器的流量就是https

參考文章:

https://www.linode.com/docs/web-servers/nginx/nginx-ssl-and-tls-deployment-best-practices

線上持續整合部署(CI & CD) 使用Docker架構

CI(Continuous integration, CI) 持續整合,CI是為了提高程式碼的品質,維持系統或是網站的穩定性,他的核心理念就是,當有新的程式碼被提交時,就會自動進行一連串的自動化步驟:編譯,測試,和部署 等。

如果是Compile語言的話,就會先進行編譯看是否程式碼可以通過自動化編譯,再來就是最重要的自動化測試,當一個新功能完成,或是新的程式碼提交後,很難保證網站或是系統的功能都是在事先預料的情況下運作, 如果只是進行人工驗證, 通常會有預想不到且沒有驗證到的情況發生,而造成網站出現沒事先預料的錯誤。

因此做自動化測試將所有應該要驗證的功能都透過自動化去驗證一遍,自動化測試包含:測試每個class或是method的正確性的單元測試,測試API是否正確運作,整合測試等。

線上Rails的Production環境, 分享一下我們用Docker架設的CI環境。

1. Docker 環境

curl -sSL https://get.docker.com/ | sh

2. Docker Compose

docker compose 是Docker一個非常棒的工具,可以將docker如何運作整個寫在一個 docker-compose.yml 檔裡面。

根據設定檔啟動Docker

docker-compose up

停止Docker

docker-compose down

在ubuntu上安裝:

curl -L https://github.com/docker/compose/releases/download/1.14.0/docker-compose-`uname -s`-`uname -m`> /usr/local/bin/docker-compose` `sudo chmod +x /usr/local/bin/docker-compose

更詳細資料參考 https://docs.docker.com/compose/install/#where-to-go-next

3. GitLab Git版本控制是CI環境的核心

我們使用Gitlab來管理我們的源碼

https://github.com/sameersbn/docker-gitlab

4. Jenkins

我們用Jenkins來跑一些自動化測試的動作,完成後再在做自動化部屬

sudo docker run  -d  -p 8080:8080 \
--name jenkins  --restart=always -v /mnt/jenkins_home:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock jayqqaa12/jenkins`

ps: 這裡要注意的地方就是將運作Jenkins的Docker Contaniner裡的 docker.sock 掛載到Host的 docker.sock,這樣Jenkins的container雖然沒有安裝docker,但是也可以執行docker, 因為他直接呼叫Host的docker來執行,所以Jenkins編譯完成Docker Image會出現在Host上。

5. Jenkins && GitLab Plugins

GitLab有和Jenkins整合的Plugins,當有新的程式碼被commit時,會自動Triger Jenkins執行自動化測試的動作。

參考以下資料 https://docs.gitlab.com/ee/integration/jenkins.html

6. Jenkins 跑 自動化測試

我們的做法是gitlab當有新的個更新時,呼叫Jenkins去做一些工作。

Jenkins的工作會產生一個臨時的工作Docker,

在Docker裡面再跑一個Docker,

由這個Docker去執行自動化測試(Rspec等…),

沒問題後用個Docker跑自動化部屬。

#echo -e "[************************************************************ Run Test ************************************************************]"
docker run -e APPDIR='/app_path' -e RUN_SHELL_FILE='/app_path/test.sh' -e 
GIT_REPOSITORY_URL='ssh://app_path.git' registry.app.work:5000/docker_run_test:latest`

7.Capistrano && Docker

Capistrano是Rails的常用的自動化部屬工具,

如果自動化測試都沒問題後,由臨時的工作Docker呼叫Capistrano自動部署到線上的Server。

如果有自己架設 Docker registry 可以直接運行 速度會快很多。

Run Auto Tesing in a clear Docker

在做自動化測試有一個很重要的要注意的地方,就是要使用乾淨的環境進行測試。 所以上面的臨時的工作Docker,就是利用Jenkins Build一個乾淨且專門用於跑自動化測試和自動化測試的環境。

參考文章

  1. http://my.oschina.net/jayqqaa12/blog/633683
  2. http://www.ithome.com.tw/article/94710

系統開發SOP

SOP

  1. 和客戶確認他要做什麼東西 和客戶一起把user story寫下來

    可以由不懂技術的人員做這一塊 但是知道怎麼去用自然語言描述客戶的需求 轉成一個一個的使用者故事

  2. tecLeader 根據user story 來選擇要使用什麼樣的技術來做

    需要什麼樣的專業人員在協助和人員配置

    例如: 後端使用什麼技術 例如使用Ruby on Rails 4.2.1, Ruby 2.2.2 前端使用什麼技術 例如:RWD,bootstrap,reactjs 什麼樣風格的設計師設計出的風格是客戶所要的

  3. teamwork tool standing by (1) Redmine (2) Git Server (Github or Bitbucket or self server) (3) Staging Server

  4. tecLeader 做系統分析

  5. tecLeader 開始根據人員配置和系統分析摟的結果和案子時程 來進行開票和控管進度流程

[Rails]今天在用購物車時發現一個Session問題

Session換頁之後, 商品沒有紀錄上去

查了之後發現是 From for 在新增商品沒 CSRF的auth code沒有新增

造成對應不到Session

所以每次新增商品時 都會重新開一個Session

所以造成購物車的商品不會累加

另外

由於Session裡面存的是購物車的是一個ruby物件

所以如果用 cookie store 由於 cookie無法儲存物件

所以用cookie會失敗

這個是由在Rails 4.1 之後的更新所做的修正

可參考 1. http://guides.rubyonrails.org/upgrading_ruby_on_rails.html 2. http://blog.plataformatec.com.br/2014/04/3-features-from-rails-4-1-that-im-excited-about/

之前Rails可以將Ruby物件放在Cookie的原因是他使用了 Marshal.dump and Marshal.load 來做物件的serialized (and deserialized)

但是由於這種做法,假如hacker如果拿到你的cookie加密的key就可以從你的cookie 解密出你存在裡面的物件, 所以降低了網站的安全性

因此Rails 4.1的更新, 讓Cookie只能儲存一些簡單的資料, 例如:string, integer, hash, array等 複雜物件就無法儲存

但也不是無法儲存, 只是物件的serialized (and deserialized) 就必須自己做了