I am studying Terraform. Currently, I am deploying my application to AWS. I use EC2, Cluster, Task Definition, ASG, and others.
My application deployment includes building a Docker image with my Java code, which is located in another GitHub repository. I am using GitHub Actions for deployment.
Now, part of my Terraform code looks like this:
resource "null_resource" "build_docker_image" {
provisioner "local-exec" {
working_dir = var.work_directory
command = \<\<EOF
aws ecr get-login-password --region ${var.region} | docker login --username AWS --password-stdin ${data.aws_caller_identity.current_user.account_id}.dkr.ecr.${var.region}.amazonaws.com && cd ${var.work_directory} && chmod +x ./mvnw && ./mvnw clean package && docker build -t ${var.back_repository_name} . && docker tag ${var.back_repository_name}:latest ${data.aws_caller_identity.current_user.account_id}.dkr.ecr.${var.region}.amazonaws.com/${var.back_repository_name}:latest && docker push ${data.aws_caller_identity.current_user.account_id}.dkr.ecr.${var.region}.amazonaws.com/${var.back_repository_name}:latest
EOF
}
triggers = {
"run_at" = timestamp()
}
}
However, this command is very long because it is written in one line.
I tried to make this line shorter, but I could not succeed. If I write this command on multiple lines, when I run my Terraform (terraform apply), only the first line runs.
I tried using bash, but it did not work (<3>WSL (34) ERROR: CreateProcessParseCommon:711: Failed to translate):
provisioner "local-exec" {
working_dir = var.work_directory
command = <<EOF
bash deploy.sh ${var.region} ${data.aws_caller_identity.current_user.account_id} ${var.back_repository_name}
EOF
}
#!/bin/bash
aws ecr get-login-password --region $1 | docker login --username AWS --password-stdin $2.dkr.ecr.$1.amazonaws.com
docker build -t $3 .
docker tag $3:latest $2.dkr.ecr.$1.amazonaws.com/$3:latest
docker push $2.dkr.ecr.$1.amazonaws.com/$3:latest
Also, I try use ' / ' or ' \n ' but it is not work too.
Please help me solve the problem. May be there are patters for building docker image.
From the bash manual:
The backslash character
‘\’
may be used to remove any special meaning for the next character read and for line continuation.
So if you would like to break one command into multiple lines you need to use the \
character in the place where you would like to move the command to the next line:
resource "null_resource" "build_docker_image" {
provisioner "local-exec" {
working_dir = var.work_directory
command = <<EOF
aws ecr get-login-password --region ${var.region} | docker login \
--username AWS \
--password-stdin ${data.aws_caller_identity.current_user.account_id}.dkr.ecr.${var.region}.amazonaws.com && \
cd ${var.work_directory} && \
chmod +x ./mvnw && \
./mvnw clean package && \
docker build -t ${var.back_repository_name} . && \
docker tag ${var.back_repository_name}:latest ${data.aws_caller_identity.current_user.account_id}.dkr.ecr.${var.region}.amazonaws.com/${var.back_repository_name}:latest && \
docker push ${data.aws_caller_identity.current_user.account_id}.dkr.ecr.${var.region}.amazonaws.com/${var.back_repository_name}:latest
EOF
}
triggers = {
"run_at" = timestamp()
}
}
Or for better readability start heredoc with <<EOF-
(mind the hyphen) so you can use indentation inside heredoc which will be ignored by Terraform (Indented Heredocs):
resource "null_resource" "build_docker_image" {
provisioner "local-exec" {
working_dir = var.work_directory
command = <<-EOF
aws ecr get-login-password --region ${var.region} | docker login \
--username AWS \
--password-stdin ${data.aws_caller_identity.current_user.account_id}.dkr.ecr.${var.region}.amazonaws.com && \
cd ${var.work_directory} && \
chmod +x ./mvnw && \
./mvnw clean package && \
docker build -t ${var.back_repository_name} . && \
docker tag ${var.back_repository_name}:latest ${data.aws_caller_identity.current_user.account_id}.dkr.ecr.${var.region}.amazonaws.com/${var.back_repository_name}:latest && \
docker push ${data.aws_caller_identity.current_user.account_id}.dkr.ecr.${var.region}.amazonaws.com/${var.back_repository_name}:latest
EOF
}
triggers = {
"run_at" = timestamp()
}
}