I want to automatically delete the existing container images that are not currently in use from the storage. We store the images already elsewhere and aws will reject a container push if too many images build up.
This is currently my .gitlab-ci.yml
job that I use to automatically push our image over to aws. What I have works if the first image is the one that is in use, but I would like something more robust for our more complex services with multiple containers in one deployment. Something about this just feels wrong and I feel like I am missing a more obvious way to "delete all the images I am allowed to delete".
deploy:
stage: Deploy
only:
- tags
- main
image: registry.gitlab/my-group/my-project:deployment
services:
- docker:dind
needs: ["build_web"]
before_script:
- docker login registry.gitlab -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD}
script:
- docker buildx build -t ${SERVICE_IMAGE} -f Dockerfile .
- all_images=$(aws lightsail get-container-images --service-name ${SERVICE_NAME} --query "containerImages[].image" --output text)
- skip_image=$(echo $all_images | awk '{print $1}')
- |
for image in $all_images; do
if [ "$image" != "$skip_image" ]; then
echo "Deleting old image: $image";
aws lightsail delete-container-image --service-name ${SERVICE_NAME} --image "$image";
fi;
done
- aws lightsail push-container-image --service-name ${SERVICE_NAME} --label ${SERVICE_NAME}-${CI_PIPELINE_ID} --image ${SERVICE_IMAGE}
- |
aws lightsail create-container-service-deployment \
--region us-east-2 \
--service-name ${SERVICE_NAME} \
--output yaml \
--containers "{
\"${SERVICE_NAME}\": {
\"image\": \":${SERVICE_NAME}.${SERVICE_NAME}-${CI_PIPELINE_ID}.latest\",
\"environment\": {
\"PORT\": \"3001\"
},
\"ports\": {
\"3001\": \"HTTP\"
}
}
}" \
--public-endpoint "{
\"containerName\": \"${SERVICE_NAME}\",
\"containerPort\": 3001,
\"healthCheck\": {
\"path\": \"/\",
\"timeoutSeconds\": 2,
\"intervalSeconds\": 5,
\"healthyThreshold\": 2,
\"unhealthyThreshold\": 2,
\"successCodes\": \"200-499\"
}
}"
after_script:
- docker push ${SERVICE_IMAGE}
environment: production
I want to automatically delete the existing container images that are not currently in use from the storage. We store the images already elsewhere and aws will reject a container push if too many images build up.
This is currently my .gitlab-ci.yml
job that I use to automatically push our image over to aws. What I have works if the first image is the one that is in use, but I would like something more robust for our more complex services with multiple containers in one deployment. Something about this just feels wrong and I feel like I am missing a more obvious way to "delete all the images I am allowed to delete".
deploy:
stage: Deploy
only:
- tags
- main
image: registry.gitlab.com/my-group/my-project:deployment
services:
- docker:dind
needs: ["build_web"]
before_script:
- docker login registry.gitlab.com -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD}
script:
- docker buildx build -t ${SERVICE_IMAGE} -f Dockerfile .
- all_images=$(aws lightsail get-container-images --service-name ${SERVICE_NAME} --query "containerImages[].image" --output text)
- skip_image=$(echo $all_images | awk '{print $1}')
- |
for image in $all_images; do
if [ "$image" != "$skip_image" ]; then
echo "Deleting old image: $image";
aws lightsail delete-container-image --service-name ${SERVICE_NAME} --image "$image";
fi;
done
- aws lightsail push-container-image --service-name ${SERVICE_NAME} --label ${SERVICE_NAME}-${CI_PIPELINE_ID} --image ${SERVICE_IMAGE}
- |
aws lightsail create-container-service-deployment \
--region us-east-2 \
--service-name ${SERVICE_NAME} \
--output yaml \
--containers "{
\"${SERVICE_NAME}\": {
\"image\": \":${SERVICE_NAME}.${SERVICE_NAME}-${CI_PIPELINE_ID}.latest\",
\"environment\": {
\"PORT\": \"3001\"
},
\"ports\": {
\"3001\": \"HTTP\"
}
}
}" \
--public-endpoint "{
\"containerName\": \"${SERVICE_NAME}\",
\"containerPort\": 3001,
\"healthCheck\": {
\"path\": \"/\",
\"timeoutSeconds\": 2,
\"intervalSeconds\": 5,
\"healthyThreshold\": 2,
\"unhealthyThreshold\": 2,
\"successCodes\": \"200-499\"
}
}"
after_script:
- docker push ${SERVICE_IMAGE}
environment: production
After some work I came up with the following:
- |
ACTIVE_IMAGES=$(aws lightsail get-container-services \
--service-name ${SERVICE_NAME} \
--query "containerServices[0].currentDeployment.containers.*.image" \
--output text)
EXISTING_IMAGES=$(aws lightsail get-container-images \
--service-name ${SERVICE_NAME} \
--query "containerImages[*].image" \
--output text)
for IMAGE in ${EXISTING_IMAGES}; do
if [[ ! "${ACTIVE_IMAGES}" =~ "${IMAGE}" ]]; then
echo "Deleting unused image: ${IMAGE}"
aws lightsail delete-container-image \
--service-name ${SERVICE_NAME} \
--image "${IMAGE}"
fi
done