【问题标题】:Elastic BeanStalk Docker app, writing local filesElastic BeanStalk Docker 应用程序,编写本地文件
【发布时间】:2017-04-10 18:35:51
【问题描述】:

我有一个 play scala 应用程序,我通过 AWS Elasticbeanstalk 控制台将其部署为通用 docker 应用程序。当我在本地运行应用程序时,我没有看到任何问题,所以我认为代码是正确的。 我需要有能力

  • 将文件写入本地磁盘
  • 在这些文件上运行一些命令行实用程序(如 ffmpeg)

但是,我的应用程序不写入本地磁盘,也不让我执行命令行实用程序。

 val localFile = new File(s"$localFilePath/$siteId/download/${fileName}.raw")
 s3Client.getObject(new GetObjectRequest(bucketName, summary.getKey), localFile)
 val cmd = s"ffmpeg -i ${localFile.getAbsolutePath} -vcodec copy ${localFile.getAbsolutePath}.mp4"
 cmd !;

这是我的 Dockerrun.aws.json 文件

{"AWSEBDockerrunVersion": "1","Logging": "/opt/docker/logs"}

更新 更新了我的 Dockerrun.aws.json 文件以包含卷映射

{"AWSEBDockerrunVersion": "1","Logging": "/opt/docker/logs","Volumes":[{"HostDirectory": "/tmp/files","ContainerDirectory": "/tmp/files"}]}

应用程序正在写入本地文件,但由于某种原因无法运行 ffmpeg。

Exception : Cannot run program "ffmpeg": error=2, No such file or directory

【问题讨论】:

  • “本地”运行是指在笔记本电脑的容器内还是完全在 Docker 之外?另外,您能否提供有关实际情况的更多信息?你有例外吗?代码是否运行但您没有看到输出文件?
  • locally = sbt run 在我的笔记本电脑上(不是通过 Docker) 实际上没有异常,它假装好像 s3Client.getObject 下载到 localfile ,但 ffmpeg 抱怨找不到输入文件.当我检查 EC2 实例时,我没有看到任何文件。
  • 如果您不使用 Docker 卷,您将看不到 EC2 实例中的文件。 Docker 容器有自己独立的文件系统。你能分享你的 Dockerfile 来帮助理解这个问题吗?这可能与您在容器内使用绝对路径有关。
  • 这是我的 Dockerrun.aws.json { "AWSEBDockerrunVersion": "1", "Logging": "/opt/docker/logs" }
  • 我的意思是 - 你的 Dockerfile。这是用于构建容器映像的内容。 Dockerrun 文件是 Beanstalk 用来从 Docker 映像部署容器的文件。你有 Dockerfile 吗?如果是这样,您可以将其粘贴到原始帖子中吗?如果没有,您的代码如何运行?根据您粘贴为 Dockerrun 文件的内容,Beanstalk 将不知道要运行哪个 Docker 容器。在此处查看官方文档:docs.aws.amazon.com/elasticbeanstalk/latest/dg/….

标签: scala amazon-web-services docker amazon-ec2 amazon-elastic-beanstalk


【解决方案1】:

TL;DR - 您的应用程序找不到 ffmpeg,因为您将其安装在 host 操作系统上,而您的代码在 container 操作系统中运行.要解决此问题,请通过编写自定义 Dockerfile 在您的容器中安装 ffmpeg

软件容器

现在,为了更好地理解您的问题,您必须了解软件容器是一种特殊的虚拟化。也就是说,容器内的操作系统与主机操作系统以及同一机器上的其他容器(无论是您的笔记本电脑还是 EC2 实例)完全分开。容器可能与主机操作系统或同一台机器上的其他容器共享一些信息,但是您需要执行显式操作才能实现这一点(即 Docker 卷)。

Docker 容器 是一种特定类型的软件容器。关于 Docker 和容器的一些基本信息可以在官方What is Docker 页面中找到。

容器与虚拟机

容器有点类似于虚拟机,但在我看来,两者之间的区别多于相似之处。它们的相似之处在于它们允许您在同一硬件上运行多个应用程序,而每个应用程序都有自己的独立虚拟环境。它们不同于虚拟化中的虚拟机种类 - 虽然虚拟机上的应用程序与同一主机上的其他应用程序共享相同的硬件,但容器内的应用程序共享主机的硬件和操作系统。

容器中的代码是隔离的!

Docker 容器利用 Linux 操作系统的specific capabilities 为每个应用程序提供一个几乎独立的环境。每个容器都生活在一个虚拟隔离的环境中,这让人感觉好像它有自己的文件系统、网络、进程 ID 等。这意味着容器内发生的任何事情都不会影响主机,反之亦然。

因此,在使用 Docker 容器时,您通常不会在 主机 上做太多事情。例如,在您的情况下,在主机上安装 ffmpeg 然后尝试从容器内使用它是错误的。即使有可能,它也违背了使用 Docker 的全部目的。正确的方法是将所有依赖项安装在 inside 容器中。它不仅可以解决您的No such file 问题,还可以让您在任何您喜欢的地方(AWS、GCP、您的笔记本电脑...)运行您的容器,并且始终以完全相同的方式运行。这种可移植性是容器所独有的,并且是人们使用容器的主要原因之一,因为它允许您的代码具有一致行为,因为它始终准确地运行相同的环境。

使用代码打包您的环境

另一种看待它的方式是 - 使用 Docker 时,您将执行环境与代码打包在一起。这是以一种非常有效和紧凑的方式完成的 - 使用 Dockerfile。您只需在代码所在的根目录中包含一个 Dockerfile。 Dockerfile 包含创建代码运行所需的环境所需的所有说明。在 Dockerfile 中,您可以安装依赖项、复制文件、更改权限以及执行许多其他操作。然后,您构建一个映像,您可以从中启动容器。

使用 Dockerfiles 还允许您版本控制您的依赖项,并提供一个很好的替代配置管理工具,如 Chef、Ansible 和 Puppet。

我建议你看看 Docker 网站上的official training videos。它们将使您更好地了解 Docker 是什么以及如何使用它。

结论

总之,如果您只是想在 Elastic Beanstalk 上运行代码,则不必使用 Docker。您可能可以让它在 Beanstalk 的 Java 环境中运行(尽管我自己从未这样做过)。但是,如果您想 Docker 化您的应用程序,您首先需要更好地了解 Docker,因为使用容器需要转变观点,而这并不总是容易做到的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-08
    • 2017-07-04
    • 2022-01-12
    • 2015-03-05
    • 2017-11-28
    • 2021-01-17
    • 2019-04-27
    • 2013-07-14
    相关资源
    最近更新 更多