在CircleCI上面使用多個Docker conatainer的方案

Paul Tang
5 min readDec 9, 2019

--

這是一篇筆記文,我的文筆很爛,此外我也剛開始接觸Docker,這不是教學而是有點像是踩雷心得,請加減看看,有問題歡迎指教XD

前情提要

我們公司使用CircleCI 作為CI的工具,基本上,CircleCI的使用相當簡單

綁定Github account 到CircleCI → Enable Repository in CircleCI → 撰寫CircleCI config YAML 檔 → 推到Github 上面

理論上他就會針對config裡面的步驟進行一步一步的測試和部署,關於config的撰寫,circleci提供一些 範例 ,這邊就不贅述了。

CircleCI在他們的伺服器上使用Docker container來進行測試,一旦把想要測試和部署的專案推上Github以後,他會觸發一個webhook讓CircleCI開啟一個container進行乾淨的測試和部署。

這次遇到的問題是,如果我今天想要測試一個API app,整合測試的部分一定有可能會使用到其他的服務,例如MySQL、Redis等等,這個就會有一點小小的麻煩了。

一開始我找到了CircleCI的文件,關於不同服務的整合測試,CircleCI有提供官方的 解決方案

但是如果我就是想要用Docker Compose進行測試怎麼辦?(很任性XD) 因為這樣就能直接把在Local端的測試環境直接搬上CI環境,也不用搞一堆其他有的沒的…?

總之,本篇文章主要會以在CircleCI docker環境內再創建另外一個Docker-compose的方法為主,也就是一個container裡面再有container的概念

Talk is Cheap, show me the code ?!

這邊就不囉唆,直接上circleci 的yaml config

以及我們要執行測試的docker compose file 其實就是一個很單純的 api 測試,執行測試的時候需要用到Celery worker,而Celery需要連到Redis & MySQL

docker compose yaml file如下

好像很簡單,對吧?

但是人生沒那麼容易的,如果你就這樣單純的執行下去 你很有可能會遇到一個問題…

django.db.utils.InterfaceError: (2003, "2003: Can't connect to MySQL server on 'db:3306' (111 Connection refused)", None)
M

什麼?!!

竟然連不到DB? 在本機端測試明明都沒問題啊….

問題分析

根據CircleCI提供的錯誤log,分析可能是因為MySQL server壓根沒有被執行起來 基本上docker-compose 如果加上 depend_on 基本上可以指定container執行的順序 例如:

結果?

很不幸的還是一樣的錯誤…

在上述的yaml 可以看到如果在api加上了depens_on,確實可以指定api會在redis 以及 MySQL後 被執行

不過請注意喔,是被執行,並不代表是可以被連線或是服務已經ready,可以參考這篇 文章

解決方案

根據文章的的建議,我們應該可以設定一個小小的檢查器,如果該服務還沒有被確定啟動,就不會執行,讓他一直等,等到dependencies 都確定可以被連線以後,才會執行下一步

這邊我們用的小工具叫做 wait-for-it

基本上就是一個pure bash script,可以用來block住你的程式碼,等到需要等待的資料庫或是其他服務真的 ready 後才會執行

使用範例如下

./wait-for-it.sh db:3306 -- echo "db is up"

也由於他是純bash寫成的,你不用安裝任何的dependencies,直接把那隻bash script丟進repo或是在circleci build的時候直接下載也可

所以改寫後的docker compose會像這樣

可以注意到在celery command的部分,我們加上了wait-for-it的指令,你就會在circleci的log上面發現,他真的有在等待

wait-for-it.sh: waiting 15 seconds for db:3307

然後你的circleci就成功了!!!!!!!!!! :)

結語

當然,我還是認為在circleci的docker container裡面再起一個docker-compose不是一個很好的idea,因為目前我們還是遇到了circleci build time非常久的問題,但是如果你發現circleci提供的 多個conatinaer作法 不合你的胃口,或許你也可以嘗試看看本篇的做法唷。有問題以及指正歡迎在下方留言,謝謝。

Originally published at https://cftang0827.github.io on December 9, 2019.

--

--

Paul Tang
Paul Tang

Written by Paul Tang

初來乍到,剛到東京的菜鳥後端工程師,希望有一天能成為獨當一面的Full Stack Hacker

No responses yet