Post

Terraform pt 2: Create Elastic Container Registry (DevOps the Hard Way series)

Terraform pt 2: Create Elastic Container Registry (DevOps the Hard Way series)

In this post, the Terraform CLI will be used to create an Amazon Elastic Container Registry, where a container image for the Uber API will be saved.

Terraform: creating an Elastic Container Registry (ECR)

Unlike in the previous post, instead of downloading just one file named main.tf, there will be two additional files involved: variables.tf, and terraform.tfvars.

main.tf

Below is main.tf, exactly as provided in the Devops the Hard Way repo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
terraform {
  backend "s3" {
    bucket = "terraform-state-devopsthehardway"
    key    = "ecr-terraform.tfstate"
    region = "us-east-1"
  }
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

resource "aws_ecr_repository" "devopsthehardway-ecr-repo" {
  name                 = var.repo_name
  image_tag_mutability = "MUTABLE"

  image_scanning_configuration {
    scan_on_push = true
  }
}

Let’s review this file section by section:

The terraform block

The file begins with a terraform block, which is a block type that didn’t exist in the previous blog post’s version of main.tf. Per Terraform’s documentation:

The special terraform configuration block type is used to configure some behaviors of Terraform itself

and

The nested backend block configures which state backend Terraform should use.

The specific terraform block introduced in this example tells Terraform where to save its required state data: to the S3 bucket that was created in the previous post for exactly that purpose.

It’s important to realize that the hard-coded bucket name of "terraform-state-devopsthehardway" will need to be edited to match whatever (globally unique) bucket name was successfully used in the previous post.

Also, AWS credentials must be explicitly added to the backend block for access to the S3 bucket, or terraform init will not successfully run.

The provider block

Next in main.tf comes a provider declaration, which is identical to the one seen in the previous post. AWS credentials will need to be added into this section, like last time. These credentials will be used for the actual creation of an Elastic Container Registry (ECR).

The resource block

Finally, the resource being declared in this file is an aws_ecr_repository, with a name of devopsthehardway-ecr-repo. This section should not require any editing.

Note that the resource block contains this line:

1
name                 = var.repo_name

The text var.repo_name is a placeholder for a Terraform input variable and will be substituted with text input from elsewhere. But where?

That is where the new files introduced in this section, variables.tf and terraform.tfvars, come in.

variables.tf

1
2
3
4
5
variable repo_name {
  type        = string
  default     = "devopsthehardway"
  description = "ECR repo to store a Docker image"
}

When this additional .tf file is saved in the same directory as main.tf, and the Terraform CLI is run inside that directory, Terraform will also read the additional .tf file during its infrastructure provisioning process. Together, the .tf files comprise a Terraform module.

In this example, Terraform reads variables.tf, where an input variable repo_name is declared with a default value of "devopsthehardway".

terraform.tfvars

There is one more Terraform file used in this example, named terraform.tfvars. While the variables.tf file seen earlier is where the repo_name input variable is declared (and provided with a default value), terraform.tfvars is where that variable’s value is explicitly defined:

1
repo_name = "devopsthehardway-ecr"

Terraform provides several options for assigning values to input variables, and one of them is the use of a .tfvars file, as shown in the example above.

Why all the different Terraform files? Declaring Terraform input variables in a separate .tf file, and their values in a dedicated .tfvars file, can allow a more generalized main.tf to be shared and reused across cloud environments.

Deploying the ECR to AWS

Once all three of these Terraform files are saved together in the same directory (and all of the required edits have been made), running the Terraform commands will create an Amazon ECR named devopsthehardway-ecr.

1
2
3
$ terraform init
$ terraform plan
$ terraform apply  #confirm `yes` when asked

If a different name is desired for the ECR, that can be changed in terraform.tfvars before running the above.

At this point, Terraform has been successfully used to create an Amazon Elastic Container Registry. This can be verified via the AWS CLI or Console:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ aws ecr describe-repositories
{
    "repositories": [
        {
            "repositoryArn": "arn:aws:ecr:****:****:repository/devopsthehardway-ecr",
            "registryId": "****",
            "repositoryName": "devopsthehardway-ecr",
            "repositoryUri": "****",
            "createdAt": "****",
            "imageTagMutability": "MUTABLE",
            "imageScanningConfiguration": {
                "scanOnPush": true
            },
            "encryptionConfiguration": {
                "encryptionType": "AES256"
            }
        }
    ]
}

Also note that Terraform has recorded its required state data to S3, inside the bucket that was specified within the terraform block in main.tf. A new state file appears in that bucket, with a filename of ecr-terraform.tfstate, as declared by the value of key in the terraform block. Terraform will consult this state file if any further Terraform operations are run within this particular module.

That concludes the creation of an Elastic Container Registry via Terraform. As mentioned at the start of this post, the purpose of this ECR is to save the container image for an Uber API that is at the center of a DevOps workflow being built.

In the next blog post, Terraform will be used to create a Kubernetes cluster, where the containerized Uber API will actually run.

This post is licensed under CC BY-NC-SA 4.0 by the author.