Como usar Terraform + Localstack (com Docker)
Tags: terraform, aws, beginners, docker
Published: 2023-03-17 21:03:34

Vou separar esse artigo em 4 partes: _motivação_, _teoria_, _prática_, _conclusão_. 

A intenção é ser um conteúdo leve, introdutório e nada de terno e gravata, que atenda desde de pessoas iniciantes e até mesmo mais experientes.

Estou voltando a escrever agora e pretendo voltar a produzir esse tipo de conteúdo ao longo desse ano. Sugestões e feedback são muito bem vindos!

## Motivação

No fim do ano passado eu estava um pouco incomodado com o fato de saber apenas sobre o Terraform teoricamente... queria aprender e ter a capacidade de usar diariamente de forma mais autonoma, só que eu queria estudar com calma, fazer uma aplicação prática para válidar o conhecimento e etc.

Em Janeiro tirei uns dias de férias para descansar, fui viajar e quando voltei tinha uma semana livre, tempo perfeito para se atualizar e colocar minhas ideias em dia. 

Terraform foi o escolhido da vez!

## Teoria

Como vamos utilizar Terraform, Docker e Localstack vou fazer um pequeno resumo de cada um.

O [Terraform](https://www.terraform.io/) é uma tecnologia [IaaC ](https://learn.microsoft.com/en-us/devops/deliver/what-is-infrastructure-as-code)(Infrastructure as a Code ou Infraestrutura como código, como prefirir.), permite que você provisione sua infraestura em nuvem através de código, numa estrutura bem familiar ao [JSON ](https://www.json.org/json-pt.html)

O [Docker](https://www.docker.com/) é uma plataforma que faz a criação de administração de containers, ou seja, permite que você isole e esteja preparado para fazer deploy do seu ambiente para nuvem.

O [Localstack](https://localstack.cloud/) é uma ferramenta que permite que você desenvolva e teste suas aplicações localmente, ou seja, permite que você utilize e simule tecnologias como SNS, Lambda, SQS, Dynamo e etc no seu ambiente local.

A ideia é basicamente usar o Terraform para provisionar a infraestrutura dentro da minha máquina local, para isso utilizei o Localstack que simula toda minha infraestrutura da AWS dentro dos containeres do Docker.

## Prática

Presumo que o Docker, Terraform e [AWS CLI](https://aws.amazon.com/pt/cli/) estejam configurados e instalados em sua máquina e então podemos iniciar a configuração do Localstack.

Criaremos o arquivo `docker-compose.yml` com a seguinte instrução:

```
version: "3.8"

services:
  localstack:
    image: localstack/localstack:1.3.1
    environment: 
      - AWS_DEFAULT_REGION=sa-east-1
      - AWS_ACCESS_KEY_ID=teste
      - AWS_SECRET_ACCESS_KEY=teste
      - EDGE_PORT=4566
      - DATA_DIR=${DATA_DIR-}
      - HOST_TMP_FOLDER=${TMPDIR:-/tmp/}localstack
      - DOCKER_HOST=unix:///var/run/docker.sock
    ports:
      - '4566-4587:4566-4587'
    volumes:
      - localstack-data:/tmp/localstack
      - "/var/run/docker.sock:/var/run/docker.sock"
    networks:
      - dev_to

volumes:
  localstack-data:
    name: localstack-data

networks:
  dev_to:
    name: dev_to
```
De forma resumida, estamos pedindo para o Docker criar a partir da imagem Localstack(1.3.1) um container. _Detalhe na EDGE_PORT=4566 que falarei mais adiante sobre ela!_

Com o comando `docker compose up -d` o Docker vai criar e subir o container na sua máquina local e prover todos os recursos que o Localstack dispõe.

Rode o comando `docker ps` e veja se obtem um resultado parecido:

![Resultado do Docker PS, container ativo!](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qxzhbyfgs4b1nsjodmhi.png)

Com nosso container no ar e com o Localstack provisionado já podemos partir para o que interessa: Terraform!

No meio do caminho acabei recebendo uma dica de um amigo sobre o [TFLocal](https://github.com/localstack/terraform-local) que foi muito útil, pois ao utilizar o Terraform, precisamos apontar pro ambiente local e o TFLocal foi desenvolvido justamente para o cenário com Localstack.

Para instalar, basta ter o [Python](https://www.python.org/doc/) e rodar `pip install terraform-local`

Com isso, vamos escrever nosso arquivo `main.tf`

```
provider "aws" {
  region                     = "sa-east-1"
  access_key                 = "teste"
  secret_key                 = "teste"
  skip_credentials_validation = true
  skip_requesting_account_id = true
  skip_metadata_api_check    = true
}


resource "aws_dynamodb_table" "basic-dynamodb-table" {
  name           = "GameScores"
  billing_mode   = "PROVISIONED"
  read_capacity  = 20
  write_capacity = 20
  hash_key       = "UserId"
  range_key      = "GameTitle"

  attribute {
    name = "UserId"
    type = "S"
  }

  attribute {
    name = "GameTitle"
    type = "S"
  }

  attribute {
    name = "TopScore"
    type = "N"
  }

  ttl {
    attribute_name = "TimeToExist"
    enabled        = false
  }

  global_secondary_index {
    name               = "GameTitleIndex"
    hash_key           = "GameTitle"
    range_key          = "TopScore"
    write_capacity     = 10
    read_capacity      = 10
    projection_type    = "INCLUDE"
    non_key_attributes = ["UserId"]
  }

  tags = {
    Name        = "dynamodb-table-1"
    Environment = "production"
  }
}
```
O arquivo `main.tf` é responsável por entender qual será o Provider(AWS, GCP, Azure) a ser utilizado e quais serviços serão criados, no exemplo acima eu quis utilizar o mesmo [exemplo](provider) no site do Terraform que é criar uma tabela no DynamoDB.

Com o arquivo finalizado, podemos iniciar os comandos que vão realmente criar tudo lá dentro para nós, então abra seu terminal e digite: `tflocal init`

O comando `tflocal init` faz exatamente o mesmo que o `terraform init` faz, inicia a configuração do terraform de acordo com o que temos de instrução no `main.tf`

Em seguida, `tflocal plan`. Que por sua vez, vai carregar as suas configurações e te mostrar o que tem para ser feito como planejado.

E por final, `tflocal apply -auto-approve`, esse comando Apply realmente vai fazer a criação (nesse caso DynamoDB) dos serviços que foram planejados e a flag `-auto-approve` faz com que não haja a necessidade de confirmar com um "yes" na linha de comando.

Pronto, temos tudo criado e a mensagem que apareceu no terminal deve ter sido algo assim:

![Resultado do TFlocal apply](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7tt3ai3nrc9y1p73vvyp.png)

Para ver se sua table criou, basta rodar `aws dynamodb list-tables --endpoint-url http://localhost:4566`:

![Lista de tabelas via AWS Cli](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/76hk72o1h7h86z571sqy.png)

A partir daqui, pode inserir registros na tabela e até mesmo usar o [NoSQL Workbench](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/workbench.html) para ter uma GUI de visualização.



Lembra que eu falei sobre o a EDGE_PORT=4566 ?

Veja que eu utilizei ela na minha consulta via CLI, ou seja todos os comandos que eu for fazer de consulta ou apontamentos via código localmente eu devo fazer na porta 4566, pois o localstack está roteando internamente e inteligentemente para os serviços solicitados. Se eu fosse consultar um SQS ou SNS eu apontaria para essa mesma porta 4566 e etc. Obviamente é algo configurável, pode ser utilizado as portas que consta nas docs do Localstack mas eu acho que é algo facilita nossa vida em meio tantas POCs (_Prove of concept_) que fazemos por ai. 

## Conclusão

Na minha opnião, desenvolver e testar local é melhor forma de você desenvolver antes de subir para um ambiente de DEV. Por ser um ambiente controlado as ferramentas como Docker, Localstack, Terraform fazem com que tenhamos um ganho absurdo de produtividade e testabilidade.

Além de conseguir testar muitas features sem gastar $ é uma ótima forma de válidar e testar as coisas!

Eu recomendo fortemente combinar essas ferramentas para o uso no dia a dia, fazendo com que nossas entregas além de validadas sejam mais consistentes.

_O amigo que mencionei é o [Renato Rodrigues](https://www.linkedin.com/in/renato-r/), ele que deu a dica de usar o tflocal para iniciar meus estudos com o Terraform usando Localstack. Fica aqui meu agradecimento!_

Links que utilizei de inspiração:

- https://www.docker.com/blog/develop-your-cloud-app-locally-with-the-localstack-extension/
- https://www.linkedin.com/pulse/develop-test-aws-apps-free-using-localstack-adtech-corp/?trk=organization-update-content_share-article