Prerequisites #
Docker Installation (Deb) #
- Docker is necessary to build the container image, install it via script:
#!/bin/bash
# Install Docker and Docker Compose on Ubuntu
sudo apt-get update
sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release -y
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
# Add user to Docker group
sudo usermod -aG docker ubuntu
AWS CLI Installation #
# Update packages
sudo apt update
# Unstall zip tool
sudo apt install unzip -y
# Download AWS CLI zip file
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
# Unzip
unzip awscliv2.zip
# Install
sudo ./aws/install
# Verify installation / check version
/usr/local/bin/aws --version
Copilot Installation #
# Download binary
curl -Lo copilot https://github.com/aws/copilot-cli/releases/latest/download/copilot-linux
# Change permissions
chmod +x copilot
# Move binary
sudo mv copilot /usr/local/bin/copilot
AWS ECS Copilot Example #
File and Folder Structure #
The file and folder structure of the Terraform project looks like this:
aws-ecs-copilot
├── Dockerfile
└── index.html
Project Folder #
# Create project folder
TF_PROJECT_NAME=aws-ecs-copilot
mkdir $TF_PROJECT_NAME && cd $TF_PROJECT_NAME
Dockerfile #
- Dockerfile
FROM public.ecr.aws/nginx/nginx:latest
EXPOSE 80
COPY index.html /usr/share/nginx/html
HTML File #
- index.html
<!DOCTYPE html>
<html>
<head>
<title>jklug.work</title>
</head>
<body>
<h1>Some HTML</h1>
<p>Example Application<br></p>
</body>
</html>
Deploy Application #
Initialize & Deploy Application #
-
Detect the containerized app via it’s Dockerfile
-
Copilot creates the necessary resources like VPC, subnets, ECR,…
# Initialize a New Application
copilot init \
--app nginx-example-app \
--name nginx-service \
--type "Load Balanced Web Service" \
--dockerfile "./Dockerfile" \
--deploy
# Shell output:
Note: It's best to run this command in the root of your Git repository.
Welcome to the Copilot CLI! We're going to walk you through some questions
to help you get set up with a containerized application on AWS. An application is a collection of
containerized services that operate together.
Ok great, we'll set up a Load Balanced Web Service named nginx-service in application nginx-example-app.
✔ Proposing infrastructure changes for stack nginx-example-app-infrastructure-roles
- Creating the infrastructure for stack nginx-example-app-infrastructure-roles [create complete] [43.7s]
- A StackSet admin role assumed by CloudFormation to manage regional stacks [create complete] [17.8s]
- An IAM role assumed by the admin role to create ECR repositories, KMS keys, and S3 buckets [create complete] [21.4s]
✔ The directory copilot will hold service manifests for application nginx-example-app.
✔ Manifest file for service nginx-service already exists at copilot/nginx-service/manifest.yml, skipping writing it.
Your manifest contains configurations like your container size and port.
- Update regional resources with stack set "nginx-example-app-infrastructure" [succeeded] [0.0s]
All right, you're all set for local development.
Only found one option, defaulting to: Create a new environment
Environment name: dev # Create new environment named "dev"
Environment dev does not yet exist in application nginx-example-app; initializing it.
✔ Manifest file for environment dev already exists at copilot/environments/dev/manifest.yml, skipping writing it.
- Update regional resources with stack set "nginx-example-app-infrastructure" [succeeded] [0.0s]
- Update regional resources with stack set "nginx-example-app-infrastructure" [succeeded] [39.3s]
- Update resources in region "us-east-1" [create complete] [38.4s]
- KMS key to encrypt pipeline artifacts between stages [create complete] [16.0s]
- ECR container image repository for "nginx-service" [create complete] [0.0s]
- S3 Bucket to store local artifacts [create complete] [3.3s]
✔ Proposing infrastructure changes for the nginx-example-app-dev environment.
- Creating the infrastructure for the nginx-example-app-dev environment. [create complete] [42.1s]
- An IAM Role for AWS CloudFormation to manage resources [create complete] [20.9s]
- An IAM Role to describe resources in your environment [create complete] [19.0s]
✔ Provisioned bootstrap resources for environment dev in region us-east-1 under application nginx-example-app.
✔ Provisioned bootstrap resources for environment dev.
✔ Proposing infrastructure changes for the nginx-example-app-dev environment.
- Creating the infrastructure for the nginx-example-app-dev environment. [update complete] [66.3s]
- An ECS cluster to group your services [create complete] [5.6s]
- A security group to allow your containers to talk to each other [create complete] [5.3s]
- An Internet Gateway to connect to the public internet [create complete] [16.3s]
- A resource policy to allow AWS services to create log streams for your workloads. [create complete] [3.5s]
- Private subnet 1 for resources with no internet access [create complete] [6.8s]
- Private subnet 2 for resources with no internet access [create complete] [3.8s]
- A custom route table that directs network traffic for the public subnets [create complete] [10.6s]
- Public subnet 1 for resources that can access the internet [create complete] [3.8s]
- Public subnet 2 for resources that can access the internet [create complete] [3.8s]
- A private DNS namespace for discovering services within the environment [create complete] [45.3s]
- A Virtual Private Cloud to control networking of your AWS resources [create complete] [13.3s]
✔ Successfully deployed environment devWARNING! Your password will be stored unencrypted in /home/ubuntu/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credential-stores
Login Succeeded
[+] Building 10.9s (7/7) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 124B 0.0s
=> [internal] load metadata for public.ecr.aws/nginx/nginx:latest 2.1s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 192B 0.0s
=> [1/2] FROM public.ecr.aws/nginx/nginx:latest@sha256:0802e3c4c7025bc4fc28d0215cca76c931db79243f51368d70988c1de0748402 8.4s
=> => resolve public.ecr.aws/nginx/nginx:latest@sha256:0802e3c4c7025bc4fc28d0215cca76c931db79243f51368d70988c1de0748402 0.0s
=> => sha256:0802e3c4c7025bc4fc28d0215cca76c931db79243f51368d70988c1de0748402 772B / 772B 0.0s
=> => sha256:486dbf987c66d381e55da2fe0fceb473435899121e907eda1dce553ba15bb88f 29.13MB / 29.13MB 3.6s
=> => sha256:841e383b441eda86c164d8e833da080b951c951d612853cac2fd44eed0d72226 627B / 627B 0.8s
=> => sha256:e49b2893e997eeda7716bd7f3b2ed60aac69faa4041a4a3b88fb885609703cbb 1.78kB / 1.78kB 0.0s
=> => sha256:9bea9f2796e236cb18c2b3ad561ff29f655d1001f9ec7247a0bc5e08d25652a1 8.58kB / 8.58kB 0.0s
=> => sha256:207b812743af01771d6c94b3ebc59543bf3c6fefe5d4d9ebfa6e5e5558801d34 43.84MB / 43.84MB 7.4s
=> => sha256:0256c04a8d84ab5ae434b607055df8fdfe0278dba43f3e603a861dc7e26da395 957B / 957B 1.0s
=> => sha256:38e992d287c563d332ed8c9bdefec32a84f50f94cc39bb4729a3e73cefde88eb 406B / 406B 1.3s
=> => sha256:9e9aab598f58e86706b73c23e0ff33fc4eb60a5e69424147f9cb7c02e853323b 1.21kB / 1.21kB 1.6s
=> => sha256:4de87b37f4ad0b499be3db4cc6831db3d8158867f12dabc0bf42046b56784d3b 1.40kB / 1.40kB 1.8s
=> => extracting sha256:486dbf987c66d381e55da2fe0fceb473435899121e907eda1dce553ba15bb88f 0.9s
=> => extracting sha256:207b812743af01771d6c94b3ebc59543bf3c6fefe5d4d9ebfa6e5e5558801d34 0.8s
=> => extracting sha256:841e383b441eda86c164d8e833da080b951c951d612853cac2fd44eed0d72226 0.0s
=> => extracting sha256:0256c04a8d84ab5ae434b607055df8fdfe0278dba43f3e603a861dc7e26da395 0.0s
=> => extracting sha256:38e992d287c563d332ed8c9bdefec32a84f50f94cc39bb4729a3e73cefde88eb 0.0s
=> => extracting sha256:9e9aab598f58e86706b73c23e0ff33fc4eb60a5e69424147f9cb7c02e853323b 0.0s
=> => extracting sha256:4de87b37f4ad0b499be3db4cc6831db3d8158867f12dabc0bf42046b56784d3b 0.0s
=> [2/2] COPY index.html /usr/share/nginx/html 0.2s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:9d9cc757f13d199677c2ced313a5f6722ecce617d54aad734d187bf765228c7d 0.0s
=> => naming to 012345678912.dkr.ecr.us-east-1.amazonaws.com/nginx-example-app/nginx-service:latest 0.0s
The push refers to repository [012345678912.dkr.ecr.us-east-1.amazonaws.com/nginx-example-app/nginx-service]
80da25e25344: Pushed
b57b5eac2941: Pushed
58045dd06e5b: Pushed
541cf9cf006d: Pushed
32c977818204: Pushed
943132143199: Pushed
88ebb510d2fb: Pushed
f5fe472da253: Pushed
latest: digest: sha256:d402380e926fc42667fa93bf9a3396fd0ba0ffb275e46bf81580e28e39cdb00b size: 1985
✔ Proposing infrastructure changes for stack nginx-example-app-dev-nginx-service
- Creating the infrastructure for stack nginx-example-app-dev-nginx-service [create complete] [358.2s]
- Service discovery for your services to communicate within the VPC [create complete] [0.0s]
- Update your environment's shared resources [update complete] [181.3s]
- A security group for your load balancer allowing HTTP traffic [create complete] [8.5s]
- An Application Load Balancer to distribute public traffic to your services [create complete] [155.5s]
- A load balancer listener to route HTTP traffic [create complete] [2.8s]
- An IAM role to update your environment stack [create complete] [17.4s]
- An IAM Role for the Fargate agent to make AWS API calls on your behalf [create complete] [13.5s]
- An HTTP listener rule for path `/` that forwards HTTP traffic to your tasks [create complete] [0.0s]
- A custom resource assigning priority for HTTP listener rules [create complete] [0.0s]
- A CloudWatch log group to hold your service logs [create complete] [4.1s]
- An IAM Role to describe load balancer rules for assigning a priority [create complete] [17.4s]
- An ECS service to run and maintain your tasks in the environment cluster [create complete] [124.4s]
Deployments
Revision Rollout Desired Running Failed Pending
PRIMARY 1 [completed] 1 1 0 0
- A target group to connect the load balancer to your service on port 80 [create complete] [21.6s]
- An ECS task definition to group your containers and run them on ECS [create complete] [3.5s]
- An IAM role to control permissions for the containers in your tasks [create complete] [17.4s]
✔ Deployed service nginx-service.
Recommended follow-up action:
- Your service is accessible at http://nginx--Publi-NBas29DPEpZR-21649905.us-east-1.elb.amazonaws.com over the internet.
- Be a part of the Copilot ✨community✨!
Ask or answer a question, submit a feature request...
Visit 👉 https://aws.github.io/copilot-cli/community/get-involved/ to see how!
Access Container via ELB #
# Curl the ELB endpoint
curl http://nginx--Publi-NBas29DPEpZR-21649905.us-east-1.elb.amazonaws.com
# Shell output:
<!DOCTYPE html>
<html>
<head>
<title>jklug.work</title>
</head>
...
List Created Resources #
- AWS Copilot manages resources using CloudFormation stacks
# List CloudFormation stack resources: Syntax
aws cloudformation list-stack-resources --stack-name <app-name>-<env-name>
# List CloudFormation stack resources: Example
aws cloudformation list-stack-resources \
--stack-name nginx-example-app-dev \
--no-cli-pager
# List more details
aws cloudformation describe-stacks \
--stack-name nginx-example-app-dev \
--no-cli-pager
Delete Application #
# Delete resources
copilot app delete