Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

I want to pass the ec2 instance id of the machine it's running on as an environment variable to the docker container. (I want to avoid doing AWS specific stuff inside the container).

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.

Something like this (which doesn't work; it doesn't cause EB errors, but the env var is not available inside the container):

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.

like image 237
Shorn Avatar asked Jan 08 '23 14:01

Shorn


1 Answers

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.

Options #1: Check for AWS Metadata from your app

You can directly curl the AWS Metadata (http://169.254.169.254/latest/meta-data/instance-id) directly from your Docker container.

Run <code>curl -s http://169.254.169.254/latest/meta-data/instance-id</code> inside Elastic Beanstalk Docker container

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. FYI, 169.254.0.0/16 is a link-local address. You can also detect your app is in AWS or not.

Options #2: Inject Dockerfile with environment variable

Dockerfile can contain environment variable by using ENV keyword. We can inject a new environment variable using ENV into your Dockerfile. The environment variable injection your Dockerfile must be done after your app is extracted and before the Docker images is built.

Injecting Dockerfile can be done by adding a pre-app-deployment hook. Just create a new file inside the appdeploy/pre using .ebextensions:

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?

The container_commands will be executed just before the app is deployed as the documentation said that. It looks like promising, but we can't use it. The container_commands will be executed after the Dockerfile is built (docker build). To use environment variable in Dockerfile, we need to inject the ENV before run docker build.

Take a look into Elastic Beanstalk: Under the Hood. Here is the file structure of 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. 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. 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. You need to verify this "hack" can be run in the next platform version before you upgrade the production environment.

Actually, there any some other options to set instance id as environment variable. Such as: modifying the docker run line in enact/00run.sh. I also don't prefer to modify the EB script.

like image 190
Edward Samuel Avatar answered Jan 16 '23 22:01

Edward Samuel