【问题标题】:Shell into a Docker container running on a Heroku dyno. How?Shell 进入在 Heroku dyno 上运行的 Docker 容器。如何?
【发布时间】:2018-03-21 01:05:41
【问题描述】:

给定一个运行容器的测功机,Heroku 相当于docker exec -it blarg /bin/bash 是什么?也就是说,如何在已经运行的容器中打开一个 shell?

示例 Dockerfile:

FROM heroku/heroku:16
CMD while true; do sleep 1; done

示例运行:

$ heroku container:push my_app
<wait a minute>
$ heroku ps
=== my_app (Free): /bin/sh -c while\ true\;\ do\ sleep\ 1\;\ done (1) 
my_app.1: up 2017/10/09 12:13:07 -0600 (~ 4m ago)

到目前为止一切顺利。

但是现在……

$ heroku ps:exec --dyno=my_app.1
Establishing credentials... error
 ▸    Could not connect to dyno!
 ▸    Check if the dyno is running with `heroku ps'

为了更好地衡量,我此时检查了heroku ps,它表明测功机仍在运行。

是的,我已经完成了 Heroku 建议 to enable Docker support 的所有事情。根据文档,我尝试使用我选择的基本映像,同时确保存在bashcurlopensshpython。我也尝试过使用 Heroku-16 基础镜像,如上例所示。

(链接的文档还引用了私人空间所需的步骤。由于我没有使用私人空间,我没有应用这些步骤。)

【问题讨论】:

    标签: docker heroku


    【解决方案1】:

    TL;DR 确保 bash 已安装在映像中并将其添加到您的 Dockerfile:

    RUN rm /bin/sh && ln -s /bin/bash /bin/sh
    

    说明

    the documentation 让人相信的相反,Heroku 不支持heroku ps:exec 到已经在 dyno 中运行的 Docker 容器中。

    引用我从 Heroku 团队收到的回复:

    我们的 ps:exec 功能 ... 通过将 bash 文件注入 dynos 来工作, 在后台打开一个额外的端口,并允许您 连接到它。

    [T]默认 Docker使用的shell是/bin/sh,不兼容 Heroku Exec 脚本(需要 /bin/bash)。

    您可以使用一种解决方法。将以下内容放入您的 Dockerfile:

    RUN rm /bin/sh &amp;&amp; ln -s /bin/bash /bin/sh

    这绝对是一个差距 我们的产品,我们会努力让它变得更好。

    【讨论】:

    • 如果简单地将sh 替换为bash 的符号链接,我会感到惊讶。如果以sh 调用,bash 进入不支持process substitution(gnu.org/software/bash/manual/html_node/…) 的posix 兼容模式(manpages.debian.org/stretch/bash/bash.1.en.html)。 heroku-exec.sh 使用进程替换 (... &lt;(curl ... ))。试试$ rm /bin/sh &amp;&amp; ln -s /bin/bash /bin/sh$ /bin/bash -c "cat &lt;(echo 1)"$ /bin/sh -c "cat &lt;(echo 1)"
    • 在 heroku-exec 脚本中添加 set +o posix 会有所帮助。
    • @wwerner 你能提供更多关于如何将set +o posix 添加到heroku-exec.sh 的详细信息吗?我现在正在努力解决这个问题。如果你能在这里提供一些额外的建议:stackoverflow.com/questions/61175807/… 会很棒!
    • 我已经尝试了我自己的 docker 镜像 heroku/heroku:16 镜像,ps:exec 仍然无法正常工作,我使用“heroku ps:scale web=1”启动了容器,或者我应该启动用另一个命令?
    • hm 最后,让它工作,仅来自 docker hub 的容器映像“heroku/heroku:16”
    【解决方案2】:

    如果安装了 bash,请运行 heroku run bash。这将使您从命令行进入 shell。

    您也可以使用 GUI 并在您的 heroku 应用程序上转到“更多”->“运行控制台”,然后输入“bash”将其调出。

    【讨论】:

    • 如您所述,在 Web 控制台中尝试此操作最终对我有用。 cli 回复的时间太长了,所以如果我等待更长时间,我不确定它是否会起作用。
    • 不,'heroku run bash' 是一次性的,它是同一图像的一个单独的新容器,你看不到现有进程正在运行
    【解决方案3】:

    已编辑: 为了在使用 Docker 并通过 Container Registry 部署的应用程序上运行 heroku ps:exec,您必须启用 runtime-heroku-exec。 您可以通过heroku features:enable runtime-heroku-exec 启用它

    Here 你可以查看exec 的文档以及启用 docker 支持的说明

    【讨论】:

    • 我已经尝试了所有这些。没有骰子。请参阅我添加到问题中的示例。您是否从示例中得到不同的结果?该示例是否缺少某些内容?
    • 到目前为止,文档具有误导性。看我的回答。
    • 这只是启用该功能,我使用图像 heroku/heroku:16 并且它已经存在,问题是 'heroku ps:exec' 不会运行 :(
    • hm 最后,让它工作,仅来自 docker hub 的容器映像“heroku/heroku:16”
    【解决方案4】:

    heroku run /bin/bashheroku ps:exec 在我的情况下都不起作用。前者打开了一个新的容器,它与真正运行的容器不同!后者在我的 alpine3 容器中不起作用,尽管 heroku features:enable runtime-heroku-exec 可以成功。我的解决方案是在容器中启动一个 shell 服务器和一个流量转发器。然后在客户端使用流量转发器创建的隧道连接到 shell 服务器。

    交通流量:

    localhost:2023 -> chisel client -> ...tunnel... -> chisel server -> localhost:8182
    

    在conainer中,用socat启动一个shell服务器,用chisel启动一个隧道服务器:

    nohup socat tcp-l:8182,reuseaddr,fork exec:/bin/bash,pty,setsid,setpgid,stderr,ctty > /tmp/socat.log 2>&1 &
    
    nohup ./chisel server --port $PORT --proxy http://httpbin.org > /tmp/chisel.log 2>&1 &
    

    在客户端,启动一个凿子客户端,将来自localhost:8182的流量转发到服务器上的socat

    chisel client http://yourapp.herokuapp.com/  0.0.0.0:2023:localhost:8182
    

    在客户端,打开另一个终端窗口:

    socat -,raw,echo=0 tcp:127.0.0.1:2023
    

    如何在服务器上获取凿子?下载它或直接从 Dockerfile 中的源代码编译

    下载chisel

    【讨论】:

      【解决方案5】:

      在我的情况下,要让它在 Ubuntu 20.04(焦点)上运行,我必须另外将 python-is-python3 包安装到 docker 映像中,以使 heroku-exec 正常工作。


      这是一个基于 ubuntu 的 dockerfile 的工作示例(2020 年 10 月),可与 heroku-exec 一起使用:

      FROM ubuntu:focal
      
      # install required packages
      RUN export DEBIAN_FRONTEND=noninteractive && apt-get update && apt-get install -y python3 curl python-is-python3 openssh-server iproute2 nginx && apt-get clean
      
      # simplfy nginx config to enable ENV variable substitution
      RUN echo 'server { listen PORT_NUMBER; }' > /etc/nginx/sites-enabled/default
      
      # add config required for HEROKU_EXEC
      # ENV HEROKU_EXEC_DEBUG=1
      RUN rm /bin/sh \
       && ln -s /bin/bash /bin/sh \
       && mkdir -p /app/.profile.d/ \
       && printf '#!/usr/bin/env bash\n\nset +o posix\n\n[ -z "$SSH_CLIENT" ] && source <(curl --fail --retry 7 -sSL "$HEROKU_EXEC_URL")\n' > /app/.profile.d/heroku-exec.sh \
       && chmod +x /app/.profile.d/heroku-exec.sh
      
      # configure NGINX to listen on dynamic $PORT env variable supplied by Heroku.
      CMD sed -i 's/PORT_NUMBER/'"$PORT"'/g' /etc/nginx/sites-enabled/default; nginx -g 'daemon off;'
      
      

      然后用这个命令连接:

      heroku ps:exec -a name-of-app-12345
      

      【讨论】:

      • 这张图片有多大?是否可以在免费帐户上运行或太大?
      • @PawelW 在我的情况下,存储在 heroku docker 注册表中的结果图像为 241MB。这在免费帐户中运行良好。 // 另见:devcenter.heroku.com/articles/… // “虽然 Docker 映像不受大小限制(与 slug 不同),但它们受 dyno 启动时间限制。”
      猜你喜欢
      • 1970-01-01
      • 2020-11-28
      • 2013-06-28
      • 1970-01-01
      • 2012-07-02
      • 2019-03-05
      • 2021-05-22
      • 2019-07-22
      • 1970-01-01
      相关资源
      最近更新 更多