Voici la procédure pour déployer des containers Docker sur Fargate.


Rôle ecsTaskExecutionRole

Vérifier l’existance de ce rôle dans l’IAM. S’il n’existe pas, il faut le créer:

Créer un fichier appelé task-execution-assume-role.json avec ce contenu:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "ecs-tasks.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Créer une tâche d’exécution de rôle:

aws iam --region eu-west-1 create-role --role-name ecsTaskExecutionRole --assume-role-policy-document file://task-execution-assume-role.json

Attacher la tâche d’exécution de rôle:

aws iam --region eu-west-1 attach-role-policy --role-name ecsTaskExecutionRole --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

Configurer AWS cli et ecs cli

# Pour OSX
brew upgrade amazon-ecs-cli
brew upgrade awscli

rm -rf ~/.ecs # ou mv ~/.ecs ...

export PROJECT_NAME=xxxxxxxxxxxxx

# Création d'un profil
ecs-cli configure profile --access-key $AWS_ACCESS_KEY_ID --secret-key $AWS_SECRET_ACCESS_KEY --profile-name $PROJECT_NAME

Création d’un cluster

ecs-cli configure --cluster $PROJECT_NAME --region eu-west-1 --default-launch-type FARGATE --config-name $PROJECT_NAME

ecs-cli up

Output:

...
VPC created: vpc-xxxxxxxxxx
Subnet created: subnet-xxxxxxxxx
Subnet created: subnet-xxxxxxxxx
Cluster creation succeeded.

Création d’un securitygroup

export VPC_ID="vpc-xxxxxxxxxxxxxxxxxxx"

# securitygroup name
export SG_NAME="xxxxxxxxxxxxx-sg"

export SG_DESCRIPTION="xxxxxxxxxx xxxxxx xxx security group"

aws ec2 create-security-group --group-name $SG_NAME --description $SG_DESCRIPTION --vpc-id $VPC_ID

Output:

{
    "GroupId": "sg-xxxxxxxxxxxxxxx"
}

Création règle Ingress

export SG_GROUP_ID="sg-xxxxxxxxxxxxxxxxx"

aws ec2 authorize-security-group-ingress --group-id $SG_GROUP_ID --protocol tcp --port 8080 --cidr 0.0.0.0/0

Configuration Docker et Ressources

Créer un fichier docker-compose.yml

version: '3'
services:
  SERVICE_NAME_IE_WP:
    image: IMAGE_DOCKER
    ports:
      - "8080:8080"
    logging:
      driver: awslogs
      options: 
        awslogs-group: PROJECT_NAME
        awslogs-region: eu-west-1
        awslogs-stream-prefix: SERVICE_NAME_IE_WP

Créer un fichier ecs-params.yml:

version: 1
task_definition:
  task_execution_role: ecsTaskExecutionRole
  ecs_network_mode: awsvpc
  task_size:
    mem_limit: 0.5GB
    cpu_limit: 256
run_params:
  network_configuration:
    awsvpc_configuration:
      subnets:
        - "subnet-xxxxxxxxxxxxxxxxx"
        - "subnet-xxxxxxxxxxxxxxxxx"
      security_groups:
        - "sg-xxxxxxxxxxxxxxxxxx"
      assign_public_ip: ENABLED

Déploiement sur Fargate:

ecs-cli compose --project-name $PROJECT_NAME service up --create-log-groups --cluster-config $PROJECT_NAME

Pour updater le container, il suffit de réexécuter la commande ci-dessus. Une nouvelle version de la task déployée se créera et l’ancienne sera éteinte.

Note: Pour ajouter une instance RDS et l’utiliser dans le container, le plus simple est de créer l’instance RDS dans le VPC du container. Puis il faudra créer une rêgle dans le securitygroup créé précédemment et réutilisant la commande suivante: aws ec2 authorize-security-group-ingress --group-id $SG_GROUP_ID --protocol tcp --port 5432 --cidr 0.0.0.0/0

Rien de plus simple et le tarif est intéressant: https://aws.amazon.com/fr/fargate/pricing/


Troubleshooting

Restart task:

Attention l’IP publique sera modifiée.

export SERVICE_NAME=xxxx
export CLUSTER_NAME=xxxx

aws ecs update-service --force-new-deployment --cluster $CLUSTER_NAME --service $SERVICE_NAME

Tip: Useful bash functions

stop_running_tasks() {
    tasks=$(aws ecs list-tasks --cluster $CLUSTER --service $SERVICE | $JQ ".taskArns | . []");
    tasks=( $tasks )
    for task in "${tasks[@]}"
    do
        [[ ! -z "$task" ]] && stop_task=$(aws ecs stop-task --cluster $CLUSTER --task "$task")
    done
}

push_ecr_image(){
    echo "Push built image to ECR"
    eval $(aws ecr get-login --region us-east-1)
    docker push $AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/repository:$TAG
}

configure_aws_cli(){
    aws --version
    aws configure set default.region us-east-1
    aws configure set default.output json
}

start_tasks() {
    start_task=$(aws ecs start-task --cluster $CLUSTER --task-definition $DEFINITION --container-instances $EC2_INSTANCE --group $SERVICE_GROUP --started-by $SERVICE_ID)
    echo "$start_task"
}