Most software companies want to concentrate on building amazing apps; they don’t want to spend time managing clusters, pipelines, etc.
At Phlyt, we recommend that clients use a container-as-a-service (CaaS) to allow them to efficiently manage backend processes and free up time to spend on their core businesses. The Phlyt product team has a lot of experience transferring applications to CaaS such as GCP and AWS.
This post is specifically about deploying apps to ECS and how to do it efficiently by using an AWS tool named Copilot. You will learn how you:
- Begin deploying an app to ECS
- Manage secrets and environment variables,
- Deploy and troubleshoot, and
- Set up a secure custom domain.
When Pivotal Web Services, a managed platform, closed in January 2021, Phlyt moved Core Academy to AWS Elastic Container Service (ECS) — a fully managed container orchestration service.
Fast Set-Up with AWS Copilot
The ECS setup was very easy. But then, we had to create the load balancers, security groups, IAM, and more. This required a lot more work and knowledge from the team than expected.
Thankfully, we discovered a tool developed by AWS named Copilot (https://aws.github.io/copilot-cli/). With Copilot’s CLI, we could deploy apps easily (similar to the “cf push” command we previously used to deploy to PWS). Even better, we found that with Copilot’s CLI, we could more easily create ECS clusters, environment, deploy apps and create CI/CD pipelines.
Here is an example of some of Copilot’s impressive features:
Deploying an App to ECS: First Steps
Let’s get started with an existing application. Make sure you have a Dockerfile in your app, then run the following command:
$ copilot init
The CLI will ask you a few questions:
- The name of the application. This will be the name of the cluster.
- The workload type. If you want to deploy a web application, you can choose “Load Balance Web Service”. If you want to deploy a database or cache, you can choose “Backend Service”. If you need to run a task based on a Cron job, you can choose “Scheduled Job”.
- The name of your service (i.e., api-gateway, webapp, etc). You can have several services in your ECS cluster.
- Your Dockerfile location.
Within a minute or two, the CLI will create all the infrastructure roles (this is a time saver!), create an ECR repository for the service, and create a manifest.yml file in the copilot folder in your existing application. This will allow you to define settings/specs for your service (more on this later).
Then, you can create a new environment (e.g., QA, prod, etc.) or you can answer no and run the command `copilot env init` later. When creating an environment, the CLI will create a new cluster, all the IAM roles, security groups, gateway, logs, and everything needed to run the application successfully.
Now that we have one cluster for the test environment, let’s review the manifest.yml that the CLI created during the init phase.
The first half is the description of the app derived from the questions asked during the init. The health-check section has many settings that you can customize to your needs.
Then, you can specify the amount of resources (CPU and memory) you need for your app.
Managing Secrets and Environment Variables
In the “environments” section, you can customize the numbers of instances to run for each environment and specify your environment variables and your secrets (set in the AWS SSM Parameter Store).
In this example, only one instance is running in the test environment and two instances are running in production.
There is also a “count” section which can be used to customize the auto-scaling thresholds (not shown in this example, but you can find every section in the Copilot documentation).
Your application probably needs passwords (i.e., database) or other API keys. You can create secrets in the AWS Systems Manager (SSM) in the parameter store section. The name of the secret is binded in the manifest.yml — I recommend that you use a very clear and distinct name that you can easily find later on when you have many applications, environments and, thus, secrets.
One important step after creating a secret is to add the following two tags to bind the secret to your service.
Deployment and Troubleshooting
If you have not deployed your application yet, you can run the following command:
$ copilot deploy
If you have created several environments, you can select the target environment at this stage.
This command will run docker from the specified Dockerfile, upload your container to the ECR, and run it on your cluster. Once the health checks are passed, this command will stop and remove any previous versions of the app.
If your app does not start, you can find lots of useful logs in the ECS clusters if, for example, your app cannot find secrets. If the problem is more app specific, you can find the startup logs in CloudWatch. Copilot will have created “log groups” based on the service name and environment.
Now that the application is up and running on a specific AWS url, the next steps are to allow use of a custom domain and to add certificates
Custom Domain and Certificates
To set up a custom domain, simply go to the EC2 -> Load Balancers page. Find your public LB from the list (you could have many if you have several applications and environments), click on the name of the load balancer, and copy the DNS name url.
Use this url to add a CNAME record in the DNS setting of the domain. Save and wait for the TTL to expire. Depending on your registrar/DNS services, this can take between one minute to one hour. Now you should be able to access the website via the custom url.
To enable https, you need to create a certificate via AWS Certificate Manager (ACM). Click on “Request a certificate,” enter your domain name (can be a wildcard or for a specific subdomain), and ACM will give you two urls to add in the domain registrar/DNS services. Create two CNAME records with the values provided. This is very similar to the previous step.
Once the TTL expires, ACM will update the status to “issued.” You don’t have to worry about expiration. As long as you are using the certificate, it will be renewed automatically.
Now you will need to use the certificate in the load balancer. Let’s go back to EC2 -> Load Balancers and select the correct LB name. At the bottom part of the screen, select the “Listeners” tab.
The default listener HTTP is on port 80.
You need to add a new HTTPS listener on port 443. During the creation process, you can select the certificate generated above.
Your webapp can now accept https requests.
Storage and Pipeline
Copilot can also create storage (i.e., S3 bucket) and a CI/CD pipeline to automate the deployments. This will be covered in my next post but if you cannot wait, simply run “copilot pipeline init” to create a CI/CD pipeline using CodeBuild and CodeDeploy.
All the steps are done through CloudFormation. If anything fails, you will be able to find what’s happening in there. Sometimes a resource will not be created or deleted. You can find the problem and apply the changes.
Copilot is a very active tool. If you update the CLI and most of the pipelines for infrastructure and deployment have a new version available, these will be automatically updated and you will benefit from all the associated improvements and enhancements.
I hope this will help you get started with ECS very quickly. For more on how Phlyt can support your application’s migration to a different infrastructure visit phlyt.io