-
-
Save jlis/4bc528041b9661ae6594c63cd2ef673c to your computer and use it in GitHub Desktop.
image: docker:latest | |
variables: | |
REPOSITORY_URL: <AWS ACCOUNT ID>.dkr.ecr.eu-central-1.amazonaws.com/<ECS REPOSITORY NAME> | |
REGION: eu-central-1 | |
TASK_DEFINTION_NAME: <TASK DEFINITION NAME> | |
CLUSTER_NAME: <CLUSTER NAME> | |
SERVICE_NAME: <SERVICE NAME> | |
services: | |
- docker:dind | |
before_script: | |
- apk add --no-cache curl jq python py-pip | |
- pip install awscli | |
- $(aws ecr get-login --no-include-email --region "${REGION}") | |
- IMAGE_TAG="$(echo $CI_COMMIT_SHA | head -c 8)" | |
stages: | |
- build | |
- deploy | |
build: | |
stage: build | |
script: | |
- echo "Building image..." | |
- docker build -t $REPOSITORY_URL:latest . | |
- echo "Tagging image..." | |
- docker tag $REPOSITORY_URL:latest $REPOSITORY_URL:$IMAGE_TAG | |
- echo "Pushing image..." | |
- docker push $REPOSITORY_URL:latest | |
- docker push $REPOSITORY_URL:$IMAGE_TAG | |
only: | |
- master | |
deploy: | |
stage: deploy | |
script: | |
- echo $REPOSITORY_URL:$IMAGE_TAG | |
- TASK_DEFINITION=$(aws ecs describe-task-definition --task-definition "$TASK_DEFINTION_NAME" --region "${REGION}") | |
- NEW_CONTAINER_DEFINTIION=$(echo $TASK_DEFINITION | python $CI_PROJECT_DIR/update_task_definition_image.py $REPOSITORY_URL:$IMAGE_TAG) | |
- echo "Registering new container definition..." | |
- aws ecs register-task-definition --region "${REGION}" --family "${TASK_DEFINTION_NAME}" --container-definitions "${NEW_CONTAINER_DEFINTIION}" | |
- echo "Updating the service..." | |
- aws ecs update-service --region "${REGION}" --cluster "${CLUSTER_NAME}" --service "${SERVICE_NAME}" --task-definition "${TASK_DEFINTION_NAME}" | |
only: | |
- master |
import sys, json, argparse | |
parser = argparse.ArgumentParser('Replaces image in the task definition') | |
parser.add_argument('image_uri', metavar='I', type=str, nargs='+', | |
help='The new image URI') | |
args = parser.parse_args() | |
definition = json.load(sys.stdin)['taskDefinition']['containerDefinitions'] | |
definition[0]['image'] = args.image_uri[0] | |
print json.dumps(definition) |
If you don't want to have external definition file you can also do this.
aws ecs register-task-definition --region ${region} --family ${task_defintion_name} --container-definitions " \
[
{
\"name\": \"hippo-ui\",
\"image\": \"${image}\",
\"cpu\": 10,
\"memory\": 256,
\"essential\": true,
\"portMappings\": [
{
\"containerPort\": 4200
}
],
\"logConfiguration\": {
\"logDriver\": \"awslogs\",
\"options\": {
\"awslogs-group\" : \"/ecs/hippo-ui-container\",
\"awslogs-region\": \"us-east-2\"
}
}
}
]"
You can also add the following commands to check if the previous task was successfully stopped and the new one is started:
- TASK_ARN=$(aws ecs list-tasks --region "${REGION}" --cluster "${CLUSTER_NAME}" --service-name "${SERVICE_NAME}") - TASK_ID=$(echo ${TASK_ARN:72:36}) - echo "Waiting until the previous task ${TASK_ID} is stopped..." - aws ecs wait tasks-stopped --region "${REGION}" --cluster "${CLUSTER_NAME}" --tasks "${TASK_ID}" - echo "The previous task ${TASK_ID} has stopped." - TASK_ARN=$(aws ecs list-tasks --region "${REGION}" --cluster "${CLUSTER_NAME}" --service-name "${SERVICE_NAME}") - TASK_ID=$(echo ${TASK_ARN:72:36}) - echo "New task ${TASK_ID} is running." - aws ecs describe-tasks --region "${REGION}" --cluster "${CLUSTER_NAME}" --tasks "${TASK_ID}"
You can also add the following commands to check if the previous task was successfully stopped and the new one is started:
- TASK_ARN=$(aws ecs list-tasks --region "${REGION}" --cluster "${CLUSTER_NAME}" --service-name "${SERVICE_NAME}") - TASK_ID=$(echo ${TASK_ARN:72:36}) - echo "Waiting until the previous task ${TASK_ID} is stopped..." - aws ecs wait tasks-stopped --region "${REGION}" --cluster "${CLUSTER_NAME}" --tasks "${TASK_ID}" - echo "The previous task ${TASK_ID} has stopped." - TASK_ARN=$(aws ecs list-tasks --region "${REGION}" --cluster "${CLUSTER_NAME}" --service-name "${SERVICE_NAME}") - TASK_ID=$(echo ${TASK_ARN:72:36}) - echo "New task ${TASK_ID} is running." - aws ecs describe-tasks --region "${REGION}" --cluster "${CLUSTER_NAME}" --tasks "${TASK_ID}"
If there are more than ONE task then it should be TASK_ID=$(echo ${TASK_ARN:82:32})
Anyone here has a solution to pass a container environment used on applications?
Like injecting this Envs in the task definition.
Note, in Gitlab you can now use $CI_COMMIT_SHORT_SHA
instead of "$(echo $CI_COMMIT_SHA | head -c 8)"
. See: https://docs.gitlab.com/ee/ci/variables/predefined_variables.html#:~:text=is%20built%20for.-,CI_COMMIT_SHORT_SHA,-11.7
Anyone here has a solution to pass a container environment used on applications?
Like injecting this Envs in the task definition.
I have used sed command in my pipeline to inject env vars in task definition file.
- TASK_DEFINITION=$(aws ecs describe-task-definition --task-definition "$CI_AWS_ECS_TASK_DEFINITION" --region "${AWS_DEFAULT_REGION}")
- NEW_CONTAINER_DEFINTIION=$(echo $TASK_DEFINITION | jq --arg IMAGE "$DOCKER_REGISTRY/$APP_NAME:latest" '.taskDefinition.containerDefinitions[0].image = $IMAGE | .taskDefinition.containerDefinitions[0]')
- echo "Registering new container definition..."
- aws ecs register-task-definition --region "${AWS_DEFAULT_REGION}" --family "${CI_AWS_ECS_TASK_DEFINITION}" --container-definitions "${NEW_CONTAINER_DEFINTIION}"
- echo "Updating the service..."
- aws ecs update-service --region "${AWS_DEFAULT_REGION}" --cluster "${CI_AWS_ECS_CLUSTER}" --service "${CI_AWS_ECS_SERVICE}" --task-definition "${CI_AWS_ECS_TASK_DEFINITION}"
this is the script i'm using however the service deployment does not start the desired task count is 1 however it does not create any
or you can use sed to set the new image tag, in my case, the CI_PIPELINE_IID and then use jq to extract the container definition:
NEW_CONTAINER_DEFINITION=$(echo $TASK_DEFINITION | sed -e "s/ecr-image:.*/ecr-image:$CI_PIPELINE_IID\",/g")
NEW_CONTAINER_DEFINITION=$(echo $NEW_CONTAINER_DEFINITION | jq '.taskDefinition.containerDefinitions[0]')
Actually there was nothing wrong with the script, it was failing to bind a port to the new container because I was using a static port binding.
Later I switched to using gitlab's ecs deployment script
- TASK_DEFINITION=$(aws ecs describe-task-definition --task-definition "$CI_AWS_ECS_TASK_DEFINITION" --region "${AWS_DEFAULT_REGION}") - NEW_CONTAINER_DEFINTIION=$(echo $TASK_DEFINITION | jq --arg IMAGE "$DOCKER_REGISTRY/$APP_NAME:latest" '.taskDefinition.containerDefinitions[0].image = $IMAGE | .taskDefinition.containerDefinitions[0]') - echo "Registering new container definition..." - aws ecs register-task-definition --region "${AWS_DEFAULT_REGION}" --family "${CI_AWS_ECS_TASK_DEFINITION}" --container-definitions "${NEW_CONTAINER_DEFINTIION}" - echo "Updating the service..." - aws ecs update-service --region "${AWS_DEFAULT_REGION}" --cluster "${CI_AWS_ECS_CLUSTER}" --service "${CI_AWS_ECS_SERVICE}" --task-definition "${CI_AWS_ECS_TASK_DEFINITION}"
this is the script i'm using however the service deployment does not start the desired task count is 1 however it does not create any
you can set minimum healthy percent to 0 and maximum percent to 100 if you want only one container running on your ecs.
Hi Guys,
I have done with my gitlab pipeline one branh (master) and now i have fail with two branh both master, develop branh.
Please help me to wrire into .gitlab-ci.yml one
build:
stage: build
deploy:
stage: deploy
all develop, master branh?
Thank for help and hope see rely soon.
Hi there!
Just finished with ECS FARGATE deployment step at the GitLab CI. Want to share the result.
Hopefully, this would be helpful and save time for someone ;)
- TASK_DEFINITION_CURRENT=$(aws ecs describe-services --services "${ECS_SERVICE_NAME}" --cluster "${ECS_CLUSTER_NAME}" | jq -r .services[].taskDefinition | cut -d "/" -f 2)
- TASK_DEFINTION_NAME=$(echo $TASK_DEFINITION_CURRENT | cut -d ":" -f 1 )
- TASK_DEFINITION=$(aws ecs describe-task-definition --task-definition "$TASK_DEFINTION_NAME")
- NEW_CONTAINER_DEFINTIION=$(echo $TASK_DEFINITION | jq --arg IMAGE "${CI_REGISTRY_IMAGE}/${CI_COMMIT_REF_SLUG}:${DEPLOY_CONTAINER_TAG}" '.taskDefinition.containerDefinitions[0].image = $IMAGE | .taskDefinition.containerDefinitions[0]')
- EXECUTION_ROLE_ARN=$(echo $TASK_DEFINITION | jq -r '.taskDefinition.executionRoleArn')
- TASK_ROLE_ARN=$(echo $TASK_DEFINITION | jq -r '.taskDefinition.taskRoleArn')
- CONTAINER_MEMORY=$(echo $TASK_DEFINITION | jq -r '.taskDefinition.memory')
- CONTAINER_CPU=$(echo $TASK_DEFINITION | jq -r '.taskDefinition.cpu')
- REQUIRE_COMPATABILITIES=$(echo $TASK_DEFINITION | jq -r '.taskDefinition.requiresCompatibilities[]')
- NETWORK_MODE=$(echo $TASK_DEFINITION | jq -r '.taskDefinition.networkMode')
- echo "Registering new container definition..."
- aws ecs register-task-definition --family "${TASK_DEFINTION_NAME}" --container-definitions "${NEW_CONTAINER_DEFINTIION}" --execution-role-arn "${EXECUTION_ROLE_ARN}" --memory "${CONTAINER_MEMORY}" --requires-compatibilities "${REQUIRE_COMPATABILITIES}" --network-mode "${NETWORK_MODE}" --cpu "${CONTAINER_CPU}" --task-role-arn "${TASK_ROLE_ARN}"
- echo "Updating the service..."
- aws ecs update-service --cluster "${ECS_CLUSTER_NAME}" --service "${ECS_SERVICE_NAME}" --task-definition "${TASK_DEFINTION_NAME}"
to avoid python you can use jq
- NEW_CONTAINER_DEFINTIION=$(echo $TASK_DEFINITION | jq --arg IMAGE "$REPOSITORY_URL:$IMAGE_TAG" '.taskDefinition.containerDefinitions[0].image = $IMAGE | .taskDefinition.containerDefinitions[0]')
Hi,
Is there anyway we can pass two container images with this? I have been trying to work around this and could not find any solutions.
Hi Team ,
ia m getting below vunrability how to fix any one pls help
Improper access control in the Intel(R) Ethernet Controller RDMA driver for linux before version 1.9.30 may allow an unauthenticated user to potentially enable escalation of privilege via network access.
Hi Team ,
i am using for deployment below script
scripts:
- $(aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ECR_REGISTRY | tr -d '\r')
- TASK_DEFINITION_CURRENT=$(aws ecs describe-services --services "${SERVICE_NAME}" --cluster "${CLUSTER_NAME}" | jq -r .services[].taskDefinition | cut -d "/" -f 2)
- TASK_DEFINTION_NAME=$(echo $TASK_DEFINITION_CURRENT | cut -d ":" -f 1 )
- TASK_DEFINITION=$(aws ecs describe-task-definition --task-definition "$TASK_DEFINTION_NAME")
- NEW_CONTAINER_DEFINTIION=$(echo
$TASK_DEFINITION | jq --arg IMAGE "$ {AWS_ECR_REGISTRY}/${APP_NAME}/${CI_COMMIT_REF_SLUG}:${SEMVER}" '.taskDefinition.containerDefinitions[0].image = $IMAGE | .taskDefinition.containerDefinitions[0]') - EXECUTION_ROLE_ARN=$(echo $TASK_DEFINITION | jq -r '.taskDefinition.executionRoleArn')
- TASK_ROLE_ARN=$(echo $TASK_DEFINITION | jq -r '.taskDefinition.taskRoleArn')
- CONTAINER_MEMORY=$(echo $TASK_DEFINITION | jq -r '.taskDefinition.memory')
- CONTAINER_CPU=$(echo $TASK_DEFINITION | jq -r '.taskDefinition.cpu')
- REQUIRE_COMPATABILITIES=$(echo $TASK_DEFINITION | jq -r '.taskDefinition.requiresCompatibilities[]')
- NETWORK_MODE=$(echo $TASK_DEFINITION | jq -r '.taskDefinition.networkMode')
- echo "Registering new container definition..."
- aws ecs register-task-definition --family "${TASK_DEFINTION_NAME}" --container-definitions "${NEW_CONTAINER_DEFINTIION}" --execution-role-arn "${EXECUTION_ROLE_ARN}" --memory "${CONTAINER_MEMORY}" --requires-compatibilities "${REQUIRE_COMPATABILITIES}" --network-mode "${NETWORK_MODE}" --cpu "${CONTAINER_CPU}" --task-role-arn "${TASK_ROLE_ARN}"
- echo "Updating the service..."
- aws ecs update-service --cluster "${CLUSTER_NAME}" --service "${SERVICE_NAME}" --task-definition "${TASK_DEFINTION_NAME}"
but i am getting below error
“message”: “(service crm-api-secured) failed to launch a task with (error ECS was unable to assume the role ‘arn:aws:iam::XXXXXXXXX:role/null’ that was provided for this task. Please verify that the role being passed has the proper trust relationship and permissions and that your IAM user has permissions to pass this role.).”
any one pls help for the same.
Hello,
I am running the same in GitlabCI but getting the authentication error in below command:
aws ecs register-task-definition --region "${AWS_DEFAULT_REGION}" --family "${TASK_DEFINITION_NAME}" --container-definitions "${NEW_CONTAINER_DEFINTIION}"
Error :"An error occurred (ClientException) when calling the RegisterTaskDefinition operation: Private repository authentication requires that the task definition specify a value for executionRoleArn."
How to pass the credentials for private repo.