Under the Hood of AWS Elastic Beanstalk Part 2

Tung Nguyen
BoltOps
3 min readJul 20, 2017

--

This a continuation of the last post: Under the Hood of Elastic Beanstalk Part 1.We’ll go over the EB nginx setup for the docker container in this post.

EB Docker on Upstart

First, the docker container is always kept running via the upstart config /etc/init/eb-docker.conf. If you kill the process, it’ll just come back up.

# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
163ebbeedede aws_beanstalk/current-app:latest "/bin/sh -c docker/b 19 hours ago Up 19 hours 3000/tcp hopeful_brattain
# docker stop 163ebbeedede
163ebbeedede
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
163ebbeedede aws_beanstalk/current-app:latest "/bin/sh -c docker/b 19 hours ago Up 1 seconds 3000/tcp hopeful_brattain
#

If you really want to stop it you’ll need to do so via upstart: stop eb-docker.

# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
163ebbeedede aws_beanstalk/current-app:latest "/bin/sh -c docker/b 19 hours ago Up 34 seconds 3000/tcp hopeful_brattain
# stop eb-docker
eb-docker stop/waiting
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# start eb-docker
eb-docker start/running, process 11090
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
163ebbeedede aws_beanstalk/current-app:latest "/bin/sh -c docker/b 19 hours ago Up 1 seconds 3000/tcp hopeful_brattain
#

Nginx Proxies to Docker Container

You can see that the normally running container listens to the port 3000 in this case. The container will expose the port that is configured in your Dockerfile or the Dockerrun.aws.json according to the AWS documentation. The script with that logic that selects the port to expose is actually located at /opt/elasticbeanstalk/hooks/appdeploy/enact/00run.sh. EB configures nginx to proxy port 80 to this exposed container port with this config file: /etc/nginx/conf.d/elasticbeanstalk-nginx-docker-upstream.conf

We can curl the docker port directly.

# curl -s -v -o /dev/null 172.17.0.9:3000 2>&1  | grep '< HTTP'
< HTTP/1.1 200 OK
#

We can also curl nginx port 80 to make sure the proxy is working all the way from nginx to the container.

# curl -s -v -o /dev/null localhost:80 2>&1  | grep '< HTTP'
< HTTP/1.1 200 OK
#

Configure Docker Container Server Concurrency

Configuring nginx to proxy to another webserver is pretty typically. Unicorn and puma are commonly use and they are configured so that they have multiple processes or threads to handle concurrency. In the EB case, nginx proxies to the server within the docker container itself. Knowing this, it is important for scaling reasons that the docker container server is configured for concurrency properly. You’ll want to configure your container to have the right number of workers or threads to maximize the RAM and CPU on the instance efficiently. EB is usually used to run only docker container on each AWS instance. So it is crucial that we configure that docker container’s server to run more than 1 process or thread or else we’ll be likely wasting resources and worse not scale.

Each application is different in how it consumes CPU and uses RAM so you’ll have to play with it. Here are simple examples for unicorn and puma.

ELB

Lastly, EB sets up and ELB so traffic gets load balanced to port 80 on each instances in the environment. So the overall routing goes: client -> ELB > nginx -> docker.

Curl the ELB endpoint to make sure that it’s working all the way from the ELB to nginx to docker.

$ curl -s -v -o /dev/null "http://your-custom-endpoint.elasticbeanstalk.com" 2>&1 | grep '< HTTP'
< HTTP/1.1 200 OK
$

Thanks for reading this far. If you found this post useful, I’d really appreciate it if you recommend this post (by clicking the clap button) so others can find it too! Also, connect with me on LinkedIn.

P.S. Be sure to join the BoltOps newsletter to receive free DevOps tips and updates.

You might also like:

--

--