AWS Elastic Beanstalk feat. Docker for Deploying Simple Web App
Tags: aws, beanstalk, docker, container
Published: 2022-06-18 07:23:00

On June 16th which is two days ago, I noticed that AWS Elastic Beanstalk is available in the Indonesia (Jakarta) region. Since I've never used this service, so I wanted to explore it. The most interesting part (for me) is EB CLI. The command line tool to manage the environments but it's used separately from AWS CLI.


![Beanstalk](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rq0hom9mlm3vnp9zyigx.png)

## What's AWS Elastic Beanstalk?

So basically, it's an easy-to-use service to deploy and manage applications without worrying about the infrastructure. Yes, it's easy! Why? All we need to do is upload the code and Beanstalk will do the rest for deploying and provisioning the infrastructure. Capacity, load balancing, scaling and health monitoring? Let the Beanstalk do all those things for you!

More about [AWS Elastic Beanstalk](https://docs.aws.amazon.com/elastic-beanstalk/index.html).

## Preparation

* Install EB CLI
    
* Docker code (Docker Compose, Dockerrun (JSON), Dockerfile)
    
* Docker image (you can use my custom image [here](https://hub.docker.com/r/nurulramadhona/httpd))
    

## How To Install EB CLI

* Clone the repository [here](https://github.com/aws/aws-elastic-beanstalk-cli-setup)
    
* Install the prerequisites (Git, Python, virtualenv). In this case, I've installed Git and Python. So here I'll show you how to install virtualenv using pipx if you already have Python 3.5+
    

```bash
$ sudo apt install python3.8-venv
$ sudo apt install pipx
$ pipx install virtualenv
  installed package virtualenv 20.14.1, Python 3.8.10
  These binaries are now globally available
    - virtualenv
done! ✨ 🌟 ✨
$ git clone https://github.com/aws/aws-elastic-beanstalk-cli-setup.git
$ python3 ./aws-elastic-beanstalk-cli-setup/scripts/ebcli_installer.py
Success!
```

Run the command below to complete the installation: (replace `/home/nurulramadhona` with yours)

```bash
$ echo 'export PATH="/home/nurulramadhona/.ebcli-virtual-env/executables:$PATH"' >> ~/.bash_profile && source ~/.bash_profile
```

Once you have run it once, you just need to take the last part anytime you want to run the `eb` command or if it doesn't it will be out as not found.

```bash
$ source ~/.bash_profile
```

## Docker Code

Here I'll use all three kinds of files that can be used to deploy Docker on Beanstalk.

* Docker Compose (docker-compose.yml)
    

```yaml
version: '3.8'
services:
  docker-httpd:
    image: "nurulramadhona/httpd:eb"
    ports:
      - "80:80"
```

* AWS JSON File (Dockerrun.aws.json)
    

```json
{
  "AWSEBDockerrunVersion": "1",
  "Image": {
    "Name": "nurulramadhona/httpd:eb",
    "Update": "true"
  },
  "Ports": [
    {
      "ContainerPort": "80"
    }
  ]
}
```

* Dockerfile
    

```bash
FROM nurulramadhona/httpd:eb
EXPOSE 80
```

## Deployment Scenario

1. Create an app named `docker-httpd`
    
2. Create a default (first) environment named `docker-httpd-1` using Docker Compose
    
3. Create a second environment named `docker-httpd-2` using JSON file
    
4. Update the application version of the default environment using Dockerfile
    
5. Cleanup
    

**1\. Create an app named docker-httpd**

Don't forget to specify the region (by default us-west-2)!

```bash
docker-httpd$ ls
docker-compose.yml
docker-httpd$ eb init -p docker docker-httpd --region ap-southeast-3
Application docker-httpd has been created.
```

Since we're not creating any environment yet, it will be shown below (no default environment):

```bash
docker-httpd$ cat .elasticbeanstalk/config.yml
branch-defaults:
  default:
    environment: null
    group_suffix: null
global:
  application_name: docker-httpd
  branch: null
  default_ec2_keyname: null
  default_platform: Docker
  default_region: ap-southeast-3
  include_git_submodules: true
  instance_profile: null
  platform_name: null
  platform_version: null
  profile: null
  repository: null
  sc: null
  workspace_type: Application
```

**2\. Create default (first) environment named docker-httpd-1 using Docker Compose**

```bash
docker-httpd$ eb create docker-httpd-1
Creating application version archive "app-220617_211333370958".
Uploading docker-httpd/app-220617_211333370958.zip to S3. This may take a while.
Upload Complete.
Environment details for: docker-httpd-1
  Application name: docker-httpd
  Region: ap-southeast-3
  Deployed Version: app-220617_211333370958
  Environment ID: e-z63ppcgfaz
  Platform: arn:aws:elasticbeanstalk:ap-southeast-3::platform/Docker running on 64bit Amazon Linux 2/3.4.16
  Tier: WebServer-Standard-1.0
  CNAME: UNKNOWN
  Updated: 2022-06-17 14:13:35.987000+00:00
Printing Status:
2022-06-17 14:13:34    INFO    createEnvironment is starting.
2022-06-17 14:13:36    INFO    Using elasticbeanstalk-ap-southeast-3-0123456789 as Amazon S3 storage bucket for environment data.
2022-06-17 14:14:01    INFO    Created security group named: sg-0f99f2ab062ebe5c9
2022-06-17 14:14:01    INFO    Created load balancer named: awseb-e-z-AWSEBLoa-1E4YND1PICBNS
2022-06-17 14:14:01    INFO    Created security group named: awseb-e-z63ppcgfaz-stack-AWSEBSecurityGroup-2LXB5URL2CCF
2022-06-17 14:14:04    INFO    Created Auto Scaling launch configuration named: awseb-e-z63ppcgfaz-stack-AWSEBAutoScalingLaunchConfiguration-D8PQPWW5Y1KA
2022-06-17 14:14:50    INFO    Created Auto Scaling group named: awseb-e-z63ppcgfaz-stack-AWSEBAutoScalingGroup-1PBPMIY0QO6SJ
2022-06-17 14:14:50    INFO    Waiting for EC2 instances to launch. This may take a few minutes.
2022-06-17 14:14:51    INFO    Created Auto Scaling group policy named: arn:aws:autoscaling:ap-southeast-3:0123456789:scalingPolicy:5695560d-c4e9-4c00-a62f-5627a18292eb:autoScalingGroupName/awseb-e-z63ppcgfaz-stack-AWSEBAutoScalingGroup-1PBPMIY0QO6SJ:policyName/awseb-e-z63ppcgfaz-stack-AWSEBAutoScalingScaleUpPolicy-5TXO4SOR1647
2022-06-17 14:14:51    INFO    Created Auto Scaling group policy named: arn:aws:autoscaling:ap-southeast-3:0123456789:scalingPolicy:aad4ed86-b263-4cf2-8f17-0b662f276158:autoScalingGroupName/awseb-e-z63ppcgfaz-stack-AWSEBAutoScalingGroup-1PBPMIY0QO6SJ:policyName/awseb-e-z63ppcgfaz-stack-AWSEBAutoScalingScaleDownPolicy-1BK8R8A0N83FE
2022-06-17 14:14:51    INFO    Created CloudWatch alarm named: awseb-e-z63ppcgfaz-stack-AWSEBCloudwatchAlarmHigh-1D7JBUMLBSEOH
2022-06-17 14:14:51    INFO    Created CloudWatch alarm named: awseb-e-z63ppcgfaz-stack-AWSEBCloudwatchAlarmLow-1W0MKMBWE1Q7Y
2022-06-17 14:15:09    INFO    Instance deployment completed successfully.
2022-06-17 14:15:39    INFO    Application available at docker-httpd-1.eba-rdewef8v.ap-southeast-3.elasticbeanstalk.com.
2022-06-17 14:15:40    INFO    Successfully launched environment: docker-httpd-1
```

When we create the environment, we also can see the list of services created by Beanstalk. Those are S3 bucket, security group, ELB (a classic by default), ASG, EC2 instance, CloudWatch and SNS.

Then since it's the first environment to be created, it will be the default environment. So when we run `eb` command without specifying the environment's name, it will refer to this environment.

For example:

```bash
docker-httpd$ eb status
Environment details for: docker-httpd-1
  Application name: docker-httpd
  Region: ap-southeast-3
  Deployed Version: app-220617_213146077755
  Environment ID: e-z63ppcgfaz
  Platform: arn:aws:elasticbeanstalk:ap-southeast-3::platform/Docker running on 64bit Amazon Linux 2/3.4.16
  Tier: WebServer-Standard-1.0
  CNAME: docker-httpd-1.eba-rdewef8v.ap-southeast-3.elasticbeanstalk.com
  Updated: 2022-06-17 14:32:10.908000+00:00
  Status: Ready
  Health: Green
```

Let's try to create one more environment to see the difference!

**3\. Create second environtment named docker-httpd-2 using JSON file**

Remove the Docker Compose file that was used to create the previous environment and replace it with Dockerfile.

```bash
docker-httpd$ rm docker-compose.yml 
docker-httpd$ cp ~/Documents/Dockerrun.aws.json .
docker-httpd$ ls
Dockerrun.aws.json
docker-httpd$ eb create docker-httpd-2
Creating application version archive "app-220617_212526081764".
Uploading docker-httpd/app-220617_212526081764.zip to S3. This may take a while.
Upload Complete.
Environment details for: docker-httpd-2
  Application name: docker-httpd
  Region: ap-southeast-3
  Deployed Version: app-220617_212526081764
  Environment ID: e-ymggxu7mai
  Platform: arn:aws:elasticbeanstalk:ap-southeast-3::platform/Docker running on 64bit Amazon Linux 2/3.4.16
  Tier: WebServer-Standard-1.0
  CNAME: UNKNOWN
  Updated: 2022-06-17 14:25:28.486000+00:00
Printing Status:
2022-06-17 14:25:27    INFO    createEnvironment is starting.
2022-06-17 14:25:28    INFO    Using elasticbeanstalk-ap-southeast-3-0123456789 as Amazon S3 storage bucket for environment data.
2022-06-17 14:25:47    INFO    Created security group named: sg-06d732826fb0be349
2022-06-17 14:25:47    INFO    Created load balancer named: awseb-e-y-AWSEBLoa-165JPKXMH3INE
2022-06-17 14:25:47    INFO    Created security group named: awseb-e-ymggxu7mai-stack-AWSEBSecurityGroup-109X7DG8OVDK4
2022-06-17 14:25:50    INFO    Created Auto Scaling launch configuration named: awseb-e-ymggxu7mai-stack-AWSEBAutoScalingLaunchConfiguration-8LOZJ395SOJH
2022-06-17 14:26:21    INFO    Created Auto Scaling group named: awseb-e-ymggxu7mai-stack-AWSEBAutoScalingGroup-CTHY5BO16CT1
2022-06-17 14:26:21    INFO    Waiting for EC2 instances to launch. This may take a few minutes.
2022-06-17 14:26:37    INFO    Created Auto Scaling group policy named: arn:aws:autoscaling:ap-southeast-3:0123456789:scalingPolicy:3ae34021-b577-470e-a493-8f4d88eda4dc:autoScalingGroupName/awseb-e-ymggxu7mai-stack-AWSEBAutoScalingGroup-CTHY5BO16CT1:policyName/awseb-e-ymggxu7mai-stack-AWSEBAutoScalingScaleDownPolicy-1KY50QYHQU7OG
2022-06-17 14:26:37    INFO    Created Auto Scaling group policy named: arn:aws:autoscaling:ap-southeast-3:0123456789:scalingPolicy:ced74c25-be73-400d-a091-0dc729bea30a:autoScalingGroupName/awseb-e-ymggxu7mai-stack-AWSEBAutoScalingGroup-CTHY5BO16CT1:policyName/awseb-e-ymggxu7mai-stack-AWSEBAutoScalingScaleUpPolicy-UNTK443C5E5G
2022-06-17 14:26:37    INFO    Created CloudWatch alarm named: awseb-e-ymggxu7mai-stack-AWSEBCloudwatchAlarmHigh-19INLYY0IX1XT
2022-06-17 14:26:37    INFO    Created CloudWatch alarm named: awseb-e-ymggxu7mai-stack-AWSEBCloudwatchAlarmLow-HMS29K3VMYEK
2022-06-17 14:26:57    INFO    Instance deployment completed successfully.
2022-06-17 14:27:11    INFO    Application available at docker-httpd-2.eba-rdewef8v.ap-southeast-3.elasticbeanstalk.com.
2022-06-17 14:27:11    INFO    Successfully launched environment: docker-httpd-2
```

Then, let's access the web from the provided URL!

```bash
docker-httpd$ eb open docker-httpd-2
docker-httpd$ curl docker-httpd-2.eba-rdewef8v.ap-southeast-3.elasticbeanstalk.com
<html><body><h1>AWS Elastic Beanstalk is now available in the Asia Pacific (Jakarta) Region</h1></body></html>
```

Below is the automatic output opened on the web browser when we run `eb open docker-httpd-2` command:

![Web 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d802nhew1jmlfqr84rue.png)

By the way, the URL or CNAME is under the same format: `env-name.eba-rdewef8v.ap-southeast-3.elasticbeanstalk.com`

```bash
2022-06-17 14:15:39    INFO    Application available at docker-httpd-1.eba-rdewef8v.ap-southeast-3.elasticbeanstalk.com.
2022-06-17 14:27:11    INFO    Application available at docker-httpd-2.eba-rdewef8v.ap-southeast-3.elasticbeanstalk.com.
```

**4\. Update the application version of the default environment using Dockerfile**

So we have two environments now. Then, we will make any changes without destroying the existing environment. This action can be done with `eb` command and is similar as we upload a new application version and deploying to the specific environment through the Console. We will replace it with Dockerfile now since we have done with Docker Compose and JSON files before.

```bash
docker-httpd$ rm Dockerrun.aws.json 
docker-httpd$ cp ~/Documents/Dockerfile .
docker-httpd$ eb deploy
Creating application version archive "app-220617_213146077755".
Uploading docker-httpd/app-220617_213146077755.zip to S3. This may take a while.
Upload Complete.
2022-06-17 14:31:47    INFO    Environment update is starting.      
2022-06-17 14:31:50    INFO    Deploying new version to instance(s).
2022-06-17 14:32:07    INFO    Instance deployment completed successfully.
2022-06-17 14:32:10    INFO    New application version was deployed to running EC2 instances.
2022-06-17 14:32:10    INFO    Environment update completed successfully.
                                                                      
docker-httpd$ curl docker-httpd-1.eba-rdewef8v.ap-southeast-3.elasticbeanstalk.com
<html><body><h1>AWS Elastic Beanstalk is now available in the Asia Pacific (Jakarta) Region</h1></body></html>
docker-httpd$ eb open
```

![Web 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4gvv2buz94jtxg7fpllq.png)

We also can run any other `eb` commands to manage the environment such as `eb events`, `eb config`, `eb health`, etc.

```bash
docker-httpd$ eb logs --all
Retrieving logs...
Logs were saved to /media/nurulramadhona/ops/docker-httpd/.elasticbeanstalk/logs/220617_215923
Logs were saved to /media/nurulramadhona/ops/docker-httpd/.elasticbeanstalk/logs/220617_215923
Updated symlink at /media/nurulramadhona/ops/docker-httpd/.elasticbeanstalk/logs/latest
docker-httpd$ eb health docker-httpd-2
 docker-httpd-2                                                                   Ok                                                                  2022-06-17 21:57:59WebServer                                                                                                                   Docker running on 64bit Amazon Linux 2/3.4.16  total      ok    warning  degraded  severe    info   pending  unknown 
    1        1        0        0        0        0        0        0    

  instance-id           status     cause                                                                                                                         health  
    Overall             Ok                
  i-0a935fb414a0bf7b5   Ok                
   
  instance-id           r/sec    %2xx   %3xx   %4xx   %5xx      p99      p90      p75     p50     p10                                                          requests  
    Overall             0.0         -      -      -      -         -        -       -       -       -
  i-0a935fb414a0bf7b5   0.0         -      -      -      -         -        -       -       -       -
   
  instance-id           type       az   running     load 1  load 5      user %  nice %  system %  idle %   iowait %                                                 cpu  
  i-0a935fb414a0bf7b5   t3.micro   3a   32 mins       0.02    0.02         0.1     0.0       0.0    99.9        0.0
   
  instance-id           status     id   version                   ago                                                                                       deployments  
  i-0a935fb414a0bf7b5   Deployed   1    app-220617_212526081764   31 mins
```

**5\. Cleanup**

As I mentioned above, there are list of services that are created for us when we create an environment but not all parts of the Beanstalk application will be deleted when we terminate the environment or even the application itself.

Before that, let's terminate both environments we have created above!

```bash
docker-httpd$ eb terminate docker-httpd-2
The environment "docker-httpd-2" and all associated instances will be terminated.
To confirm, type the environment name: docker-httpd-2
2022-06-17 15:08:04    INFO    terminateEnvironment is starting.
2022-06-17 15:08:21    INFO    Deleted CloudWatch alarm named: awseb-e-ymggxu7mai-stack-AWSEBCloudwatchAlarmLow-HMS29K3VMYEK 
2022-06-17 15:08:21    INFO    Deleted CloudWatch alarm named: awseb-e-ymggxu7mai-stack-AWSEBCloudwatchAlarmHigh-19INLYY0IX1XT 
2022-06-17 15:08:21    INFO    Deleted Auto Scaling group policy named: arn:aws:autoscaling:ap-southeast-3:0123456789:scalingPolicy:ced74c25-be73-400d-a091-0dc729bea30a:autoScalingGroupName/awseb-e-ymggxu7mai-stack-AWSEBAutoScalingGroup-CTHY5BO16CT1:policyName/awseb-e-ymggxu7mai-stack-AWSEBAutoScalingScaleUpPolicy-UNTK443C5E5G
2022-06-17 15:08:21    INFO    Deleted Auto Scaling group policy named: arn:aws:autoscaling:ap-southeast-3:0123456789:scalingPolicy:3ae34021-b577-470e-a493-8f4d88eda4dc:autoScalingGroupName/awseb-e-ymggxu7mai-stack-AWSEBAutoScalingGroup-CTHY5BO16CT1:policyName/awseb-e-ymggxu7mai-stack-AWSEBAutoScalingScaleDownPolicy-1KY50QYHQU7OG
2022-06-17 15:08:21    INFO    Waiting for EC2 instances to terminate. This may take a few minutes.
2022-06-17 15:11:39    INFO    Deleted Auto Scaling group named: awseb-e-ymggxu7mai-stack-AWSEBAutoScalingGroup-CTHY5BO16CT1
2022-06-17 15:11:39    INFO    Deleted load balancer named: awseb-e-y-AWSEBLoa-165JPKXMH3INE
2022-06-17 15:11:39    INFO    Deleted Auto Scaling launch configuration named: awseb-e-ymggxu7mai-stack-AWSEBAutoScalingLaunchConfiguration-8LOZJ395SOJH
2022-06-17 15:11:39    INFO    Deleted security group named: awseb-e-ymggxu7mai-stack-AWSEBSecurityGroup-109X7DG8OVDK4
2022-06-17 15:11:54    INFO    Deleted security group named: sg-06d732826fb0be349
2022-06-17 15:11:58    INFO    Deleting SNS topic for environment docker-httpd-2.
2022-06-17 15:11:59    INFO    terminateEnvironment completed successfully.
```

Do the same thing for another environment!

```bash
docker-httpd$ eb terminate
The environment "docker-httpd-1" and all associated instances will be terminated.
To confirm, type the environment name: docker-httpd-1

docker-httpd$ eb list
docker-httpd$
```

So, here the two things still existed!

```bash
docker-httpd$ aws s3 ls
2022-06-17 21:13:45 elasticbeanstalk-ap-southeast-3-0123456789
docker-httpd$ aws elasticbeanstalk describe-applications | grep Name
  ApplicationName: docker-httpd
```

Now, let's delete both services!

* S3
    

The bucket created by Beanstalk is used for all Beanstalk applications created under our AWS account (maybe it's the reason why the bucket is kept even though we terminated the application). It has a policy attached with the rules to allow `GET` and deny other operations. Only the Beanstalk role is allowed to do anything with it but because I act as administrator, I have another way for being able to delete it which is by removing the bucket policy first.

```bash
docker-httpd$ aws s3 rm s3://elasticbeanstalk-ap-southeast-3-0123456789 --recursive
docker-httpd$ aws s3api delete-bucket --bucket elasticbeanstalk-ap-southeast-3-0123456789

An error occurred (AccessDenied) when calling the DeleteBucket operation: Access Denied
docker-httpd$ aws s3api delete-bucket-policy --bucket elasticbeanstalk-ap-southeast-3-0123456789
docker-httpd$ aws s3api delete-bucket --bucket elasticbeanstalk-ap-southeast-3-0123456789
docker-httpd$ aws s3 ls
docker-httpd$
```

* Elastic Beanstalk Application
    

```bash
docker-httpd$ aws elasticbeanstalk delete-application --application-name docker-httpd
docker-httpd$ aws elasticbeanstalk describe-applications
Applications: []
```

Alright! We are done with the task!

Thank you for coming and I'm looking forward to your feedback. Follow me to get notified when my new post is published!

**References:**

* https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/docker.html
    
* https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/eb-cli3-getting-started.html