Construindo um Backend GraphQL sem uma Linha de Código
Tags: docker, mongodb, graphql, opensource
Published: 2020-04-23 14:57:22

_Photo por Kevin Ku no Unsplash_

Criar um backend simples não é uma tarefa tão simples assim... Ainda mais se quisermos que ele use tecnologias mais avançadas como o [GraphQL](https://azure.microsoft.com/resources/videos/build-2019-build-scalable-apis-using-graphql-and-serverless/?WT.mc_id=blog-devto-ludossan). 

Recentemente me encontrei em uma situação ao mesmo tempo simples, porém complexa. Eu estou precisando refazer o [meu site pessoal](https://lsantos.dev), que hoje é apenas uma página template do GitHub websites, para meu novo site eu tenho certeza que gostaria de ter um arquivo de posts e atividades que participei, ou seja, quero ter uma lista de tudo que fiz e produzi para que possa colocar como um "portfolio" e também um guia para quem precisar acessar o site.

Como já estou planejando este desenvolvimento há um tempo, me inspirei no site do [Erick Wendel](http://erickwendel.com/) para ter algumas ideias e decidi ter um backend em [GraphQL](https://channel9.msdn.com/Series/GraphQL/Creating-a-GraphQL-Server-Part-1-Building-a-GraphQL-Server-with-Apollo-GraphQL?WT.mc_id=blog-devto-ludossan) por alguns motivos bem simples:

- Não vou precisar usar todos os campos no site, portanto quero poder filtrar o que eu vou trazer da API
- Quero ter a capacidade de descrever todo o Schema da minha API em um arquivo 

Além disso, quero manter o site simples, não estou querendo nada super complicado ou evoluído, quanto menos tempo e menos código eu puder desprender nele, melhor!

# A busca de ferramentas

Inicialmente me senti tentado a seguir para o [Hasura](https://azure.microsoft.com/updates/instantly-provision-graphql-on-azure-with-hasura-and-azure-database-for-postgresql/?WT.mc_id=blog-devto-ludossan), uma ferramenta excelente que provisiona backends em GraphQL instantaneamente, porém o problema é que o único banco suportado é o PostgreSQL, e eu realmente não queria utilizar um banco relacional para poder ter mais flexibilidade na hora de planejar o meu Schema.

Então, depois de alguma busca, acabei encontrando o [Mongoke](https://github.com/remorses/mongoke), uma ferramenta open-source que me permite fazer mais ou menos a mesma coisa, porém com o [MongoDB](https://azure.microsoft.com/blog/microsoft-azure-tutorial-how-to-integrate-azure-functions-with-mongodb/?WT.mc_id=blog-devto-ludossan).

# Preparação

Para esse backend eu precisava de pelo menos um banco de dados já pronto. Então utilizei o [Free Tier do MongoDB Atlas](https://azure.microsoft.com/blog/microsoft-azure-tutorial-how-to-integrate-azure-functions-with-mongodb/?WT.mc_id=blog-devto-ludossan) na Azure para poder ter um banco robusto sem precisar pagar nada.

Fora isso, todo o resto eu já tinha pronto:

- Website no Github Pages ([link](https://github.com/khaosdoctor/khaosdoctor.github.io))

{% github khaosdoctor/khaosdoctor.github.io %}

- Dados no banco de dados
- [Mongoke](https://github.com/remorses/mongoke)
- [Docker]() para poder testar tudo
- [Conta na Azure](https://azure.microsoft.com/?WT.mc_id=blog-devto-ludossan) para hospedar isso tudo

# Desenvolvimento

O Mongoke funciona da seguinte maneira:

- Criamos um arquivo `mongoke.yml` com a descrição do nosso Schema GraphQL
- Ao executar o Mongoke passando a string de conexão e o caminho do arquivo – ou a URL – teremos a criação de um webserver que servirá nossa API com queries prontas baseadas em nosso schema

Simples não? Vamos colocar em prática!

## Criando o arquivo YML

A primeira coisa que precisamos fazer é criar o nosso arquivo de Schema do GraphQL. No meu banco de dados tenho uma collection chamada `activities` e ela possui alguns campos que vamos descrever no Schema do Mongoke:

```yml
# https://github.com/khaosdoctor/site-backend/raw/master/mongoke.yml
schema: |
  enum ActivityType {
    talk
    article
    foss
    other
    host
    book
    event
    podcast
    video
  }

  type Activity {
    _id: ObjectId
    id: Int
    date: Date
    title: String
    description: String
    type: ActivityType
    categories: String
    videos: String
    url: String
  }

types:
  Activity:
    collection: activities
```

Primeiramente criamos um `enum` para descrever todos os tipos de atividades que tenho em meu banco de dados, isto vai ser essencial para podermos filtrar e validar os inputs do site quando ele estiver no ar.

Em seguida criamos um tipo `Activity` que será o registro propriamente dito. Este registro possui os campos descritos no schema anterior. Agora você deve estar se perguntando porque criamos apenas o registro único, não deveríamos ter criado um registro do tipo "lista de atividades"? Algo assim:

```graphql
type ActivityList {
  data: [Activity]
}
```

É ai que entra a mágica! O Mongoke automaticamente vai criar para nós um tipo `<type>Nodes` – no nosso caso, `ActivityNodes` – que segue a modelagem de nós e arestas tão comum do [GraphQL](https://channel9.msdn.com/Series/GraphQL/Creating-a-GraphQL-Server-Part-1-Building-a-GraphQL-Server-with-Apollo-GraphQL?WT.mc_id=blog-devto-ludossan), desta forma podemos ter a lista de atividades automaticamente.

Depois de definir o `type`, vamos precisar dizer que ele é relativo a uma collection no nosso banco, e é para isto que a seção `types` serve. Ela está basicamente dizendo que o tipo `Activity` está relacionado à collection `activities` no meu [MongoDB](https://azure.microsoft.com/blog/microsoft-azure-tutorial-how-to-integrate-azure-functions-with-mongodb/?WT.mc_id=blog-devto-ludossan).

## Testando localmente

O Mongoke é completamente baseado em Docker, portanto vamos criar um arquivo `docker-compose.yml` para poder testar nosso setup localmente antes de precisar fazer o deploy!

```yml
# https://github.com/khaosdoctor/site-backend/raw/master/docker-compose.yml
version: "3"

services:
  backend:
    ports:
      - 80:80
    image: mongoke/mongoke
    environment:
      DB_URL: mongodb://mongo/contributions
      PORT: "80"
    volumes:
      - ./mongoke.yml:/conf.yml
  mongo:
    image: mvertes/alpine-mongo
    ports:
      - 27017:27017
```

Veja que estamos subindo uma instancia do mongo localmente para testar e estamos usando as variáveis `DB_URL` e criando um volume local na raiz da imagem `mongoke/mongoke` para passar o nosso arquivo de schema. Estamos também liberando a porta 80 para acessar o nosso ambiente de testes GraphiQL:

![](https://dev-to-uploads.s3.amazonaws.com/i/qydo0ds9cygdbobsw24u.png)

> **Dica:** Sempre use imagens `alpine` como o `alpine-mongo` porque elas tem um tamanho consideravelmente menor do que imagens normais

## Colocando no ar

Para colocar o backend no ar eu também não queria nenhum tipo de trabalho extra, por isso eu utilizei as [Azure Container Instances](https://azure.microsoft.com/services/container-instances/?WT.mc_id=blog-devto-ludossan), que permitem que eu crie um container e rode ele de forma [Serverless](https://azure.microsoft.com/solutions/serverless/?WT.mc_id=blog-devto-ludossan), ou seja, não tenho que me preocupar com escalabilidade e nem com máquinas, é só executar o meu container diretamente na nuvem!

E tudo fica muito mais simples porque já temos uma imagem pronta do `mongoke/mongoke`, ou seja, não vamos precisar fazer absolutamente nada de novo, só usar o que já está providenciado!

Para começar, vamos criar um novo resource group usando o [Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest&WT.mc_id=blog-devto-ludossan).

> Se você ainda não instalou e configurou seu CLI da Azure veja [este link](https://docs.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest&WT.mc_id=blog-devto-ludossan)

Para fazer isso vamos simplesmente executar o seguinte comando:

```sh
az group create --name personal-website --location brazilsouth
```

> **Dica:** Você pode escolher outras regiões para colocar o seu grupo! Escolhi a região brasileira porque está geograficamente mais próxima da gente.

Depois disso, vamos criar a nossa instância do [ACI](https://azure.microsoft.com/services/container-instances/?WT.mc_id=blog-devto-ludossan) através do comando:

```sh
az container create \
--resource-group personal-website \
--name personal-website-backend \
--image mongoke/mongoke \
--location brazilsouth \
--dns-name-label lsantos-api \
--ports 80 \
--environment-variables \
MONGOKE_CONFIG_URL="https://lsantos.me/site-backend/mongoke.yml" \
DB_URL="<sua URL de conexão com o Mongo Atlas>" \
DISABLE_GRAPHIQL="true"
```

Perceba o seguinte. Como estamos executando nosso container de forma remote, eu não gostaria de ter que criar e mandar um arquivo para dentro do container, felizmente o Mongoke tem a possibilidade de colocarmos uma URL para o nosso arquivo Schema lá no github! Então podemos hospedar o nosso arquivo no Github Pages ou então pegar o endereço do arquivo _raw_ e colocar na variável `MONGOKE_CONFIG_URL`.

Além disso também estou desativando o ambiente GraphiQL porque não queremos o ambiente de testes e sandbox funcionando em nosso ambiente de produção, não é mesmo?

Uma vez que executamos o comando, esperamos alguns instantes e poderemos ver nosso container criado no painel da Azure:

![](https://dev-to-uploads.s3.amazonaws.com/i/q1l8nob49ih8jo3svvhs.png)

E poderemos acessar a instância, e até mesmo se conectar a ela e buscar seus logs através da aba `Containers`:

![](https://dev-to-uploads.s3.amazonaws.com/i/frxpm9fkofqwq5yru9qc.png)

Podemos então acessar o domínio FQDN gerado pela Azure para poder ver nosso backend completamente no ar!

# Conclusão e próximos passos

Este artigo foi baseado na Live que fiz com o Igor Halfeld sobre como podemos criar um backend em GraphQL, então se você quiser assistir como fazemos o desenvolvimento completo é só ver o vídeo abaixo!

{% youtube Qt0bzxdV_Jg %}

O repositório deste backend:

{% github khaosdoctor/site-backend %}

Para os próximos passos podemos aplicar uma série de automações, por exemplo:

- Deploy automático via Github Actions diretamente para o [ACI](https://azure.microsoft.com/services/container-instances/?WT.mc_id=blog-devto-ludossan)
- Inserir um novo artigo no banco sempre que eu criar um novo artigo aqui no Dev.to
- Inclusão do nosso FQDN direto em meu sub-domínio através do CloudFlare

E muitas outras ideias! O objetivo deste artigo é mostrar que não é necessário pagar horrores ou então ter um grande trabalho para criar um backend completo utilizando tecnologias de ponta como o GraphQL, você pode [criar uma conta gratuitamente](https://azure.microsoft.com/services/container-instances/?WT.mc_id=blog-devto-ludossan) na Azure e usufruir dos créditos iniciais para fazer seus testes e até mesmo criar seu backend completo sem precisar pagar um centavo!

Não deixe de acompanhar mais do meu conteúdo no [meu blog](https://blog.lsantos.dev/?utm_source=devto&utm_medium=article&utm_campaign=mongoke) e se [inscreva na newsletter](https://blog.lsantos.dev/signup?utm_source=devto&utm_medium=article&utm_campaign=mongoke) para receber notícias semanais!