如何在Heroku上运行Docker in Docker?

10
为什么?
我正在尝试创建一个通用解决方案,以在Heroku上运行docker-compose。我希望通过使用Heroku Button部署实现一键部署解决方案。这样,用户不需要任何git、Heroku cli和docker的知识。
问题所在。
只有当我将“stack”设置为“container”时,才能使用Docker和docker守护程序。有些构建包可以提供给你docker和docker-compose CLI,但是没有docker守护程序,你无法运行docker镜像。因此,构建包不能工作。 将“stack”设置为“container”后,我可以使用文件“heroku.yml”(article)。在其中,我定义了我的进程。(它替换了“Procfile”。如果我仍然向我的项目添加“Procfile”,它将无效。) 我还可以在那里定义一个“Dockerfile”来构建我的docker镜像。 然而,当我运行docker镜像时,会弹出以下错误:
2019-02-28T15:32:48.462101+00:00 app[worker.1]: Couldn't connect to Docker daemon at http+docker://localhost - is it running?
2019-02-28T15:32:48.462119+00:00 app[worker.1]: 
2019-02-28T15:32:48.462122+00:00 app[worker.1]: If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable.

问题在于Docker容器内没有运行Docker守护进程。解决方法是挂载它:
docker run -v /var/run/docker.sock:/var/run/docker.sock ...
由于您不能使用Procfile,因此无法运行该命令。(请参见上面的heroku.yml替换了Procfile)。如果我正在使用构建包,则可以使用Procfile,但Docker守护程序将不会运行......

我尝试在Dockerfile中定义VOLUME,但问题仍然存在。此外,Heroku文章说“不支持卷挂载。 Dyno的文件系统是短暂的。”

在Heroku上可以运行Docker镜像。我遇到的问题是在Docker镜像中运行Docker。
通过挂载/var/run/docker.sock,在我的VPS上可以很好地运行Docker镜像,但在Heroku上无法(?)完成。

最后一句话: 我正在努力使这项工作正常,以便其他人即使不熟悉git、heroku cli和docker也可以轻松部署软件解决方案。


已经过去一年了,我仍在寻找解决这个问题的方法。 - Tin Nguyen
你尝试通过SSH连接到守护进程了吗?出于安全考虑,我认为不可能访问Heroku的docker守护进程,这就是你在本地挂载卷时所做的。 - Folkvir
在VPS上我可以很好地完成它。但在Heroku上我做不到。SSH连接到Heroku堆栈应用程序是可以的,但是如描述中所说,Docker守护程序没有运行。可能可以通过SSH连接到Docker容器(尚未尝试),但我不知道如何从容器访问主机。此外,在运行堆栈应用程序时,它受到严格限制(无法使用root和许多其他限制)。我正在寻找一个正在运行其自己的Docker守护程序的Docker容器。过去有一些工作正在进行,但似乎已经停止,转而绑定到主机的Docker守护程序。 - Tin Nguyen
这不是我所能看到的:https://hub.docker.com/_/docker。我的意思是,当你在heroku部署的容器内部时,你确定守护进程没有运行吗?错误告诉我,你不能使用这个地址连接到守护进程:`http+docker://localhost`。所以,你能否使用tcp://0.0.0.0:2375或端口2376或启用自定义地址?请参考:https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-socket-option - Folkvir
我也尝试过,但是出现了相同的错误信息。我使用环境变量DOCKER_HOST指定了位置,并尝试了不同的URL,包括你提到的那个。我还尝试了/var/run/docker.sock。如果您能在Heroku上创建一个最小的DinD hello world示例,我将不胜感激。 - Tin Nguyen
经过一些研究,我认为您尝试实现的目标在Heroku上至少是不可能的。他们不允许您运行--privileged容器。当在本地工作时,DinD非常好用,但是当被推到Heroku时,dockerd会回答您需要一个root(或拥有特权的)用户来启动守护程序。因此,您可能想要使用无根docker镜像,例如docker:stable-dind-rootless(https://hub.docker.com/_/docker)。我尝试了一下,但是没有找到可行的解决方案,也不能花更多时间在这上面了。希望您可以找到解决办法 :) - Folkvir
3个回答

2
很遗憾,对于你的问题,答案是:目前还不行。
出于安全原因,Heroku不提供给用户运行特权容器的能力,因为容器可以访问主机的功能。文档非常明确地说明了你的限制,例如:没有--priviledged容器和没有root用户,没有VOLUMES,磁盘是暂时的。
在尝试使用DinD镜像解决你的问题后,我得出结论,在Heroku容器内部运行Docker并不是正确的选择和设计。我相信你想要实现的东西与Heroku向用户提供的服务非常接近。提供一个平台或应用程序,使非开发人员只需按下一个按钮即可推送和部署应用程序,可以在各种方面非常有趣。这可以通过使用他们的平台API的应用程序来完成。在这种情况下,Web应用程序(在Heroku上运行)可能无法做到你想要的事情。相反,你需要在桌面应用程序中嵌入git、docker和你的应用程序,以解析、验证、构建和推送你的应用程序/组件到Heroku的容器注册表中。
最终,如果您仍然认为您需要一个 DinD 解决方案,那么目前使用 VPS 是唯一的解决方案。但请注意,这可能会对您的系统造成安全漏洞,并且当尝试限制这些安全门时,您可能会提供类似于 Heroku 的服务。

我将此标记为已接受的答案,因为目前我仍然不认为这是可能的。如果它变得可能,并且有人可以通过Heroku Deploy按钮提供一个最小的Hello World复制答案,我将授予500声望分数。 - Tin Nguyen

0

我认为你不能在Heroku上运行一个服务,该服务可以使用docker命令来启动一些docker容器。

我想通过使用Heroku按钮部署来制作一个一键部署解决方案。

我认为你可以更新部署按钮的引用到一些自动化服务器(例如:已经部署在Heroku/另一个云上的Jenkins实例)来触发部署流程,不让人们与git/docker等进行交互。
但是,当不使用像Jenkins/CircleCI这样的流行解决方案时,你必须处理很多问题,比如安全性、参数等。


您可以在Heroku上部署Docker容器,请参考https://blog.heroku.com/build-docker-images-heroku-yml和https://devcenter.heroku.com/articles/build-docker-images-heroku-yml。但是,我想将多个Docker容器捆绑在单个容器中,如DinD(Docker in Docker)的精神所在。最好有一个正在运行自己Docker守护程序的Docker容器。 - Tin Nguyen

-2
我所做的是像这样在我的Dockerfile中安装它:
RUN curl -fsSLO https://get.docker.com/builds/Linux/x86_64/docker-17.04.0-ce.tgz \
  && tar xzvf docker-17.04.0-ce.tgz \
  && mv docker/docker /usr/local/bin \
  && rm -r docker docker-17.04.0-ce.tgz

然后在运行Docker的args部分中,我添加了这个:

args '--user root -v /var/run/docker.sock:/var/run/docker.sock'

如果想要深入了解为什么这个方法可行,请参考:stackoverflow.com/q/27879713/354577,但是这种方法对我来说效果很好。


2
我在我的问题中已经解答了这个问题。在Heroku上不能挂载/var/run/docker.sock - Tin Nguyen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接