[英]How can I set a per-instance env variable for an elastic beanstalk docker container?
Our elastic single-container beanstalk docker application runs as load balanced with multiple ec2 instances. 我们的弹性单容器beanstalk docker应用程序在与多个ec2实例进行负载平衡时运行。
I want to pass the ec2 instance id of the machine it's running on as an environment variable to the docker container. 我想将它运行的机器的ec2实例id作为环境变量传递给docker容器。 (I want to avoid doing AWS specific stuff inside the container).
(我想避免在容器内部执行AWS特定的东西)。
I figure I need to put something in an .ebextension config file, where I do a curl to get the instance data and then set it into an environment variable that will be passed to the docker container. 我想我需要在.ebextension配置文件中放置一些东西,在那里我做一个curl来获取实例数据,然后将它设置为一个环境变量,它将被传递给docker容器。
Something like this (which doesn't work; it doesn't cause EB errors, but the env var is not available inside the container): 像这样的东西(它不起作用;它不会导致EB错误,但容器内的env var不可用):
container_commands:
set_instance_id:
command: export EC2_INSTANCE_ID=`curl -s http://169.254.169.254/latest/meta-data/instance-id`
Ideally, I'd like to avoid hacking the EB run scripts, because they're undocumented and seem to change without notice. 理想情况下,我想避免黑客攻击EB运行脚本,因为它们没有文档,似乎在没有通知的情况下发生变化。
Unfortunately, at this moment, you can not do the thing that you want without cluttering your app with AWS specific stuff or modifying the EB script/deployment process. 不幸的是,此时此刻,如果不使用AWS特定内容或修改EB脚本/部署过程使您的应用程序混乱,您就无法做到您想要的事情。
Options #1: Check for AWS Metadata from your app 选项#1:从您的应用中检查AWS元数据
You can directly curl
the AWS Metadata ( http://169.254.169.254/latest/meta-data/instance-id ) directly from your Docker container. 您可以直接从Docker容器直接
curl
AWS Metadata( http://169.254.169.254/latest/meta-data/instance-id )。
From your app, if there is no environment name EC2_INSTANCE_ID
(or anything you want), just call the AWS metadata service to get the instance id. 在您的应用中,如果没有环境名称
EC2_INSTANCE_ID
(或您想要的任何内容),只需调用AWS元数据服务即可获取实例ID。 FYI, 169.254.0.0/16 is a link-local address . 仅供参考,169.254.0.0 / 16是本地链接地址 。 You can also detect your app is in AWS or not .
您还可以检测您的应用是否在AWS中 。
Options #2: Inject Dockerfile with environment variable 选项#2:使用环境变量注入Dockerfile
Dockerfile can contain environment variable by using ENV
keyword. Dockerfile可以使用
ENV
关键字包含环境变量。 We can inject a new environment variable using ENV
into your Dockerfile. 我们可以使用
ENV
将新的环境变量注入Dockerfile。 The environment variable injection your Dockerfile must be done after your app is extracted and before the Docker images is built. 必须在提取应用程序之后和构建Docker镜像之前注入Dockerfile的环境变量。
Injecting Dockerfile can be done by adding a pre-app-deployment hook . 注入Dockerfile可以通过添加pre-app-deployment钩子来完成 。 Just create a new file inside the
appdeploy/pre
using .ebextensions
: 只需使用
.ebextensions
在appdeploy/pre
创建一个新文件:
files:
"/opt/elasticbeanstalk/hooks/appdeploy/pre/02injectdockerfile.sh":
mode: "000755"
content: |
. /opt/elasticbeanstalk/hooks/common.sh
EB_CONFIG_APP_CURRENT=$(/opt/elasticbeanstalk/bin/get-config container -k app_deploy_dir)
cd $EB_CONFIG_APP_CURRENT
echo "ENV EC2_INSTANCE_ID \"`curl -s http://169.254.169.254/latest/meta-data/instance-id`\"" >> Dockerfile
Why must it be done in pre-appdeploy? 为什么必须在预应用程序中完成? Or can we just use
container_commands
? 或者我们可以只使用
container_commands
吗?
The container_commands
will be executed just before the app is deployed as the documentation said that. 如文档所说,
container_commands
将在应用程序部署之前执行。 It looks like promising, but we can't use it. 它看起来很有希望,但我们不能使用它。 The
container_commands
will be executed after the Dockerfile is built ( docker build
). 该
container_commands
的Dockerfile建成(之后将被执行docker build
)。 To use environment variable in Dockerfile, we need to inject the ENV
before run docker build
. 要在Dockerfile中使用环境变量,我们需要在运行
docker build
之前注入ENV
。
Take a look into Elastic Beanstalk: Under the Hood . 看看Elastic Beanstalk:在胡德之下 。 Here is the file structure of appdeploy hook:
这是appdeploy hook的文件结构:
[ec2-user@ip-172-31-62-137 ~]$ tree /opt/elasticbeanstalk/hooks/appdeploy/
/opt/elasticbeanstalk/hooks/appdeploy/
├── enact
│ ├── 00run.sh
│ └── 01flip.sh
├── post
│ └── 01_monitor_pids.sh
└── pre
├── 00clean_dir.sh
├── 01unzip.sh
├── 02docker_db_check.sh
└── 03build.sh
The app file is extracted in pre/01unzip.sh
and docker build
is executed in pre/03build.sh
. 应用程序文件在
pre/01unzip.sh
压缩, pre/01unzip.sh
docker build
在pre/03build.sh
执行。 So, we need add a new script to inject the ENV
with the script file name order is after 01unzip.sh
and before 03build.sh
. 因此,我们需要添加一个新脚本来注入
ENV
,脚本文件名顺序是在01unzip.sh
之后和03build.sh
之前。 As you said, this is undocumented and might be changed. 正如你所说,这是无证的,可能会改变。 But, I thought, it should not be changed if you use same Elastic Beanstalk platform version.
但是,我想,如果你使用相同的Elastic Beanstalk平台版本,就不应该改变它。 You need to verify this "hack" can be run in the next platform version before you upgrade the production environment.
在升级生产环境之前,您需要验证此“hack”是否可以在下一个平台版本中运行。
Actually, there any some other options to set instance id as environment variable. 实际上,还有其他一些选项可以将实例id设置为环境变量。 Such as: modifying the
docker run
line in enact/00run.sh
. 如:在
enact/00run.sh
修改enact/00run.sh
docker run
line。 I also don't prefer to modify the EB script. 我也不喜欢修改EB脚本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.