如何使用非默认运行参数在 AWS Elastic Beanstalk 中运行 Docker 容器?

Posted

技术标签:

【中文标题】如何使用非默认运行参数在 AWS Elastic Beanstalk 中运行 Docker 容器?【英文标题】:How can I run a Docker container in AWS Elastic Beanstalk with non-default run parameters? 【发布时间】:2015-03-31 18:57:25 【问题描述】:

我有一个 Docker 容器,它在我的本地开发机器上运行良好。我想将其移至 AWS Elastic Beanstalk,但我遇到了一些麻烦。

我正在尝试使用s3fsS3 存储桶安装到我的容器中。我有 Dockerfile:

FROM tomcat:7.0
MAINTAINER me@example.com

RUN apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential libfuse-dev libcurl4-openssl-dev libxml++2.6-dev libssl-dev mime-support automake libtool wget tar 

# Add the java source
ADD . /path/to/tomcat/webapps/
ADD run_docker.sh /root/run_docker.sh
WORKDIR $CATALINA_HOME

EXPOSE 8080

CMD ["/root/run_docker.sh"]

然后我安装s3fs,挂载S3 存储桶,并在创建映像后运行Tomcat 服务器,方法是运行run_docker.sh

#!/bin/bash
#run_docker.sh

wget https://github.com/s3fs-fuse/s3fs-fuse/archive/master.zip -O /usr/src/master.zip;
cd /usr/src/;
unzip /usr/src/master.zip;
cd /usr/src/s3fs-fuse-master;
autoreconf --install;
CPPFLAGS=-I/usr/include/libxml2/ /usr/src/s3fs-fuse-master/configure;
make;
make install;
cd $CATALINA_HOME;

mkdir /opt/s3-files;
s3fs my-bucket /opt/s3-files;
catalina.sh run

当我使用命令构建和运行这个 Docker 容器时:

docker run --cap-add mknod --cap-add sys_admin --device=/dev/fuse -p 80:8080 -d username/mycontainer:latest

效果很好。然而,当我删除 --cap-add mknod --cap-add sys_admin --device=/dev/fuse 时,s3fs 无法挂载我的 S3 存储桶。

现在,我想在 AWS Elastic Beanstalk 上运行它,当我部署容器(并运行 run_docker.sh)时,所有步骤都可以正常执行,除了run_docker.sh中的步骤s3fs my-bucket /opt/s3-files无法挂载bucket。

这大概是因为无论 Elastic Beanstalk 为运行 Docker 容器做什么,它都不会添加任何额外的标志,例如 --cap-add mknod --cap-add sys_admin --device=/dev/fuse

我的Dockerrun.aws.json 文件如下所示:


  "AWSEBDockerrunVersion": "1",
  "Image": 
    "Name": "tomcat:7.0"
  ,
  "Ports": [
    
      "ContainerPort": "8080"
    
  ]

是否可以向 AWS EB Docker 部署添加额外的 docker run 标志? 另一种选择是找到另一种安装S3 存储桶的方法,但我怀疑无论如何我都会遇到类似的权限错误。有没有人看到任何方法来做到这一点???

更新:

对于尝试使用以下@Egor 答案的人,当EB 配置设置为使用v1.4.0 running Docker 1.6.0 时,它可以工作。超过 v1.4.0 版本的任何内容都会失败。所以要让它工作,像平常一样构建你的环境(这应该会给你一个失败的构建),然后用 v1.4.0 running Docker 1.6.0 配置重建它。应该这样做!

【问题讨论】:

如何使用“1.4.0 running Docker 1.6.0”配置重建环境? EB 控制台似乎没有提供此选项,文档也没有。 【参考方案1】:

添加文件.ebextensions/01-commands.config

container_commands:
    00001-docker-privileged: command: 'sed -i "s/docker run -d/docker run --privileged -d/" /opt/elasticbeanstalk/hooks/appdeploy/pre/04run.sh'

我也在用 s3fs

【讨论】:

有趣。 04run.sh 这里是什么?这是否特定于您的环境/设置?还是 docker run 步骤只是 EB 所做的第四步? gist.github.com/yurtaev/1e8d639cb03bbb95e71a#file-04run-sh 是 EB 的特定文件 这 - 不幸 - 不适合我。我看到04run.sh 已修改并包含--privileged 标志,但日志状态为:fuse: failed to open /dev/fuse: Operation not permitted。有什么想法吗? 小更新。我 ssh 进入 EB 上的主机实例,停止 Docker 容器,将其删除,然后使用 --privileged 标志重新运行它;那行得通。所以看起来sed 命令在04run.sh 运行之前没有被执行。 我遇到了与@Brett 相同的问题,我得到了不允许的操作。有没有这方面的新信息?【参考方案2】:

如果您使用的是最新版本的 aws docker stack(例如 docker 1.7.1),则需要稍微修改上述答案。试试这个:

commands:
    00001_add_privileged:
        cwd: /tmp
        command: 'sed -i "s/docker run -d/docker run --privileged -d/" /opt/elasticbeanstalk/hooks/appdeploy/enact/00run.sh'

注意运行脚本位置&&名称的变化

【讨论】:

我一直想知道如何做到这一点,太棒了。就我而言,我试图将 args 传递给公共 docker 镜像仓库,所以我使用了 command: 'sed -i "s/\$EB_CONFIG_DOCKER_IMAGE_STAGING/\$EB_CONFIG_DOCKER_IMAGE_STAGING -gzip -enable-url-source/" /opt/elasticbeanstalk/hooks/appdeploy/enact/00run.sh' 太棒了。很高兴它可以提供帮助。【参考方案3】:

您现在可以使用任务定义添加功能。以下是文档: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html

这就是您要添加到任务定义中的具体内容:

"linuxParameters": 
    "capabilities": 
      "add": [
        "SYS_PTRACE"
      ]
    
  ,

【讨论】:

【参考方案4】:

感谢 elijahchancey 的回答,这很有帮助。我想补充一点小评论:

Elasticbeanstalk 现在正在使用 ECS 任务来部署和管理应用程序集群。 Multicontainer Docker Configuration docs 中有一个非常重要的段落(我最初错过了)。

以下示例显示了常用参数的子集。更多可选参数可用。有关任务定义格式的更多信息和任务定义参数的完整列表,请参阅 Amazon ECS 开发人员指南中的 Amazon ECS Task Definitions。

所以该文档不是完整的参考,但它只是显示典型条目,您应该在其他地方找到更多。这会产生相当大的影响,因为现在(2018 年)您可以指定更多选项,并且不再需要破解 ebextensions。您唯一需要做的就是在您的多泊坞窗Dockerrun.aws.jsoncontainerDefinitions 中使用任务参数。

这在单个 docker 容器中没有提到,但可以尝试验证...

带有额外上限的多 docker Dockerrun.aws.json 示例:


  "AWSEBDockerrunVersion": 2,
  "containerDefinitions": [
    
      "name": "service1",
      "image": "myapp/service1:latest",
      "essential": true,
      "memoryReservation": 128,
      "portMappings": [
        
          "hostPort": 8080,
          "containerPort": 8080
        
      ],
      "linuxParameters": 
        "capabilities": 
          "add": [
            "SYS_PTRACE"
          ]
        
      
    
  ]

【讨论】:

以上是关于如何使用非默认运行参数在 AWS Elastic Beanstalk 中运行 Docker 容器?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 AWS Elastic Beanstalk 在 URL 中运行带有参数的 PHP 脚本?

非 www 到 www 使用 AWS Elastic Load Balancer 和 Nginx

如何在 AWS Elastic Beanstalk 上使用 Resque 运行 Rails 后台作业?

Symfony 4 在 AWS Elastic Beanstalk 上运行

如何在 aws elastic beanstalk 环境实例启动上运行 shell 脚本

如何在运行 AWS Linux 2 的 AWS Elastic Beanstalk 上配置 Linux 交换空间?