利用Docker容器實現代理轉發和資料備份

genetalks_大資料發表於2019-04-04

我們將應用以Docker容器的方式部署到伺服器上的時候,通常需要考慮兩個方面的的問題:網路和儲存。

網路方面,有些應用需要佔用埠,而其中一部分應用甚至需要對外提供訪問。 出於安全方面考慮,代理轉發方式相對於直接開放防火牆埠方式更為合適。

儲存方面,由於容器內部並不適合做資料持久化,所以一般通過掛載卷的方式將資料儲存在伺服器磁碟上。 但是伺服器也不能保證絕對安全,所以資料也需要備份到雲上。

代理轉發

預設情況下容器之間的網路是互相隔離的,但是對於一些有關聯的應用而言(web前端容器和服務端容器以及資料庫容器),一般會把它們劃分到一個獨立的橋接子網路(以下簡稱子網),使得這些容器之間可以相互通訊,但同時又與外部進行隔離。 對於需要對子網外部提供訪問的容器,可以將埠對映到伺服器主機上。整個結構大致如下:

利用Docker容器實現代理轉發和資料備份

上面的埠對映只解決了伺服器(宿主機)訪問容器網路服務的問題,如果我們要從本地機器上通過因特網訪問伺服器上的容器,一般是不行的,因為伺服器除了安全考慮,預設情況下會啟用防火牆,並只開放22等少數幾個埠。

對於傳統的網路程式,實現方式就是通過反向代理伺服器來對網路請求進行轉發,比如使用Nginx配置如下代理:

# 針對不同路徑進行轉發
server {
    listen       80;                                                         
    server_name  www.xx.com;                                               

    location /a {
        proxy_pass localhost:1234;
    }
    location /b {
        proxy_pass localhost:2234;
    }
}
# 針對不同域名進行轉發
server {
    listen       80;                                                         
    server_name  www.yy.com;                                               

    location / {
        proxy_pass localhost:1234;
    }
}
複製程式碼

那麼此時問題似乎是解決了,但是如果Nginx也是在容器中執行呢? 剛才我們提到子網對於外部的容器是隔離的,那麼Nginx容器將無法訪問這些對外服務。 你可能很容想到把Nginx容器劃分到對應的子網路這種方式,容器的確支援多個子網的配置,但是這種操作方式的麻煩在於,每次新增子網時都需要修改Nginx容器的網路配置並重啟容器。

**所以比較好的方式是將Nginx設定為HOST網路模式。**放棄Nginx容器與伺服器的隔離性,直接與伺服器共享網路和埠。那麼Nginx容器即可直接訪問所有對映了埠的容器。 如下圖所示:

利用Docker容器實現代理轉發和資料備份

資料備份

應用場景

考慮到速度和安全性方面的問題,通常公司會有一些只供內網訪問的伺服器。但是這些伺服器上的資料包括伺服器本身都是隨時可能被修改或者發生故障的。 所以資料備份顯得尤為重要。這裡我們討論體積較小的資料備份。 以我最近為團隊搭建的知識庫伺服器為例。 該web應用是一個小型的python服務,以容器的形式部署在內網伺服器上,支援線上編輯功能,以md檔案的形式儲存資料。 因為容器一旦發生故障則內部資料無法再訪問,所以直接放在容器中肯定是不安全的,只能通過掛載檔案的方式讓容器和伺服器共享資料讀寫。 那麼通過什麼方式對資料進行備份呢?這裡我們選擇GitHub的私有倉庫來進行儲存。原因有3個:

  1. 安全。資料不容易丟失和竊取。
  2. 方便,只需要通過git命令即可備份。
  3. 快速。由於備份的資料體積和數量並不大。

雖然方式已經確定,但要實現還有兩個問題:

  1. 向GitHub倉庫需要進行許可權認證。
  2. 如何定時或自動提交資料到GitHub。

實現方法

首先按照容器單一指責的原則,我們應該建立一個新的容器用來執行備份任務。 這裡我們我可以使用docker-compose或者其它編排工具來建立多個容器。 然後就是許可權認證,在本機建立ssh key並加入到GitHub的設定中,這樣使得容器可以推送檔案到對應倉庫。 不過現在只是伺服器可以推送程式碼,容器還不行,所以還需要將.ssh檔案拷貝到容器中。 最後是自動備份的實現,比較好的方式是每次檔案有變動的時候提交併推送程式碼,但是目前並沒有找到在容器中監聽檔案的簡單方式,所以退而求其次,採用定時任務的策略,即每隔5分鐘執行對應的git命令來提交和推送檔案到倉庫。 這裡可以使用基於映象busybox封裝的輕量級的容器,將專案程式碼掛載到容器中保證檔案的同步更新,然後啟動cron服務來實現操作。


作者資訊:朱德龍,人和未來高階前端工程師。

相關文章