How to customize the docker run command on Elastic Beanstalk? How to customize the docker run command on Elastic Beanstalk? docker docker

How to customize the docker run command on Elastic Beanstalk?


I ended up fixing it with two container commands

container_commands:  00_fix_networking:    command: sed -i 's/docker run -d/docker run --net=host -d/' /opt/elasticbeanstalk/hooks/appdeploy/enact/00run.sh  01_fix_docker_ip:    command: sed -i 's/server $EB_CONFIG_NGINX_UPSTREAM_IP/server localhost/' /opt/elasticbeanstalk/hooks/appdeploy/enact/01flip.sh

Update: I also had to fix the Upstart script. Unfortunately, I didn't write down what I did because I didn't end up needing to alter the docker run command. You would do a files directive for (I think) /etc/init/docker. AWS edits the Nginx configuration in the same manner as in 01flip.sh in that file as well.


Explanation:

In the 64bit Amazon Linux 2015.03 v2.0.2 running Docker 1.7.1 platform version, the file you need to edit is /opt/elasticbeanstalk/hooks/appdeploy/enact/00run.sh. This file is now far more complex than Samar's version so I didn't want to put the actual contents in there. However, the change is basically the same. There's the line that starts with

docker run -d

I fixed it with a container command:

container_commands:  00_fix_networking:    command: sed -i 's/docker run -d/docker run --net=host -d/' /opt/elasticbeanstalk/hooks/appdeploy/enact/00run.sh

This successfully adds the --net=host argument but now there's another problem. The system ends up with an invalid Nginx directive. Using --net=host means that when you run docker inspect <container id> there is no IP address in the NetworkSettings. AWS uses this to create the server directive for Nginx and ends up generating server :<some port you chose> (before adding --net=host it would look like server <ip>:<port>). I needed to patch that file, too. It's generated in /opt/elasticbeanstalk/hooks/appdeploy/enact/01flip.sh.

01_fix_docker_ip:  command: sed -i 's/server $EB_CONFIG_NGINX_UPSTREAM_IP/server localhost/' /opt/elasticbeanstalk/hooks/appdeploy/enact/01flip.sh


While elastic beanstalk is generally well suited for applications that work with standard set of configurations, its difficult to customize and keep things updated along with the updates AWS provides to EB stacks. Having said that, I've done something like below which is a bit hacky but works fine.

files:    "/opt/elasticbeanstalk/hooks/appdeploy/pre/04run.sh":      mode: "000755"      owner: root      group: root      encoding: plain      content: |        #script content of original 04run.sh along with modification on docker run cmd        # eg. I injected multi-ports here        docker run -d \               "${EB_CONFIG_DOCKER_ENV_ARGS[@]}" \               "${EB_CONFIG_DOCKER_VOLUME_MOUNTS[@]}" \               "${EB_CONFIG_DOCKER_ENTRYPOINT_ARGS[@]}" \               "${PORT_ARGS[@]}" \               $EB_CONFIG_DOCKER_IMAGE_STAGING \               "${EB_CONFIG_DOCKER_COMMAND_ARGS[@]}" 2>&1 | tee /tmp/docker_run.log | tee $EB_CONFIG_DOCKER_STAGING_APP_FILE

This is not very neat, at least I have to make sure that it does not break with updates on elastic beanstalk. The above one is for docker 1.5 stack but you can do something similar with the version you're running.


Note that the latest version of the AWS stack (with Docker 1.7.1) has a slightly different pre-deploy setup. You'll need to update the file at the location: /opt/elasticbeanstalk/hooks/appdeploy/enact/00run.sh

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

or, for example, if you want to pass args to your Docker image:

commands:    00001_modify_docker_run:        cwd: /tmp        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'