A common and standard option to package a web service is via container, e.g. docker. After you have built your awesome web service, tested it and packaged it in container, how do we deploy it to cloud so it will be available to serve requests 24X7? Major cloud platforms like AWS and GCP offer native services to host containers, but usually there is long documentation you need to read. This article helps you to get your service up and running in minutes.

We will use docker as the container technology and AWS as our cloud solution. We assume you have some experience of working with AWS, and know how to build a docker image for your service.

AWS EC2

If you are looking for a quick and dirty way to get something out of the gate, this is the most transparent and flexible approach. You can start a virtual machine on any cloud platform like AWS EC2, pull the image from a container registry, run a container like you do on your local computer and access it via the Internet. Make sure the security setting on your instance has the right port open that maps to the one used in your container, e.g. 5000 for Flask app.

AWS ECS

In most cases, you want to deploy your container without the trouble to manage dedicated instances and have the ability to focus on the task and automatically scale the service when traffic goes up. Managed container services help us do just that. We will look at how to use it on AWS and GCP.

Upload docker image

First, we need to upload the image to a container registry for the service to access. AWS has its own registry service called ECR. To do that, go to ECR portal and create a new repository.

Create a new repo on AWS ECR

Make sure you have aws-cli installed and configured properly using aws configure . Inside the repo, click ‘View push commands’ and follow the instructions to upload the local image to your repo.

Create ECS Cluster

ECS runs on top of computing instances used to execute your container which is called a cluster. Go ahead and create one (ECS -> Clusters -> Create Cluster). Select ‘Networking only’ with Fargate option. Fargate allows you to skip the tedious process of managing servers or clusters. Enter cluster name field and hit create.

Create ECS Task Definition

Moving on, we will create a task definition. A task definition specify information related to your container and resource to use, this essentials defines how you want to run your service as container. Go to ECS Task Definitions menu on the left, click ‘Create new Task Definition’. Select ‘Fargate’ launch type. Enter the configuration page. Here is a breakdown (use default value unless mentioned below):

Task Definition Name: any name you want to call it, usually I name it as an action to be taken, e.g. run-my-service.

Task Role: select ‘ecsTaskExecutionRole’.

Task Size (memory and CPU): this one is a bit tricky. The easy way is to estimate roughly how much memory your service consumes when it’s running, for simple web API that performs database operations, 0.5–1GB usually is enough. Based on the option for memory, the CPU option will be recommended automatically.

Container Definitions: the most critical part to configure. Here you specify which container(s) you want to use in this task. It’s fairly straightforward, remember to set which port to map.

Finally, click ‘Create’ to complete task definition. You can also go back and create a revision of a task by changing some of the fields in the definition and the revision number will be bumped up.

Create ECS Service

Now you are one step away to launch your service. Go to the cluster you want to use, under the ‘Service’ tab, click ‘Create’. Next, you need to configure the service. Key fields are below:

Launch type: use Fargate

Task definition: choose the task you want to launch and the revision number

Service name: use a clear name for the service. You might have already used the service name in the task definition, keep it consistent is not a bad thing

Number of tasks: set to 1

Leave other fields as default and go to next page to configure network.

Cluster VPC: use a proper VPC that allows public access, and pick a security group that has the service port access permission.

Load balancing: select None unless you need to run duplicate of the service, in which case you need to create the load balancer separately and choose the right option for you.

Service discovery: you can turn it off.

Go to next page for auto-scaling, if you didn’t use load balancer then you can skip this step. Otherwise, it’s fairly straightforward to set the boundary of scaling and the scaling policies where you define when to scale up and down instances. Finally, hit ‘Review’ and submit the creation.

Now, if you go into to the service and select ‘Tasks’ tab, you will see your task is Pending, and after a short time, your task will turn to Running status. Click the ‘Task’ field to see the detailed information of the running task, in the network section, you will find the ‘Public IP’ field. Use ip:port to access the service.

Updating the service

Whenever you make changes to the service code and repackage it to a new docker image, you can easily update the service without interrupting the current running version. Simply tag the image as a new version and upload it to the registry where you will find all available versions in the same repo. Then, create a revision of the task by changing the container definition to be the new version. Finally, go to service and click the ‘Update’ button on the top right, change the task to the new revision and keep everything else untouched. You shall see a new task is pending and will become running while the previous one gets deleted. The whole replacement is seamless and automatic, you just need to grab the corresponding IP for the new one.