Navigating the Cloud: Creating Container Applications in AWS
Published: 2023-04-28 20:43:14

Containers are the portable packages we can use to wrap, execute and isolate our software. They ensure the software will run the same in any environment you run the container. A container is light, can be run by itself, and can include all your dependencies. Containers are derived from images that are created upon building your whole project from a template or a plan. Additionally, containers can be pretty similar to virtual machines, however, they are fundamentally different in the way they operate, as the containers “step” onto the host Os, whereas VMs each have their own OS “stepping” onto the hardware.


We use containers in the cloud simply because they are easy to deploy and configure. Setting up your first cloud container application takes only a few minutes. In the AWS cloud, we have the choice to use ECS or EKS service - elastic container service and elastic kubernetes service. If you need to use kubernetes you can always look for EKS, however, in this article, we will be using ECS, because of the simplicity it can provide.


We begin by defining our project Dockerfile and building the container image to kick off our process. The configuration of your Dockerfile will not be a part of this article, as it can be really lengthy depending on the context. There are a lot of really simple guides to creating your Dockerfile online. We can start building the project into an image when you have that out of the way. To do this we will run the build command like in the example

```
docker build -t tagname .
```

The next important task is to create a container registry using the AWS ECR service - elastic container registry. A container repository is like a collection of uploaded images. AWS offers public and private repositories, and it's up to you which to choose. For the most part, they are free, depending on the usage. Create your registry simply by choosing the type - public or private, and the repo name. As soon as that's done AWS will show you a list of commands you can use to build and push your images to the repository, thus making it really easy.

![ECR repository](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xs68jnrtjptkmlkdyfez.png)

![Create ECR repository](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pynammf1afbwc9jitlgq.png)

![ECR image push commands](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kbgsrvqtn01sdhj4e78x.png)

Once you have pushed your image to EC, it will be available for us to use in our container setup and we can proceed with the ECS setup. The first resource you will create is a cluster, as it's also the first thing you will see when you open the ECS menu.  A container cluster is a way to group the deployed containers later into services and tasks. Additionally, we define the underlying infrastructure like EC2 instances within the scope of the cluster, which means that we choose which compute provider will run our software. An important part of setting up the cluster is the option to choose between EC2 and Fargate(default) infrastructure for our cluster.If you make a choice to base your cluster on AWS EC2 you will be required to configure an auto-scaling group, whether create a new one or use an existing one. One important note for the monitoring options: if you decide to use the disabled by default container insights, which may be useful as they provide data on the overall health and load of the cluster, they will incur additional charges for Cloudwatch metrics, so don't let that get catch you off guard, as it did with me.

![Create ECS cluster](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bcjjp198fqytnez153sz.png)

![ECS Cluster infrastructure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o8r58vokua9bex6yorie.png)

Next is the task definition where we create the container outlines, pointing to the image that will be our app, port mapping, secrets or env variables, and health check settings. The task definition is the basic blueprint that is used in the service. It is versioned, meaning you can have and use several versions of different configurations.


![Create ECS Task Definition](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h4llnjlixirvop3sxid4.png)


![ECS Task Definition overview](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nzklfqlxljl172izf5n1.png)

What follows is a choice of whether to create a service or a task. Usually, services create tasks that run the software, so essentially they are based on them, however, I recommend using standalone tasks only in a few specific cases, where you have a separate or standalone functionality or job. So for now we will follow through with the create service option. 

The first choice you are tasked to make is whether to use a launch type or capacity provider strategy. You can think of this as choosing between the easy option and the harder one, and the capacity-provided strategy will be harder to understand at first. If this is your first time working with ECS I can recommend going with the launch type option, as ecs will automatically create any resources it will need to run your service, such as EC2 instances, ASG(Auto Scaling Groups), and others, all according to the config of the cluster. The capacity provider strategy option instructs the service how to distribute the tasks over your defined capacity, which for EC2 instances for example can be one or more different ASG, with the choice of which provider is more important. For Fargate there are 2 predefined options - FARGATE and FARGATE_SPOT. However this setting is unnecessary in many cases, therefore we will not dwell on it more. 

Of course, the services/tasks are dependent on the task definition we created beforehand, so we will just point to the TD(Task Definition) and its specific version.


![Create ECS Service](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/87zn7cda79tysd3ihk35.png)

For the rest of the config options, we can simply stick with the defaults, as they will do the trick just fine in most cases. Depending on the level of customization you can choose otherwise, as for example in the service type field. In specific cases, you may need to use the daemon type for your services, although this is rarely going to be the case.

If you intend to use multiple EC2 instances in your ASG if this is the compute option you have decided on, you can also configure and auto-create a load balancer, which is going to be a must.


![ECS Service Load Balancing](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/io77fajypdfsmg2xw05d.png)

 One interesting option can be the service auto-scaling, this way ecs can scale your service depending on specific metrics or policies, which is really similar to the way ASG scale up and down.


![ECS Service auto scaling](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9p0h725ly0l1qgcby9rt.png)

After you hit the create button ECS you will be able to see your service in the list, and after a while a task should appear as well, indicating the process was a success. Note that the process can take a bit of time, for the health checks to pass and the configs to be completed, and also to roll the tasks deployed. Once you see the active status, you can follow any deployments or inspect the task count from the main service list or to get into more details, the deployments and events menu in the service. The container statuses can also be inspected as if you have configured multiple containers, you will be able to check on each of them individually from “Configuration and tasks”.


![Created ECS Service overview and status](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ftgrdks6is1d0p4zhc6v.png)


![Containers overview after service is created](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gi7j6m3lfuypjr7dkgi3.png)