Prerequisites #
Install AWS CLI #
# 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
Configure AWS CLI #
# Start AWS CLI configuration
aws configure
AWS Elastic Container Registry (ECR) #
Create ECR Repository #
# Create a repository
aws ecr create-repository --repository-name example-application --region eu-central-1
# Shell output:
{
"repository": {
"repositoryArn": "arn:aws:ecr:eu-central-1:012345678912:repository/example-application",
"registryId": "012345678912",
"repositoryName": "example-application",
"repositoryUri": "012345678912.dkr.ecr.eu-central-1.amazonaws.com/example-application",
"createdAt": "2024-12-15T09:56:25.008000+00:00",
"imageTagMutability": "MUTABLE",
"imageScanningConfiguration": {
"scanOnPush": false
},
"encryptionConfiguration": {
"encryptionType": "AES256"
}
}
}
Enable ScanOnPush #
Enable the option to automatically scan the container images for security vulnerabilities, each time they are pushed to the repository:
# Enable ScanOnPush for the repository
aws ecr put-image-scanning-configuration \
--repository-name example-application \
--image-scanning-configuration scanOnPush=true \
--region eu-central-1
# Shell output:
{
"registryId": "012345678912",
"repositoryName": "example-application",
"imageScanningConfiguration": {
"scanOnPush": true
}
}
Docker Login #
Login the new registry repository:
# Retrieve an authentication token and authenticate the Docker client
aws ecr get-login-password --region eu-central-1 | docker login --username AWS --password-stdin 012345678912.dkr.ecr.eu-central-1.amazonaws.com/example-application
# Shell output:
WARNING! 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
Push Image to ECR #
Example Application #
- Dockerfile
# Use the official Caddy image as the base
FROM caddy:alpine
# Create a non-root user "caddy"
RUN addgroup -S caddy && adduser -S -G caddy caddy
# Adjust permissions
RUN mkdir -p /usr/share/caddy && \
chown -R caddy:caddy /usr/share/caddy /config /data
# Copy website files into the container
ADD index.html /usr/share/caddy/
# Switch to the non-root user
USER caddy
# Expose the default Caddy port
EXPOSE 80
- index.html
<!DOCTYPE html>
<html>
<head>
<title>jklug.work</title>
</head>
<body>
<h1>Some HTML</h1>
<p>Example Docker Container<br></p>
</body>
</html>
Build the Image #
# Build the image for the application
docker build -t example-application .
Tag the Image #
- Docker images need a fully qualified name to push
# Tag the local Docker image to associate it with the ECR repository
docker tag example-application:latest 012345678912.dkr.ecr.eu-central-1.amazonaws.com/example-application:latest
Verify the image:
# List Docker images
docker images
# Shell output:
REPOSITORY TAG IMAGE ID CREATED SIZE
012345678912.dkr.ecr.eu-central-1.amazonaws.com/example-application latest 336a6a181143 3 minutes ago 49.3MB
example-application latest 336a6a181143 3 minutes ago 49.3MB
Push the Image to ECR #
# Push the image to ECR
docker push 012345678912.dkr.ecr.eu-central-1.amazonaws.com/example-application:latest
# Shell output:
62b7f03085b1: Pushed
42d4c1ec2197: Pushed
23c36cdedae8: Pushed
5f70bf18a086: Pushed
355a1927f295: Pushed
625cb1c61fcf: Pushed
d7a20f4b69ff: Pushed
75654b8eeebd: Pushed
latest: digest: sha256:11b2bd79a548048c284a42801206efec00493656b6654ea956c32687e6901b92 size: 1986
Verify Security Scan #
# List image security scan details
aws ecr describe-image-scan-findings \
--repository-name example-application \
--region eu-central-1 \
--image-id imageTag=latest
# Shell output:
...
"imageScanStatus": {
"status": "COMPLETE",
"description": "The scan was completed successfully."
}
Verify / List Image in ECR #
# List container images in the ECR repository
aws ecr list-images --repository-name example-application --region eu-central-1
# Shell output:
{
"imageIds": [
{
"imageDigest": "sha256:11b2bd79a548048c284a42801206efec00493656b6654ea956c32687e6901b92",
"imageTag": "latest"
}
]
}
Access ECR from Another Host #
Create a new IAM user and attach the AmazonEC2ContainerRegistryReadOnly
policy to access the ECR from another host:
Create IAM User #
# Create a new IAM user named "example-user"
aws iam create-user --user-name example-user
Create Access Keys #
# Create Access Keys for the user
aws iam create-access-key --user-name example-user
# Shell output:
{
"AccessKey": {
"UserName": "example-user",
"AccessKeyId": "AKIARCHUALIN6QRH6WYK",
"Status": "Active",
"SecretAccessKey": "cKSprb4yeyL31mXDxs6qlcjNYoVazlY3eGFPWG7P",
"CreateDate": "2024-12-11T21:49:17+00:00"
}
}
Attach Policy #
ECR Policies:
-
AmazonEC2ContainerRegistryReadOnly
Pull permission -
AmazonEC2ContainerRegistryFullAccess
Push and Pull permission
# Attach the "AmazonEC2ContainerRegistryReadOnly" policy to the user:
aws iam attach-user-policy --user-name example-user --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
Verify the Policy #
# Confirm the policy is attached to the user
aws iam list-attached-user-policies --user-name example-user
# Shell output:
{
"AttachedPolicies": [
{
"PolicyName": "AmazonEC2ContainerRegistryReadOnly",
"PolicyArn": "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
}
]
}
Configure AWS CLI #
SSH into another Linux host and configure the AWS CLI with the previously created access keys:
# Configure AWS CLI with the new credentials
aws configure
# Shell output
AWS Access Key ID [None]: # Paste key: AKIARCHUALIN6QRH6WYK
AWS Secret Access Key [None]: # Paste key: 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
Default region name [None]:
Default output format [None]:
Docker Login #
# Retrieve an authentication token and authenticate the Docker client
aws ecr get-login-password --region eu-central-1 | docker login --username AWS --password-stdin 012345678912.dkr.ecr.eu-central-1.amazonaws.com/example-application
# Shell output:
WARNING! 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
Pull the Image #
# Pull the "example-application" image from the ECR repository
docker pull 012345678912.dkr.ecr.eu-central-1.amazonaws.com/example-application:latest
Verify the image:
# List Docker images
docker images
# Shell output
REPOSITORY TAG IMAGE ID CREATED SIZE
012345678912.dkr.ecr.eu-central-1.amazonaws.com/example-application latest 26cb4de176d7 37 minutes ago 11.8MB
Create a Container #
# Create a Docker container of the image
docker run -d --name example-application -p 80:80 26cb4de176d7
# List containers
docker ps
# Shell output:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3b24f9428c86 26cb4de176d7 "/usr/sbin/httpd -D …" 2 seconds ago Up 1 second 0.0.0.0:80->80/tcp, :::80->80/tcp example-application
# Verify the example application
curl localhost
# Shell output:
<!DOCTYPE html>
<html>
<head>
<title>jklug.work</title>
</head>
<body>
<h1>Some HTML</h1>
<p>Example Docker Container<br></p>
</body>
</html>
Cleanup #
Delete IAM User #
# Detach the policies attached to the user
aws iam detach-user-policy --user-name example-user --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
# List the access keys for the user
aws iam list-access-keys --user-name example-user
# Shell output:
{
"AccessKeyMetadata": [
{
"UserName": "example-user",
"AccessKeyId": "AKIARCHUALIN6QRH6WYK",
"Status": "Active",
"CreateDate": "2024-12-11T21:49:17+00:00"
}
]
}
# Delete the access keys
aws iam delete-access-key --user-name example-user --access-key-id AKIARCHUALIN6QRH6WYK
# Delete the user
aws iam delete-user --user-name example-user
Delete ECR Repository #
List Container Images #
# List repository images
aws ecr list-images --repository-name example-application --region eu-central-1
# Shell output:
{
"imageIds": [
{
"imageDigest": "sha256:787ab7c1433646d5a191dbedf787a9facfcb8e6fe8997bc638138379f983a16b",
"imageTag": "latest"
}
]
}
Delete Container Image #
# Delete specific image:
aws ecr batch-delete-image --repository-name example-application --image-ids imageDigest=sha256:787ab7c1433646d5a191dbedf787a9facfcb8e6fe8997bc638138379f983a16b --region eu-central-1
Delete ECR Repository #
# Delete the ECR repository
aws ecr delete-repository --repository-name example-application --region eu-central-1 --force