Deploy a Container Web App on Amazon Lightsail
TUTORIAL
Module 4: Deploy a New Container Version
In this module, you will learn to update a container that has already been deployed
Overview
In the life of an application, it will be updated many times. In this module, you will learn how to update your deployment and how to roll back a deployment, in case the new application version has issues.
What you will accomplish
- Update the application code and build a new local container image
- Push the updated container image to Amazon Lightsail
- Deploy the new version of your application
- Roll back a deployment, in case something goes wrong
Minimum time to complete
10 minutes
Module prerequisites
- AWS account with administrator-level access*
- Recommended browser: The latest version of Chrome or Firefox
*Accounts created within the past 24 hours might not yet have access to the services required for this tutorial.
Implementation
Update your application code and build a new container image
Let's pretend the city name on the application front page is incorrect and needs to be modified.
Open the file code/templates/index.html. Search for Las Vegas and replace it with Paris.
Then, build and test the container as explained in module 2. Open a terminal and enter the following commands:
docker build -t demo-flask-signup .
docker run -p 8080:80 --rm -v ~/.aws:/root/.aws demo-flask-signup:latest
Now that the container is running, open a browser and point it at http://localhost:8080. You should see the application home screen, with the new city name.
Push the updated container image to Amazon Lightsail
Now that the container is built, the next step is to push this new container image to Amazon Lightsail.
Open a terminal and enter the following commands:
aws lightsail push-container-image --region eu-west-3 --service-name signup-application --label latest --image demo-flask-signup:latest
The command outputs a message, such as the following:
# aws lightsail push-container-image --region eu-west-3 --service-name signup-application --label latest --image demo-flask-signup:latest
df0f7d33bb59: Pushed
951ffe99d911: Pushed
cee40450fe90: Pushed
1327150a5178: Pushed
4bc5d67b6427: Layer already exists
ce8ffb5c560e: Layer already exists
4226d5d0360f: Layer already exists
9d1af766c818: Layer already exists
d97733c0a3b6: Layer already exists
c553c6ba5f13: Layer already exists
48b4a40de359: Layer already exists
ace9ed9bcfaf: Layer already exists
764055ebc9a7: Layer already exists
Digest: sha256:42d2e19ee7340bc7f028593318e9b7406e9e70fb4785618d3f6c78443e097a87
Image "demo-flask-signup:latest" registered.
Refer to this image as ":signup-application.latest.2" in deployments.
The last line of the output displays the internal name of your container. Note the name because we will need it to deploy the container onto the container service. In case you want to access the container name at a later stage, you can enter the following command:
aws lightsail get-container-images --region eu-west-3 --service-name signup-application
The command outputs a message, such as the following:
# aws lightsail get-container-images --region eu-west-3 --service-name signup-application
{
"containerImages": [
{
"image": ":signup-application.latest.2",
"digest": "sha256:42d2e19ee7340bc7f028593318e9b7406e9e70fb4785618d3f6c78443e097a87",
"createdAt": "2024-03-13T14:20:08-04:00"
},
{
"image": ":signup-application.latest.1",
"digest": "sha256:128f84907d30a1fb47c1888720485fa8050cc99bc1034e0cfd1f46d3b6e57e19",
"createdAt": "2024-03-13T13:23:08-04:00"
}
]
}
Issue the commands to check the deployment state.
Notice the "state": "DEPLOYING" status. After a while, the state will become ACTIVE. The deployment takes a few minutes to complete. You can check the state of your deployment using the following command:
aws lightsail get-container-services --region eu-west-3 --query "containerServices[].nextDeployment.state"
aws lightsail get-container-services --region eu-west-3 --query "containerServices[].currentDeployment.state"
Test your deployment
To test your deployment, first retrieve the URL Lightsail created for you. Open a terminal and enter the following command:
aws lightsail get-container-services --region eu-west-3 --query "containerServices[].url"
The command outputs a message, such as the following:
# aws lightsail get-container-services --region eu-west-3 --query "containerServices[].url"
[
"https://signup-application.me04fvc6dbk4e.eu-west-3.cs.amazonlightsail.com/"
]
We now have two versions of our container image - :signup-application.latest.1 and :signup-application.latest.2.
Deploy a new version of your application
Now that the container image is stored on Amazon Lightsail, we can deploy that image to the container service, using similar commands as described in the previous Deploy a Container module.
Edit the lc.json file and replace the name of the image to use—:signup-application.latest.1—to the new version :signup-application.latest.2.
The new lc.json file should look like this:
{
"serviceName": "signup-application",
"containers": {
"signup-app-container": {
"image": ":signup-application.latest.2",
"ports": {
"80": "HTTP"
}
}
},
"publicEndpoint": {
"containerName": "signup-app-container",
"containerPort": 80
}
}
Then, deploy the container by entering the following command:
aws lightsail create-container-service-deployment --region eu-west-3 --cli-input-json file://lc.json
The command outputs a message, such as the following:
# aws lightsail create-container-service-deployment --region eu-west-3 --cli-input-json file://lc.json
{
"containerService": {
"containerServiceName": "signup-application",
"arn": "arn:aws:lightsail:eu-west-3:012345678901:ContainerService/528a0bcf-fd14-42d4-a09a-943a241adc51",
"createdAt": "2024-03-15T11:43:10-04:00",
"location": {
"availabilityZone": "all",
"regionName": "eu-west-3"
},
"resourceType": "ContainerService",
"tags": [],
"power": "nano",
"powerId": "nano-1",
"state": "DEPLOYING",
"scale": 2,
"nextDeployment": {
"version": 1,
"state": "ACTIVATING",
"containers": {
"signup-app-container": {
"image": ":signup-application.latest.2",
"command": [],
"environment": {},
"ports": {
"80": "HTTP"
}
}
},
"publicEndpoint": {
"containerName": "signup-app-container",
"containerPort": 80,
"healthCheck": {
"healthyThreshold": 2,
"unhealthyThreshold": 2,
"timeoutSeconds": 2,
"intervalSeconds": 5,
"path": "/",
"successCodes": "200-499"
}
},
"createdAt": "2024-03-15T11:43:10-04:00"
},
"isDisabled": false,
"principalArn": "arn:aws:iam::577312533299:role/amazon/lightsail/eu-west-3/containers/signup-application/1jetjd21p8qshe57seuh71tnrnn29ps77lnno20sbgl2ghbuc0r0",
"privateDomainName": "signup-application.service.local",
"url": "https://signup-application.me04fvc6dbk4e.eu-west-3.cs.amazonlightsail.com/"
}
}
Test your deployment
To test the deployment, switch to your browser window and refresh the page on the container service URL provided in the previous module.
You can retrieve the URL by entering this command in a terminal:
aws lightsail get-container-services --region eu-west-3 --query "containerServices[].url"
The command outputs a message, such as the following:
# aws lightsail get-container-services --region eu-west-3 --query "containerServices[].url"
[
"https://signup-application.me04fvc6dbk4e.eu-west-3.cs.amazonlightsail.com/"
]
Roll back a deployment
The last deployment did not override the first version of the application; it just created a new version.
To verify the versions available, open a terminal and enter the following command:
aws lightsail get-container-service-deployments --region eu-west-3 --service-name signup-application
The command outputs a message, such as the following:
# aws lightsail get-container-service-deployments --region eu-west-3 --service-name signup-application
{
"deployments": [
{
"version": 1,
"state": "ACTIVE",
"containers": {
"signup-app-container": {
"image": ":signup-application.latest.1",
"command": [],
"environment": {},
"ports": {
"80": "HTTP"
}
}
},
"publicEndpoint": {
"containerName": "signup-app-container",
"containerPort": 80,
"healthCheck": {
"healthyThreshold": 2,
"unhealthyThreshold": 2,
"timeoutSeconds": 2,
"intervalSeconds": 5,
"path": "/",
"successCodes": "200-499"
}
},
"createdAt": "2024-03-13T14:21:30-04:00"
}
]
}
Reading the output of the previous command, you can observe there are two deployment versions. Version 1 is in an INACTIVE state, while version 2 is ACTIVE.
The following command gives a less detailed overview of your deployments:
aws lightsail get-container-service-deployments --region eu-west-3 --service-name signup-application --query 'deployments[].{version: version, state: state, image:containers.\"signup-app-container\".image}'
The command outputs a message, such as the following:
# aws lightsail get-container-service-deployments --region eu-west-3 --service-name signup-application --query 'deployments[].{version: version, state: state, image:containers.\"signup-app-container\".image}'
[
{
"version": 2,
"state": "ACTIVE",
"image": ":signup-application.latest.2"
},
{
"version": 1,
"state": "INACTIVE",
"image": ":signup-application.latest.1"
}
]
Now imagine the last version of the application you just deployed is not behaving correctly. Maybe a bug has not surfaced during the testing.
To access the log of your containers, open a terminal and enter the following command:
aws lightsail get-container-log --region eu-west-3 --service-name signup-application --container-name signup-app-container --output text
The command outputs a message, similar to the following:
# aws lightsail get-container-log --region eu-west-3 --service-name signup-application --container-name signup-app-container --output text
LOGEVENTS 2024-03-18T10:29:28-04:00 [deployment:1] Creating your deployment
LOGEVENTS 2024-03-18T10:30:03-04:00 Starting NGinx
LOGEVENTS 2024-03-18T10:30:03-04:00 2024/03/18 14:30:03 [notice] 13#13: using the "epoll" event method
LOGEVENTS 2024-03-18T10:30:03-04:00 2024/03/18 14:30:03 [notice] 13#13: nginx/1.25.4
LOGEVENTS 2024-03-18T10:30:03-04:00 2024/03/18 14:30:03 [notice] 13#13: built by gcc 12.2.0 (Debian 12.2.0-14)
...
To quickly roll back your deployment and redeploy the previous version of the application, change the lc.json file to make it use the first version of the container image and redeploy this image.
Modify the lc.json file to the following:
{
"serviceName": "signup-application",
"containers": {
"signup-app-container": {
"image": ":signup-application.latest.1",
"ports": {
"80": "HTTP"
}
}
},
"publicEndpoint": {
"containerName": "signup-app-container",
"containerPort": 80
}
}
Then run the following command in the terminal:
aws lightsail create-container-service-deployment --region eu-west-3 --cli-input-json file://lc.json
The command outputs a message, similar to the following:
# aws lightsail create-container-service-deployment --region eu-west-3 --cli-input-json file://lc.json
{
"containerService": {
"containerServiceName": "signup-application",
"arn": "arn:aws:lightsail:eu-west-3:607950359977:ContainerService/d9203026-b87b-4e6a-8a91-df2540dbfe86",
"createdAt": "2024-03-18T10:25:22-04:00",
"location": {
"availabilityZone": "all",
"regionName": "eu-west-3"
},
"resourceType": "ContainerService",
"tags": [],
"power": "nano",
"powerId": "nano-1",
"state": "DEPLOYING",
"scale": 2,
"currentDeployment": {
"version": 2,
"state": "ACTIVE",
"containers": {
"signup-app-container": {
"image": ":signup-application.latest.2",
"command": [],
"environment": {},
"ports": {
"80": "HTTP"
}
}
},
"publicEndpoint": {
"containerName": "signup-app-container",
"containerPort": 80,
"healthCheck": {
"healthyThreshold": 2,
"unhealthyThreshold": 2,
"timeoutSeconds": 2,
"intervalSeconds": 5,
"path": "/",
"successCodes": "200-499"
}
},
"createdAt": "2024-03-18T10:41:11-04:00"
},
"nextDeployment": {
"version": 3,
"state": "ACTIVATING",
"containers": {
"signup-app-container": {
"image": ":signup-application.latest.1",
"command": [],
"environment": {},
"ports": {
"80": "HTTP"
}
}
},
"publicEndpoint": {
"containerName": "signup-app-container",
"containerPort": 80,
"healthCheck": {
"healthyThreshold": 2,
"unhealthyThreshold": 2,
"timeoutSeconds": 2,
"intervalSeconds": 5,
"path": "/",
"successCodes": "200-499"
}
},
"createdAt": "2024-03-18T10:55:42-04:00"
},
"isDisabled": false,
"principalArn": "arn:aws:iam::844358175455:role/amazon/lightsail/eu-west-3/containers/signup-application/1jetjd21p8qshe57seuh71tnrnn29ps77lnno20sbgl2ghbuc0r0",
"privateDomainName": "signup-application.service.local",
"url": "https://signup-application.oh6a4qb72ia80.eu-west-3.cs.amazonlightsail.com/",
"privateRegistryAccess": {
"ecrImagePullerRole": {
"isActive": false,
"principalArn": ""
}
}
}
}
After a while, deployment v3, using container image v1 is ACTIVE. Deployments v2 and v1 are INACTIVE.
You can verify the first version is deployed by opening your browser and pointing it at the container service URL.
Conclusion
This is the end of this tutorial. Before taking a well-deserved break, be sure to clean up the environment to not accrue charges on your AWS account.
Up Next: Clean Up Resources