天天看點

docker registry push 覆寫_建構的docker容器轉移到另一台可以通過SSH通路的機器上使用内置工具Pushing With Layers我自己的解決方案與CircleCI一起使用結論

我最近在我的一個業餘項目中遇到了挑戰。我需要将在一台機器上建構的docker容器轉移到另一台可以通過SSH通路的機器上。我不想将我的容器推送到公共docker系統資料庫,也不想設定自己的私有系統資料庫。

使用内置工具

很快就在stack overflow找到了答案(https://stackoverflow.com/a/26226261/272958)

docker save  | bzip2 |  ssh [email protected] 'bunzip2 | docker load'
           

讓我們分解一下:

  1. docker save 擷取所有圖像資料,并将其及其标簽序列化為二進制資料流。
  2. docker load 接收二進制資料流并将其反序列化為帶有标簽的圖像。
  3. bzip2壓縮流并bunzip2解壓縮流。
  4. ssh [email protected] 'some command' ssh進入遠端主機并運作指定的指令。

事實證明,docker load它能夠自動解壓縮bzip'd内容,是以您可以将指令簡化為:

docker save  | bzip2 |  ssh [email protected] 'docker load'
           

您可以删除,bzip2但是docker映像通常很大,從進行壓縮bzip2可以節省大量帶寬。

我仍然有一個問題。我通過慢速的3G Internet連接配接進行所有操作,并且遠端主機已經具有要推送的映像中的大多數層,我隻需要推送包含我的應用程式邏輯的微小新層即可。

Pushing With Layers

經過更多研究,我發現docker-push-ssh。使用此指令,您可以執行以下操作:

docker-push-ssh [email protected] 
           

它僅傳輸所需的層。為此:

  1. 在本地計算機上設定一個臨時Docker系統資料庫-這很容易做到,因為在名為docker的鏡像中有一個docker系統資料庫 registry:2
  2. 難道一個docker push到本地系統資料庫。因為它遍及本地計算機的網絡,是以速度很快。
  3. 使用SSH代理遠端伺服器上的端口,以便它連接配接到本地計算機上的代理。
  4. 難道一個docker pull遠端伺服器上。該拉取在SSH隧道上運作,但是docker pull非常聰明,僅拉取它尚不具備的層。
docker registry push 覆寫_建構的docker容器轉移到另一台可以通過SSH通路的機器上使用内置工具Pushing With Layers我自己的解決方案與CircleCI一起使用結論

我自己的解決方案

這是一個好主意,但是我遇到了三個問題:

  1. 它是用Python編寫的,并且需要Python 2.7,我不想依賴于已安裝。
  2. 它已經有一段時間沒有更新了,通常不會有什麼問題,但是考慮到它依賴于舊版本的Python,這有點令人擔憂。
  3. 目前尚不清楚遠端計算機上所需的特權級别。我希望能夠将事情鎖定下來,以便進行推送的使用者隻能将特定的已命名docker映像推送到遠端計算機,而不能做其他任何事情。

為了解決所有這些問題,我決定在Node.js中建立一個名為docker-over-ssh的CLI 。盡管名稱如此,但docker-over-ssh實際上完全與傳輸無關。它僅需要一種通過stdin和stdout與自身的遠端執行個體進行通信的方法。要使用它,請docker-over-ssh同時在本地和遠端計算機上安裝。然後,您可以運作:

docker-over-ssh push   ssh [email protected] "docker-over-ssh pull "
           

該圖看起來與先前的解決方案完全相同。

該docker-over-ssh push指令将啟動本地docker系統資料庫,将映像推送到其中,然後運作“子指令”(在本示例中為ssh [email protected] "docker-over-ssh pull "),并将tcp流量從該子指令的stdio代理到本地docker系統資料庫。

該docker-over-ssh pull 指令啟動一個本地TCP代理(用幾行node.js代碼編寫),并将該代理連接配接到stdio,以便它可以與本地docker系統資料庫通信。然後,它docker pull指向本地系統資料庫運作。僅傳輸新的層,進而使所有工作保持高效。

使用者唯一需要的許可是docker-over-ssh pull 在遠端計算機上運作的能力,而無需任何其他操作。

與CircleCI一起使用

在這一點上,我有一個可行的解決方案,但是我想使它自動化,以便可以從CircleCI進行部署。向CircleCI添加SSH密鑰非常容易。面臨的挑戰是如何通過其複雜的docker網絡設定來完成這項工作:

  • 您的本地代碼(即終止代理的node.js代碼)無法與使用運作的容器對話docker run。
  • 該docker守護程序(用于運作docker push)不能跟跑為主要CircleCI工作服務容器。

我找不到直接解決這兩個問題的任何實用方法,但是我發現NGROK可以很容易地建立一個可以通路本地服務的Internet通路位址。有了這個,我能夠告訴CircleCI啟動Docker系統資料庫作為建構服務,然後使用ngrok啟動一個臨時代理以将其公開給docker守護程式。它甚至支援使用使用者名和密碼(由我自動生成)來保護它,以確定一切安全。

最後,我要做的就是更新CircleCI配置:

docker: - image: circleci/node:12 environment: LOCAL_DOCKER_REGISTRY_PORT: '5000' - image: registry:2
           

并将DOCKER_REGISTRY_NGROK環境變量設定為我的ngrok API密鑰,您可以免費擷取。

然後,我向docker-over-ssh添加了一些代碼來處理這兩個環境變量。

結論

我做所有這些事情的原因是嘗試安裝一個dokku伺服器,我可以在其中運作很多輔助項目,并避免在heroku上花費很少的金錢來處理很少使用的東西。我對這個問題的解決方案感到非常滿意,但是由于Digital Ocean擁有托管的Kubernetes服務,而且價格似乎非常實惠,是以我現在決定研究Kubernetes 。這将需要我弄清楚運作具有某種身份驗證/授權的持久性Docker系統資料庫。

翻譯自:https://itnext.io/docker-over-ssh-51ab25a79f2e

繼續閱讀