如何自動化專案在伺服器上的部署過程

如今 Docker 正夯,已經是伺服器部署專案時的首選工具了。
只要寫好 Dockerfile 就可以 build 出一個 image,從而就可以在 Docker daemon 上執行這個 image 的 container。
這樣做不但方便部署,而且還方便維護伺服器。

但是上面的步驟你看出來了嗎?你大概會需要做這些事情:

$ docker build -t foo/dockerized-bar ./
$ docker run foo/dockerized-bar

這只是第一次部署時你需要做的事情而已。
在日後的開發中,我先假設你跟我一樣是使用 GitHub 做版本控制,
因此你以後在更新專案後重新部署這個 container 時可能需要做這些事情:

$ git push
$ docker build -t foo/dockerized-bar ./
$ docker ps | grep "foo/dockerized-bar" | cut -d ' ' -f 1 | xargs --no-run-if-empty docker stop
$ docker run foo/dockerized-bar

如果你有強迫症,你可能還會想要清掉舊的 container:

$ docker ps -a | grep "Exited" | cut -d ' ' -f 1 | xargs --no-run-if-empty docker rm

也就是說,整個過程會變成這樣:

$ git push
$ docker build -t foo/dockerized-bar ./
$ docker ps | grep "foo/dockerized-bar" | cut -d ' ' -f 1 | xargs --no-run-if-empty docker stop
$ docker run foo/dockerized-bar
$ docker ps -a | grep "Exited" | cut -d ' ' -f 1 | xargs --no-run-if-empty docker rm

這個還沒有算進去在 run container 時所帶的參數,不然要更麻煩。
還有,你可能有超多 project 在持續開發而且需要重新部署,你難道想要在 Terminal 裡面打這些指令好幾十遍嗎?

這樣子,即使 Docker 再好,你大概也懶得去搞它。
但是今天,我們可以結合 Docker Hub 提供的 Automated building 服務以及 drud/watchtower 來進行這整個過程的自動化!
這兩個東西設定完之後,你以後在 commit 之後只需要做這件事了:

$ git push

這樣還看不出來你的工作量減了多少嗎?
少了 97%

設定 Docker HubAutomated build

Automated buildDocker Hub 官方提供的一個超佛心服務,就是在你 push 之後自動幫你 build Docker image。
好,我這裡先假設你在使用 GitHub 做版本控制以及專案原始碼的 hosting。
你只要把 Dockerfile 寫好,然後丟到你 repo 的 / 底下,前置工作就完成了。
這裡也假設你已經有了 Docker 的使用基礎,那你就應該要有一個 Docker Hub 賬號。

開始設定 Automated build 吧!

  1. 如果你的專案已經在 Docker Hub 有一個 repository 了,那就先把它刪掉吧(沒差,只要留著 Dockerfile 跟兩個 description 就好了)。
  2. 進入 Docker Hub,點擊右上角「Create」右邊的小三角形,然後點擊「Create Automated Build」。
  3. 接著會請你連線到 GitHub 賬號,請連線。
  4. 接著照著裡面的資訊全部填進去就好囉。

Repository 建立之後,請進入 repo 頁面,然後點擊「Build Settings」,然後按下你需要 build 的 branch 右方的「Trigger」按鈕。(你還可以在該頁面設定哪些 branch 是 Docker Hub 需要自動幫你 build 的)

設定 drud/watchtower

這裡需要分成兩個部分,因為你的 Docker Hub repository 可能是 public 跟 private 的。

如果你需要自動重新啟動的 container 內執行的 image 在 Docker Hub 上是被設定為 private 的,請跟隨「Private Repositories」教學。

Public Repositories

請在你裝有 Docker daemon 的伺服器上執行以下指令:

$ docker run -d \
  --name watchtower \
  -v /var/run/docker.sock:/var/run/docker.sock \
  drud/watchtower --debug --cleanup
Private Repositories

請在你裝有 Docker daemon 的伺服器上執行以下指令:

$ docker run -d \
  --name watchtower \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e REPO_USER="<DOCKER_HUB_USERNAME>" \
  -e REPO_PASS="<DOCKER_HUB_PASSWORD>" \
  -e REPO_EMAIL="<DOCKER_HUB_EMAIL>" \
  drud/watchtower --debug --cleanup

其中,請將「<DOCKER_HUB_USERNAME>」、「<DOCKER_HUB_PASSWORD>」以及「<DOCKER_HUB_EMAIL>」分別更換為你 Docker Hub 的使用者名稱密碼以及 email

結語

現在已經不再是當初 server 內亂糟糟的服務一大堆的年代了,
如今虛擬化容器技術如此發達,效能跟原生差不多,
如果開發、維護、部署可以非常非常方便,那我寧願犧牲那 0.1% 的效能來換。
這篇文章教了你如何把這個部署的過程再度簡化,讓你的開發更加順手,感謝你看到這邊,因為我知道我這篇文章寫的還蠻長的。

(Cover photo credit: http://logz.io/blog/what-is-docker/)