【问题标题】:`docker run` on a remote host远程主机上的“docker run”
【发布时间】:2017-11-10 19:16:55
【问题描述】:

是否可以(直接使用docker 命令或docker-py API)从远程主机启动容器?

假设我有两台具有不同架构的机器: - A 是x86 机器 - B 是ARM 机器

我想使用我的 A 机器在 B 机器上运行一个容器。一开始我以为可以用这个命令:

[A]$> DOCKER_HOST=$MACHINE_B_IP:$MACHIN_B_PORT docker run hello-from-B

但是这个命令实际上会拉取图像 hello-from-B 并尝试在机器 A 上运行它,这最终会出现在一些 exec format error 上,因为显然你不能将特定于 ARM 的图像运行到 x86机器。

机器 A 和 B 之间的通信运行良好。我可以运行imagesps 之类的命令,它给了我预期的结果:

[A]$> DOCKER_HOST=$MACHINE_B_IP:$MACHIN_B_PORT docker images
REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
hello-from-B              <none>              fd5059044831        13 hours ago        1.26GB

我听说过docker-machine,但还没有尝试过,但据我了解,这并不能解决我的问题。

有没有办法直接使用docker 来实现。一种解决方法可能是使用ssh 连接到远程主机并直接从远程主机使用docker 客户端,但我想尽可能避免这种解决方案。

提前致谢,


TL;DR;

DOCKER_HOST=... docker run something 如何在DOCKER_HOST 上运行something 而不是在我的本地机器上运行它。

【问题讨论】:

标签: linux docker


【解决方案1】:

检查最新的 docker 18.09 是否包含该功能。
docker/cli PR 1014

增加了对 SSH 连接的支持。例如docker -H ssh://me@server

  • 对于DOCKER_HOST-H,cli 应该接受ssh://me@server。使用它会使用传递的配置执行 ssh。
  • ssh 命令将调用远程端 docker CLI 二进制文件中的隐藏命令。例如,docker dial-stdio。

此命令将连接到本地 DOCKER_HOST 变量(几乎总是默认的本地套接字)并在命令 stdio 上转发该连接。
尽管该命令应该在本地运行到 dockerd 二进制文件,但我们认为删除本地 docker 二进制文件是此功能的无效配置,因此我们可以依赖它始终存在。

如何验证

docker -H ssh://me@server run -it --rm busybox

目前的反应:

来自世界各地的运维人员和系统管理员,我们感谢您提供这个奇妙而出人意料的功能。
我希望这会大大减少我看到人们打开 dockerd TCP w/o TLS 并选择远程管理的 SSH 端点的次数。

【讨论】:

  • 我感谢您发布这个答案 - 就像一个魅力!
【解决方案2】:

如果您的目标机器 B 可以在 these platform 之一上创建,那么我猜 docker-machine 将满足您的需求。您将使用docker-machine create --driver &lt;..driver setup..&gt; MACHINE_B 创建您的机器,然后使用eval $(docker-machine env MACHINE_B) 激活它。 docker-machine env MACHINE_B 会打印出一些导出语句:

export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://...."
export DOCKER_CERT_PATH="/..."
export DOCKER_MACHINE_NAME="MACHINE_B"

一旦您的机器处于活动状态,您就可以像在本地一样使用docker 命令对 MACHINE_B 进行远程操作。

【讨论】:

  • 看来generic 驱动程序可能是一种解决方案。我也听说过none 驱动程序,但找不到有关此驱动程序的文档。无论如何,docker-machine 可能是我正在寻找的,我会试一试。谢谢!
  • 祝你好运,我自己没有使用过驱动程序none,但我找到了herearticle
  • 看来docker-machine 并没有解决我的问题。它仍然以:exec format error 结尾。出于某种原因,它试图在我的x86_64 机器上执行我的容器(基于aarch64 arch)。也许那是因为驱动程序和其他驱动程序按预期工作。另外..我正在尝试以非常规方式使用docker。还是谢谢!
  • 其实我做错了。我正在尝试启动默认为x86 机器构建的hello-world 图像。所以它可能会起作用......我会与您保持联系。
  • docker-machine 一切正常。首先,我只使用DOCKER_HOST,它也应该可以按预期工作。我没有注意我试图运行的图像。另外,作为旁注,docker-machine 需要 TLS(或至少是旧版本),我已经尝试了一堆 tlsnoverify blahblah 用于测试目的,但没有一个有效。现在我已经设置了整个 TLS 环境,我可以毫无困难地使用它。再次感谢。
【解决方案3】:

这篇文章很好的解释了这个概念:https://docs.docker.com/engine/reference/commandline/dockerd/#bind-docker-to-another-hostport-or-a-unix-socket

考虑到页面上的巨大警告,我建议您通过 SSH 使用安全连接,即。 ssh user@host 'docker run hello-from-B'

警告:更改默认 docker 守护进程绑定到 TCP 端口或 Unix docker 用户组将增加您的安全风险 允许非 root 用户在主机上获得 root 访问权限。确保你 控制对 docker 的访问。如果您绑定到 TCP 端口,任何人 有权访问该端口具有完整的 Docker 访问权限;所以不是 建议在开放网络上使用。


使用 -H 可以让 Docker 守护进程监听 特定的 IP 和端口。默认情况下,它将监听 unix:///var/run/docker.sock 只允许本地连接 根用户。您可以将其设置为 0.0.0.0:2375 或特定主机 IP 让每个人都可以访问,但不建议这样做,因为那样的话 对于某人获得对所在主机的 root 访问权限是微不足道的 守护进程正在运行。

同样,Docker 客户端可以使用-H 连接到自定义端口。 Docker 客户端将默认连接到 unix:///var/run/docker.sock 在 Linux 上,tcp://127.0.0.1:2376 在 窗户。

-H 接受以下格式的主机和端口分配:

tcp://[host]:[port][path] or unix://path


您可以使用多个 -H,例如,如果您想同时收听 TCP 和 Unix 套接字

# Run docker in daemon mode
$ sudo <path to>/dockerd -H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock &
# Download an ubuntu image, use default Unix socket
$ docker pull ubuntu
# OR use the TCP port
$ docker -H tcp://127.0.0.1:2375 pull ubuntu

【讨论】:

  • 我建议使用非 ssh 选项,因为传递 jenkins 凭据等环境变量很棘手(并非不可能)
  • @MohammedRafeeq 诡计多端?
  • 从 jenkins 文件尝试将环境变量传递给通过 ssh 访问的目标 docker 机器。你会明白我的意思
  • sh " DOCKER_HOST=\"${DOCKER_HOST}\" docker run -e ENVIRONMENT_VARIABLE ..." 是首选。它很容易发送环境变量值,否则无论设置什么值,在 ssh 进入目标 docker 主机后都无法访问它们。DOCKER_HOSTvariable 的格式为 tcp://hostname:2376 2376 是默认端口
【解决方案4】:

正如你所说,服务器之间的连接是可用的,你可以利用 Docker 丰富的 API。

配置 docker daemon 端口有两种方式

1) 在/etc/default/docker文件配置:

DOCKER_OPTS="-H tcp://127.0.0.1:5000 -H unix:///var/run/docker.sock"

2) 在/etc/docker/daemon.json进行配置:

{
"hosts": ["tcp://127.0.0.1:5000", "unix:///var/run/docker.sock"]
}

有关配置 docker daemon 端口的更多详细信息,refer configure-docker-daemon-port

配置 Docker 端口后,您可以访问远程主机中的 Docker API。

JSON 输入文件:

#cat container_create.json 
{
  "AttachStdin": true,
  "AttachStdout": true,
  "AttachStderr": true,
  "ExposedPorts": {
    "property1": {},
    "property2": {}
  },
  "Tty": true,
  "OpenStdin": true,
  "StdinOnce": true,
  "Cmd": null,
  "Image": "ubuntu:14.04",
  "Volumes": {
    "additionalProperties": {}
  },
  "Labels": {
    "property1": "string",
    "property2": "string"
  }
}

创建容器的 API:

curl -X POST http://192.168.56.101:6000/containers/create -d @container_create.json --header "Content-Type: application/json" | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   602  100    90  100   512   1737   9883 --:--:-- --:--:-- --:--:-- 10039
{
  "Warnings": null,
  "Id": "f5d3273e48350d606bd8b9d2a5bd876dc5c2d1a73183f876a1dd56473cad8940"
}

生成的ID是容器ID,状态不会是active/running。

用于启动已创建容器的 API。

# curl -X POST http://192.168.56.101:6000/containers/f5d3273e48350/start | jq .  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

用于检查状态/检查容器的 API:

# curl -X GET http://192.168.56.101:6000/containers/f5d3273e48350/json | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  4076    0  4076    0     0   278k      0 --:--:-- --:--:-- --:--:--  306k
{
  "NetworkSettings": {
    "Networks": {
      "bridge": {
        "MacAddress": "02:42:ac:11:00:03",
        "GlobalIPv6PrefixLen": 0,
        "GlobalIPv6Address": "",
        "IPv6Gateway": "",
        "IPAMConfig": null,
        "Links": null,
        "Aliases": null,
        "NetworkID": "689d6b65ce1b06c93b2c70f41760a3e7fb2b50697d71cd9c1f39c64c865e5fa6",
        "EndpointID": "76bf1f8638d1ff0387e6c3fe89e8ccab1670c709ad550f9acc6f46e559654bee",
        "Gateway": "172.17.0.1",
        "IPAddress": "172.17.0.3",
        "IPPrefixLen": 16
      }
    },
    "MacAddress": "02:42:ac:11:00:03",
    "SecondaryIPAddresses": null,
    "SandboxKey": "/var/run/docker/netns/24a031d9dfda",
    "Ports": {
      "0/tcp": null
    },
    "LinkLocalIPv6PrefixLen": 0,
    "LinkLocalIPv6Address": "",
    "HairpinMode": false,
    "SandboxID": "24a031d9dfda70026a875f4841269c5e790b12ccafcc11869111faa240020b99",
    "Bridge": "",
    "SecondaryIPv6Addresses": null,
    "EndpointID": "76bf1f8638d1ff0387e6c3fe89e8ccab1670c709ad550f9acc6f46e559654bee",
    "Gateway": "172.17.0.1",
    "GlobalIPv6Address": "",
    "GlobalIPv6PrefixLen": 0,
    "IPAddress": "172.17.0.3",
    "IPPrefixLen": 16,
    "IPv6Gateway": ""
  },

    },
    "AttachStderr": true,
    "AttachStdout": true,
    "AttachStdin": true,
    "User": "",
    "Domainname": "",
    "Hostname": "f5d3273e4835",
    "OpenStdin": true,
    "StdinOnce": true,
    "Env": [
      "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
    ],
    "Cmd": [
      "/bin/bash"
    ],
    "ArgsEscaped": true,
    "Image": "ubuntu:14.04",

<*************REMOVING THE OUTPUT CONTENT********>

  "ExecIDs": null,
  "HostnamePath": "/var/lib/docker/containers/f5d3273e48350d606bd8b9d2a5bd876dc5c2d1a73183f876a1dd56473cad8940/hostname",
  "ResolvConfPath": "/var/lib/docker/containers/f5d3273e48350d606bd8b9d2a5bd876dc5c2d1a73183f876a1dd56473cad8940/resolv.conf",
  "Image": "sha256:132b7427a3b40f958aaeae8716e0cbb2177658d2410554ed142e583ef522309f",
  "State": {
    "FinishedAt": "0001-01-01T00:00:00Z",
    "StartedAt": "2017-06-09T06:53:45.120357144Z",
    "Error": "",
    "Status": "running",
    "Running": true,
    "Paused": false,
    "Restarting": false,

  "Path": "/bin/bash",
  "Created": "2017-06-09T06:52:51.820429355Z",
  "Id": "f5d3273e48350d606bd8b9d2a5bd876dc5c2d1a73183f876a1dd56473cad8940",
  "HostsPath": "/var/lib/docker/containers/f5d3273e48350d606bd8b9d2a5bd876dc5c2d1a73183f876a1dd56473cad8940/hosts",
  "LogPath": "/var/lib/docker/containers/f5d3273e48350d606bd8b9d2a5bd876dc5c2d1a73183f876a1dd56473cad8940/f5d3273e48350d606bd8b9d2a5bd876dc5c2d1a73183f876a1dd56473cad8940-json.log",
  "Name": "/objective_bartik",
  "RestartCount": 0,
  "Driver": "aufs",
  "MountLabel": "",
  "ProcessLabel": "",
  "AppArmorProfile": "docker-default"
}

更多信息请参考:

DOCKER APIs

How to build an Image using Docker API?

How to commit Docker Container using API

希望这些信息对他有所帮助。

【讨论】:

  • 我一直在使用docker-py API 进行测试并尝试使用DOCKER_HOST 在机器B 上运行容器,不幸的是这与调用DOCKER_HOST=... docker run... 的结果相同。无论如何,您的解决方案似乎符合我的要求,如果 docker-machine 没有按预期工作,我会尝试。谢谢!
  • 您能否更新对您有帮助的适当答案。当他们面临类似问题时,它也会帮助其他人。谢谢..
猜你喜欢
  • 2017-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-07
  • 2018-07-12
  • 2017-04-30
相关资源
最近更新 更多