【问题标题】:How to run docker-compose on remote host?如何在远程主机上运行 docker-compose?
【发布时间】:2016-02-16 12:51:32
【问题描述】:

我在本地撰写文件。如何在docker-compose up -dDOCKER_HOST=<some ip> 等远程主机上运行容器包?

【问题讨论】:

  • 你的问题我不清楚。你真的想通过docker-compose在远程主机上部署容器吗?
  • 是的,就像 docs.docker.com/compose/production 但我想在没有 docker-machine 的情况下这样做
  • 查看这篇文章:developer.rackspace.com/blog/…
  • 我不明白这个问题。 DOCKER_HOST=... docker-compose up -d 应该可以工作

标签: docker docker-compose


【解决方案1】:

Docker 18.09.0 发布和(截至目前)即将发布的docker-compose v1.23.1 发布之后,这将变得容易得多。上面提到的 Docker 版本分别为DOCKER_HOST 环境变量和-H 命令添加了对ssh 协议的支持和docker ... 命令的-H 参数。下一个docker-compose 发布will incorporate this feature as well

首先,您需要SSH access to the target machine(任何方法都可能需要它)。

然后,要么:

# Re-direct to remote environment.
export DOCKER_HOST="ssh://my-user@remote-host"

# Run your docker-compose commands.
docker-compose pull
docker-compose down
docker-compose up

# All docker-compose commands here will be run on remote-host.

# Switch back to your local environment.
unset DOCKER_HOST

或者,如果您愿意,只需一个命令即可完成所有操作:

docker-compose -H "ssh://my-user@remote-host" up

这样做的好处是,您可以在 docker-compose.yml 文件中用于配置的所有本地环境变量都可用,而无需以某种方式将它们转移到 remote-host

【讨论】:

  • 我需要在远程服务器上进行撰写,还是在那儿为我完成所有设置?
  • 据我所知,远程服务器上不需要docker-composedocker-compose 只是代表您运行各种常规docker 命令的包装器。当运行docker-compose -H "ssh://my-user@remote-host" up 时,这将在控制机器上转换为类似于docker -H "ssh://my-user@remote-host" run --name foo some-image ... 的内容,因此不会在远程机器上运行docker-compose 命令。
  • 我收到错误X11 forwarding request failed on channel 0
【解决方案2】:

如果您不需要在本地机器上运行 docker 容器,但仍然在同一台远程机器上,您可以在 docker 设置中更改此设置。

在本地机器上: 可以通过-H参数控制远程主机

docker -H tcp://remote:2375 pull ubuntu

要将它与 docker-compose 一起使用,您应该在 /etc/default/docker 中添加此参数

在远程机器上

您应该从外部地址更改监听,而不仅仅是 unix 套接字。

更多详情请见Bind Docker to another host/port or a Unix socket

如果你需要在多个远程主机上运行容器,你应该配置 Docker Swarm

【讨论】:

  • 请记住,默认情况下,这允许网络中的任何人访问该机器的 Docker 守护程序。由于对 Docker 守护进程的访问类似于该机器上的sudo 权限,因此您应该只在受信任的环境中执行此操作。有一些方法可以保护或限制对受信任客户端的访问,仅在此处或有关该主题的几篇博客文章中进行了说明。不过,这更像是一个高级主题。 docs.docker.com/engine/security/https/…
【解决方案3】:

您现在可以为此使用 docker 上下文:

docker context create dev ‐‐docker “host=ssh://user@remotemachine”

docker-compose ‐‐context dev up -d

更多信息在这里:https://www.docker.com/blog/how-to-deploy-on-remote-docker-hosts-with-docker-compose/

【讨论】:

  • 我相信这是实现这一目标的最佳方式。感谢分享。
  • 如果服务器需要密钥认证,我们如何使用docker context进行连接?如何提供密钥?
【解决方案4】:

来自撰写文档

Compose CLI environment variables

DOCKER_HOST

设置 docker 守护进程的 URL。与 Docker 客户端一样,默认为 unix:///var/run/docker.sock。

这样我们就可以做

export DOCKER_HOST=tcp://192.168.1.2:2375
docker-compose up

【讨论】:

  • 这仅在您将目标机器上的 Docker 守护程序配置为允许通过 TCP 进行远程访问时才有效,例如解释在这里:success.docker.com/article/… 还要记住我在对@Thibaut 的回答的评论中概述的安全问题。
【解决方案5】:

我最近发现的另一种可能性是通过 SSH 隧道控制远程 Docker Unix 套接字(感谢 https://medium.com/@dperny/forwarding-the-docker-socket-over-ssh-e6567cfab160 我了解这种方法的地方)。

先决条件

您可以通过 SSH 连接到目标机器。出于安全性和便利性考虑,首选无密码、基于密钥的访问,您可以学习如何设置它,例如这里:https://askubuntu.com/questions/46930/how-can-i-set-up-password-less-ssh-login

此外,一些消息来源提到通过 SSH 隧道转发 Unix 套接字只能从 OpenSSH v6.7 开始(运行 ssh -V 进行检查),不过我没有在旧版本上尝试过。

SSH 隧道

现在,在本地位置和远程机器上的 Docker Unix 套接字之间创建一个新的 SSH 隧道: ssh -nNT -L $(pwd)/docker.sock:/var/run/docker.sock user@someremote

或者,也可以绑定到本地端口而不是文件位置。确保端口已为连接打开并且尚未使用。 ssh -nNT -L localhost:2377:/var/run/docker.sock user@someremote

重定向 Docker 客户端

让终端保持打开状态并打开第二个终端。在那里,让您的 Docker 客户端与新创建的隧道套接字而不是本地 Unix Docker 套接字通信。

如果您绑定到文件位置:

export DOCKER_HOST=unix://$(pwd)/docker.sock

如果您绑定到本地端口(上面使用的示例端口):

export DOCKER_HOST=localhost:2377

现在,运行一些 Docker 命令,例如 docker ps 或启动容器、拉取映像等。只要 SSH 隧道处于活动状态,一切都会在远程机器上发生。为了再次运行本地 Docker 命令:

  • 在第一个终端点击Ctrl+C 关闭隧道。
  • 如果您绑定到文件位置:再次删除临时隧道套接字。否则您以后将无法再次打开同一个:rm -f "$(pwd)"/docker.sock
  • 让您的 Docker 客户端再次与您的本地 Unix 套接字通信(如果未设置,这是默认值):unset DOCKER_HOST

这样做的好处是您省去了复制docker-compose.yml 文件和其他资源或在远程机器上设置环境变量的麻烦(这很困难)。

非交互式 SSH 隧道

如果您想在无法使用交互式终端的脚本上下文中使用它,可以使用SSH ControlMaster and ControlPath optionsopen and close the SSH tunnel in the background

# constants
TEMP_DIR="$(mktemp -d -t someprefix_XXXXXX)"
REMOTE_USER=some_user
REMOTE_HOST=some.host
control_socket="${TEMP_DIR}"/control.sock
local_temp_docker_socket="${TEMP_DIR}"/docker.sock
remote_docker_socket="/var/run/docker.sock"

# open the SSH tunnel in the background - this will not fork
# into the background before the tunnel is established and fail otherwise
ssh -f -n -M -N -T \
    -o ExitOnForwardFailure=yes \
    -S "${control_socket}" \
    -L "${local_temp_docker_socket}":"${remote_docker_socket}" \
    "${REMOTE_USER}"@"${REMOTE_HOST}"

# re-direct local Docker engine to the remote socket
export DOCKER_HOST="unix://${local_temp_docker_socket}"

# do some business on remote host
docker ps -a

# close the tunnel and clean up
ssh -S "${control_socket}" -O exit "${REMOTE_HOST}"
rm -f "${local_temp_docker_socket}" "${control_socket}"
unset DOCKER_HOST

# do business on localhost again   

【讨论】:

    【解决方案6】:

    鉴于您能够在远程机器上登录,在该机器上运行docker-compose 命令的另一种方法是使用SSH

    通过scpdocker-compose.yml 文件复制到远程主机,在SSH 上运行docker-compose 命令,最后通过再次删除文件进行清理。 这可能如下所示:

    scp ./docker-compose.yml SomeUser@RemoteHost:/tmp/docker-compose.yml
    ssh SomeUser@RemoteHost "docker-compose -f /tmp/docker-compose.yml up"
    ssh SomeUser@RemoteHost "rm -f /tmp/docker-compose.yml"
    

    您甚至可以缩短它并省略docker-compose.yml 文件的发送和删除,方法是使用docker-compose-f - 选项,这将期望docker-compose.yml 文件从stdin 传输。只需将其内容通过管道传递给SSH 命令:

    cat docker-compose.yml | ssh SomeUser@RemoteHost "docker-compose -f - up"
    

    如果您在 docker-compose.yml 文件中使用环境变量替换,上述命令不会将它们替换为远程主机上的本地值,并且您的命令可能会由于未设置变量而失败。为了克服这个问题,可以使用envsubst utility 将变量替换为内存中的本地值,然后再将内容传递给SSH 命令:

    envsubst < docker-compose.yml | ssh SomeUser@RemoteHost "docker-compose up"
    

    【讨论】:

    • 这很新颖......如果 yml 文件包含存储在需要登录的私有注册表中的图像怎么办?
    • 我猜在这种情况下,您必须在中间的某个地方添加一个登录步骤。使用docker login my.docker.registryproviding your user and password on the command line 以交互方式与用户/密码提示进行交互(但请注意确保安全)。
    猜你喜欢
    • 2019-05-09
    • 1970-01-01
    • 2021-08-28
    • 1970-01-01
    • 2014-04-25
    • 1970-01-01
    • 1970-01-01
    • 2016-08-31
    • 1970-01-01
    相关资源
    最近更新 更多