天天看点

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

继续阅读