Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Junte-se a nós no Amazon Web Services re:Invent 2024! Saiba como usar o MongoDB para casos de uso de AI .
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Idiomaschevron-right
Gochevron-right

Entre em alta: usando Docker + Go com MongoDB

Nic Raboy, Anaiya Raisinghani9 min read • Published Aug 06, 2021 • Updated Feb 27, 2023
DockerGo
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Na comunidade de desenvolvedores, garantir que seus projetos sejam executados com precisão, independentemente do ambiente, pode ser difícil. Quer esteja tentando recriar uma demonstração a partir de um tutorial on-line ou trabalhando em uma revisão de código, ouvir as palavras "Well, it works on my machine… " pode ser muito desconcertante. Em vez de passar horas depurando, queremos apresentar a você uma plataforma que mudará sua experiência de desenvolvedor: Docker.
O Docker é uma ótima ferramenta para aprender, pois oferece aos desenvolvedores a capacidade de seus aplicativos serem usados facilmente entre ambientes e é eficiente em termos de recursos em comparação com as máquinas virtuais. Este tutorial irá orientá-lo sobre como navegar no Docker, além de como integrar oGo na plataforma. Usaremos esse projeto para nos conectar ao nosso MongoDB Atlas Search Cluster criado anteriormente para usar Sinônimos no Atlas Search. Fique atento para uma leitura bem-sucedida sobre como aprender todos os itens acima e, ao mesmo tempo, expandir seu conhecimento de gíries da Ger-Z com nosso cluster de sinônimos. Fique popular!

Os pré-requisitos

Há alguns requisitos que devem ser atendidos para ter sucesso com este tutorial.
  • Cluster MongoDB Atlas AM0 ou superior
  • Área de trabalho do Docker
Para usar o MongoDB com o driver Golang, você só precisa de um cluster M0 gratuito. Para criar esse cluster, siga as instruções listadas na documentação do MongoDB. No entanto, vamos fazer muitas referências a um tutorial anterior em que usamos o Atlas Search com sinônimos personalizados.
Como este é um tutorial Docker , você precisará Docker Desktop. Na verdade, você não precisa ter o Go configurado em sua máquina host porque o Docker pode lidar com isso para nós à medida que avançamos no tutorial.

Criando uma API Go com o driver Golang do MongoDB

Como mencionado anteriormente, você não precisa do Go instalado e configurado em seu computador host para ser bem-sucedido. No entanto, não faria mal usá-lo caso você queira testar as coisas antes de criar uma imagem do Docker.
Em seu computador, crie um novo diretório de projeto e, dentro desse diretório de projeto, crie um diretóriosrc com os seguintes arquivos:
  • go.mod
  • main.go
O arquivogo.mod é nosso arquivo de gerenciamento de dependência para módulos Go. Ele pode ser facilmente criado manualmente ou usando o seguinte comando:
1go mod init
O arquivo principal.go é onde manteremos todo o código do nosso projeto.
Começando com o arquivogo.mod, adicione as seguintes linhas:
1module github.com/mongodb-developer/docker-golang-example
2go 1.15
3require go.mongodb.org/mongo-driver v1.7.0
4require github.com/gorilla/mux v1.8.0
Essenciais, estamos definindo qual versão do Go usar e os módulos que queremos usar. Para este projeto, usaremos o driver MongoDB Go, bem como oGorilla Web Toolkit.
Isso nos leva à construção de nossa API simples.
Dentro do arquivo main.go, adicione o seguinte código:
1package main
2
3import (
4 "context"
5 "encoding/json"
6 "fmt"
7 "net/http"
8 "os"
9 "time"
10
11 "github.com/gorilla/mux"
12 "go.mongodb.org/mongo-driver/bson"
13 "go.mongodb.org/mongo-driver/mongo"
14 "go.mongodb.org/mongo-driver/mongo/options"
15)
16
17var client *mongo.Client
18var collection *mongo.Collection
19
20type Tweet struct {
21 ID int64 `json:"_id,omitempty" bson:"_id,omitempty"`
22 FullText string `json:"full_text,omitempty" bson:"full_text,omitempty"`
23 User struct {
24 ScreenName string `json:"screen_name" bson:"screen_name"`
25 } `json:"user,omitempty" bson:"user,omitempty"`
26}
27
28func GetTweetsEndpoint(response http.ResponseWriter, request *http.Request) {}
29func SearchTweetsEndpoint(response http.ResponseWriter, request *http.Request) {}
30
31func main() {
32 fmt.Println("Starting the application...")
33 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
34 defer cancel()
35 client, err := mongo.Connect(ctx, options.Client().ApplyURI(os.Getenv("MONGODB_URI")))
36 defer func() {
37 if err = client.Disconnect(ctx); err != nil {
38 panic(err)
39 }
40 }()
41collection = client.Database("synonyms").Collection("tweets")
42 router := mux.NewRouter()
43 router.HandleFunc("/tweets", GetTweetsEndpoint).Methods("GET")
44 router.HandleFunc("/search", SearchTweetsEndpoint).Methods("GET")
45 http.ListenAndServe(":12345", router)
46}
Há mais no código, mas, antes de vermos o restante, vamos começar a decompor o que temos acima para dar sentido a ele.
Você provavelmente notará nossa estrutura de dadosTweets:
1type Tweet struct {
2 ID int64 `json:"_id,omitempty" bson:"_id,omitempty"`
3 FullText string `json:"full_text,omitempty" bson:"full_text,omitempty"`
4 User struct {
5 ScreenName string `json:"screen_name" bson:"screen_name"`
6 } `json:"user,omitempty" bson:"user,omitempty"`
7}
No início do tutorial, mencionamos que este exemplo é fortemente influenciada por um tutorial anterior que usou dados do Twitter. É altamente recomendável que você dê uma olhada nele. Essa estrutura de dados tem alguns dos campos que representam um tuíte que raspamos do Twitter. Não mapeamos todos os campos porque isso não era necessário para este exemplo.
Em seguida, você notará o seguinte:
1func GetTweetsEndpoint(response http.ResponseWriter, request *http.Request) {}
2func SearchTweetsEndpoint(response http.ResponseWriter, request *http.Request) {}
Essas serão as funções que manterão nossa lógica de endpoint da API. Vamos ignorá-los por enquanto e nos concentrarmos em entender a lógica de conexão e configuração.
Até o momento, a maior parte do que nos interessa está acontecendo na funçãomain.
A primeira coisa que estamos fazendo é conectar ao MongoDB:
1ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
2defer cancel()
3client, err := mongo.Connect(ctx, options.Client().ApplyURI(os.Getenv("MONGODB_URI")))
4defer func() {
5 if err = client.Disconnect(ctx); err != nil {
6 panic(err)
7 }
8}()
9collection = client.Database("synonyms").Collection("tweets")
Você provavelmente notará a MONGODB_URI variável de ambiente no código acima. Não é uma boa ideia codificar a MongoDB de conexão do string no aplicativo. Isso nos impede de sermos flexíveis e pode ser um risco à segurança. Em vez disso, estamos usando variáveis de ambiente que passaremos com o Docker quando implantarmos nossos contêineres.
Você pode acessar o painel do MongoDB Atlas para sua string de URI .
O banco de dados que planejamos usar é synonyms e planejamos usar a collectiontweets, sobre a qual mencionamos no tutorial anterior.
Depois de nos conectar ao MongoDB, nos concentramos em configurar o Gorilla Web Toolkit:
1router := mux.NewRouter()
2router.HandleFunc("/tweets", GetTweetsEndpoint).Methods("GET")
3router.HandleFunc("/search", SearchTweetsEndpoint).Methods("GET")
4http.ListenAndServe(":12345", router)
Neste código, estamos definindo qual caminho do endpoint deve rotear para qual função. As funções estão definidas, mas ainda não adicionamos nenhuma lógica a elas. O próprio aplicativo servirá na porta 12345.
A partir de agora, o aplicativo possui as informações básicas de conexão e configuração necessárias. Vamos voltar a cada uma dessas funções de endpoint.
Começaremos com o GetTweetsEndpoint porque ele funcionará bem com um cluster M0 :
1func GetTweetsEndpoint(response http.ResponseWriter, request *http.Request) {
2 response.Header().Set("content-type", "application/json")
3 var tweets []Tweet
4 ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
5 cursor, err := collection.Find(ctx, bson.M{})
6 if err != nil {
7 response.WriteHeader(http.StatusInternalServerError)
8 response.Write([]byte(`{ "message": "` + err.Error() + `" }`))
9 return
10 }
11 if err = cursor.All(ctx, &tweets); err != nil {
12 response.WriteHeader(http.StatusInternalServerError)
13 response.Write([]byte(`{ "message": "` + err.Error() + `" }`))
14 return
15 }
16 json.NewEncoder(response).Encode(tweets)
17}
No código acima, estamos dizendo que queremos usar a operaçãoFind em nossa coleção para todos os documentos nessa coleção, portanto, o objeto de filtro vazio.
Se não houver erros, poderemos obter todos os resultados do nosso cursor, carregá-los em uma fatiaTweete, em seguida, codificar JSON nessa fatia para enviar ao cliente. O cliente receberá dados JSON como resultado.
Agora podemos examinar a função de endpoint mais interessante.
1func SearchTweetsEndpoint(response http.ResponseWriter, request *http.Request) {
2 response.Header().Set("content-type", "application/json")
3 queryParams := request.URL.Query()
4 var tweets []Tweet
5 ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
6 searchStage := bson.D{
7 {"$search", bson.D{
8 {"index", "synsearch"},
9 {"text", bson.D{
10 {"query", queryParams.Get("q")},
11 {"path", "full_text"},
12 {"synonyms", "slang"},
13 }},
14 }},
15 }
16 cursor, err := collection.Aggregate(ctx, mongo.Pipeline{searchStage})
17 if err != nil {
18 response.WriteHeader(http.StatusInternalServerError)
19 response.Write([]byte(`{ "message": "` + err.Error() + `" }`))
20 return
21 }
22 if err = cursor.All(ctx, &tweets); err != nil {
23 response.WriteHeader(http.StatusInternalServerError)
24 response.Write([]byte(`{ "message": "` + err.Error() + `" }`))
25 return
26 }
27 json.NewEncoder(response).Encode(tweets)
28}
A ideia por trás da função acima é que queremos usar um aggregation pipeline para o Atlas Search. Ela usa as informações de sinônimo que descrevemos no tutorial anterior.
A primeira coisa importante a ser observada no código acima é a seguinte:
1​​queryParams := request.URL.Query()
Estamos obtendo os parâmetros de query passados com a solicitação HTTP. Estamos esperando que um parâmetroq exista com a query de pesquisa a ser usada.
Para manter as coisas simples, usamos um único estágio para o pipeline de agregação do MongoDB:
1searchStage := bson.D{
2 {"$search", bson.D{
3 {"index", "synsearch"},
4 {"text", bson.D{
5 {"query", queryParams.Get("q")},
6 {"path", "full_text"},
7 {"synonyms", "slang"},
8 }},
9 }},
10}
Neste estágio, estamos fazendo uma pesquisa de texto com um índice específico e um conjunto específico de sinônimos. A query que usamos para nossa pesquisa de texto vem do parâmetro query de nossa solicitação HTTP.
Supondo que tudo correu bem, podemos carregar todos os resultados do cursor em uma fatiaTweet, codificá-la em JSON e retorná-la ao cliente que a solicitou.
Se você tiver o Go instalado e configurado em seu computador, vá em frente e tente executar esse aplicativo. Só não se esqueça de adicionar o MONGODB_URI às suas variáveis de ambiente antes.
Se você quiser saber mais sobre o desenvolvimento de API com o Kit de Ferramentas da Web do Gorilla e o MongoDB, confira este tutorial sobre o assunto.

Configuração de uma imagem Docker para Go com MongoDB

Vamos começar com o Docker! Se for uma plataforma que você nunca usou antes, pode parecer um pouco assustador no começo, mas deixe-nos guiá-lo passo a passo. Mostraremos como baixar o Docker e começar a configurar seu primeiro Dockerfile para se conectar ao nosso cluster Atlas de Sinônimos Gen-Z.
As primeiras coisas primeiro. Vamos baixar o Docker. Isso pode ser feito por meio do sitedeles em apenas alguns minutos.
Depois de colocar isso em funcionamento, é hora de criar seu primeiro Dockerfile.
Na raiz da sua pasta de projeto, crie um novo arquivo Dockerfile com o seguinte conteúdo:
1#get a base image
2FROM golang:1.16-buster
3
4MAINTAINER anaiya raisinghani <anaiya.raisinghani@mongodb.com>
5
6WORKDIR /go/src/app
7COPY ./src .
8
9RUN go get -d -v
10RUN go build -v
11
12CMD ["./docker-golang-example"]
Muitos Dockerfiles são compostos desse formato, e muitos deles são altamente personalizáveis e podem ser editados para atender às necessidades do seu projeto.
O primeiro passo é pegar uma imagem base que você vai usar para construir sua nova imagem. Você pode pensar em usar Dockerfiles como camadas de um bolo. Há uma variedade de imagens de base diferentes por exemplo, ou você pode usar FROM scratch para começar a partir de uma imagem totalmente em branco. Como esse projeto está usando a linguagem de programação Go, optamos por começar da imagem basegolang e adicionar a marcação 1.16 para representar a versão do Go que planejamos usar. Sempre que você incluir uma marcação ao lado da imagem base, certifique-se de configurá-la com dois pontos no meio, assim: golang:1.16. Para saber mais sobre qual tag beneficiará mais seu projeto, consulte a documentação do Docker sobre o assunto.
Este site contém muitas tags diferentes que podem ser usadas em uma imagem base do Golang. As tags são importantes porque contêm informações muito valiosas sobre a imagem base que você está usando, como versões de software, variações do sistema operacional etc.
Vamos contar o resto do que vai acontecer neste Dockerfile!
É opcional incluir um MAINTAINER para sua imagem, mas é uma boa prática para que as pessoas que visualizam seu Dockerfile possam saber quem o criou. Não é necessário, mas é útil incluir seu nome completo e seu endereço de e-mail no arquivo.
É crucial incluir o comando em seu Dockerfile, pois {WORKDIR /go/src/appWORKDIR especifica em qual diretório de trabalho você está. Todos os comandos a seguir serão executados em qualquer diretório que você escolher, portanto, certifique-se de estar ciente de em qual diretório você está atualmente em.
O comandoCOPY ./src . permite a você copiar quaisquer arquivos que você desejar do local especificado na máquina host para a imagem Docker.
Agora, podemos usar o comandoRUN para definir exatamente o que queremos que aconteça no momento da construção da imagem antes da implantação como container. O primeiro comando que temos é RUN go get -d -v, que baixará todas as dependências do Go listadas no arquivogo.mod que foi copiado na imagem.
Nosso segundo comando RUNéRUN go build -v, que construirá nosso projeto em um arquivo binário executável.
A última etapa deste Dockerfile é usar um comandoCMD , CMD [“./docker-golang-example”]. Este comando definirá o que é executado quando o container é implantado e não quando a imagem é construída. Essenciais, estamos dizendo que queremos que o aplicativo Go construído seja executado quando o contêiner for implantado.
Depois de configurar o Dockerfile, você poderá criar e executar seu projeto usando todo o link da URI do MongoDB:
Para construir a imagem Docker e implantar o contêiner, execute o seguinte a partir da linha de comando:
1docker build -t docker-syn-image .
2docker run -d -p 12345:12345 -e “MONGODB_URI=YOUR_URI_HERE” docker-syn-image
Siga estas instruções permitirá que você execute o projeto e acessá-lo a partir de http://localhost:12345. Mas! É tão entediante. E se nós lhe dissermos que há uma maneira mais fácil de executar seu aplicativo sem ter que escrever todo o link URI? Há! Só é preciso uma etapa a mais: configurar um arquivo Docker Compose.

Configurar um arquivo de composição do Docker para simplificar implantações

Um arquivo Docker Compose é uma pequena etapa legal para executar todos os seus arquivos e dependências do container por meio de um comando simples: docker compose up.
Para configurar este arquivo, você precisa estabelecer um arquivo de configuração YAML primeiro. Faça isso criando um novo arquivo na raiz da pasta do projeto, nomeando-o docker-composee adicionando .yml no final. Você pode nomear outra coisa se quiser, mas esta é a mais fácil, pois ao executar o comandodocker compose up, você não precisará especificar um nome de arquivo. Quando estiver na pasta do projeto, siga as etapas abaixo.
É assim que seu arquivo Docker Compose ficará depois de configurar tudo:
1version: "3.9"
2services:
3 web:
4 build: .
5 ports:
6 - "12345:12345"
7 environment:
8 MONGODB_URI: your_URI_here
Vamos percorrer isso!
Primeiras coisas primeiro. Determine qual versão do esquema você deseja executar. Você deve estar usando a versão mais recente e pode descobrir isso na documentação do Docker.
Em seguida, defina quais serviços, também conhecidos como container, você deseja executar em seu projeto. Incluímos web desde que estamos anexando ao nosso Atlas Search. O nome não é importante e atua mais como um identificador desse serviço específico. Em seguida, especifique que você está criando seu aplicativo e insira as informaçõesports no local correto. Para a próxima etapa, podemos configurar nosso environment como nosso MongoDB URI e pronto!
Agora, execute o comando docker compose up e veja a mágica acontecer. Seu container deverá ser compilado e executado, e você poderá se conectar à sua porta e ver todos os tweets!

Conclusão

Este tutorial agora deixou você preparado com o conhecimento necessário para criar uma API Go com o driver Golang do MongoDB, criar um Dockerfile, criar um arquivo Docker Compose e conectar seu container recém-construído a um MongoDB Atlas Cluster.
O uso dessas novas plataformas permitirá que você leve seus projetos a um nível totalmente novo.
Se você quiser dar uma olhada no código usado em nosso projeto, pode acessá-lo no GitHub.
Usando Docker ou Go, mas tem alguma dúvida? Confira os MongoDB Community!

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Início rápido

Reagindo às mudanças do banco de dados com o MongoDB Change Streams e Go


Feb 03, 2023 | 5 min read
Tutorial

Criptografia no nível do campo do lado do cliente (CSFLE) no MongoDB com Golang


Feb 03, 2023 | 15 min read
exemplo de código

Filme: exemplo de aplicativo de microsserviços Go


Sep 11, 2024 | 0 min read
Tutorial

Servidores HTTP persistindo dados no MongoDB


Sep 04, 2024 | 5 min read
Sumário