Implantando o Go + React to Heroku usando o Docker, Parte 1

Dean Baker Segue 9 de maio · 7 min ler Foto de Guillaume Bolduc no Unsplash

Há um monte de how-tos e tutoriais em fazer mais do que estou prestes a escrever, mas nada que realmente puxou tudo junto para mim. Eu queria algo que eu pudesse jogar para ajudar a aprender Go, mas também ter a capacidade de empurrá-lo para algum lugar ao vivo – Heroku é uma ótima escolha para um projeto de estimação como este. Esta é a parte 1 de uma série de 3 partes:

  • Parte 1— implantando um servidor e cliente simples (este guia)
  • Parte 2 – adicionando um banco de dados
  • Parte 3 – adicionando autenticação do usuário

Você pode ver o código completo aqui: github

O que você vai construir

Vamos construir um cliente no React.js e no servidor Go que podemos implantar no Heroku usando o Docker. Também teremos um ambiente local decente para o desenvolvimento.

O que você precisará

Você precisará das seguintes ferramentas para começar:

Começando

Vamos criar um diretório raiz que irá manter diretórios separados de cliente e servidor , a raiz também conterá o Dockerfile (este é um arquivo, não um diretório) usado para construir o produto final.

 projeto 
|
| -cliente /
| -server /
| -Dockerfile

O servidor Go

Primeiras coisas primeiro, vamos criar uma API para o front-end consumir. No diretório do servidor, crie um novo módulo Go e crie um arquivo initial.go inicial.

 $ go mod init github.com/deandemo/react-go-heroku 

criar arquivo main.go

Aqui estamos usando o gin , um framework web popular para ajudar no roteamento, que será útil um pouco mais tarde.

Se você gostaria de ver como o aplicativo se comporta:

 $ go run main.go # Você terá que rodar isso em um novo terminal 
$ curl localhost: 8080 / api / ping

Começando com o React

Isenção de responsabilidade: o código gerado aqui provavelmente mudará conforme React e create-react-app evoluírem.

Vamos alavancar a ferramenta create-react-app do facebook para criar um front-end rapidamente, então entre no diretório raiz do seu projeto e execute:

 Cliente $ npx create-react-app 

Como estamos criando um mono-repo, por favor, apague o repositório git ( .git) no diretório / client recém-criado.

PingComponent

Vamos criar um componente que possa atingir um servidor; nesse caso, usaremos axios , uma estrutura popular para ajudar a fazer chamadas de API. Simplesmente coloque o arquivo abaixo no diretório src do aplicativo reagir, chame este arquivo PingComponent.js

Antes que este código seja válido, devemos importar o pacote axios:

 # A partir da execução do diretório / client / 
$ npm instalar axios --save

PingComponent.js

Observe na linha 13 que estamos chamando um nó de extremidade em api/ping , se inicializarmos o aplicativo reagir usando o npm start isso equivaleria a pressionar http: // localhost: 3000 / api / ping – Mais sobre isso mais tarde, enquanto ligamos nosso ambiente local.

App.js

Agora podemos conectar nosso componente ping da maneira mais simples possível. No arquivo App.js que foi criado usando a ferramenta create-react-app, adicione o seguinte:

App.js

Observe as linhas 4 e 23 onde importamos e usamos nosso PingComponent.

Proxy para desenvolvimento local

Se fôssemos iniciar ambas as bases de código, teríamos um cliente rodando na porta 3000 e um servidor na porta 8080 . Isso não é ideal para desenvolvimento, portanto, podemos configurar o cliente para fazer proxy de todas as solicitações desconhecidas para o servidor da API, modificando nosso pacote.json por adicionando um campo de proxy :

 "proxy": " http: // localhost: 8080 " 

Correndo localmente

Ok, ótimo, agora temos um servidor e um cliente que tem a capacidade de fazer solicitações de proxy para ele. Vamos dar uma chance!

Abra um terminal e inicie o servidor primeiro (se ainda não estiver em execução), em seguida inicie o cliente usando o npm start . Isso deve abrir automaticamente o aplicativo em um navegador e você deve ver o sucesso!

 # Do diretório / server 
$ go run main.go
# Do diretório / client
$ npm start

Docker

Agora nós temos um ambiente de desenvolvimento, vamos colocar essa coisa para "cutucar".

Dockerfile

Primeiro, criaremos um contêiner do Docker que hospedará nosso código de produção. Esse será o programa executável Go, bem como a versão de produção do nosso aplicativo React. Para isso, podemos usar uma construção do docker de vários estágios , colar esse texto em um arquivo chamado Dockerfile que vive na raiz do nosso projeto.

 # Construa a Go API 
DE golang: o mais recente construtor AS
ADICIONAR . /aplicativo
WORKDIR / app / server
RUN go mod download
RUN CGO_ENABLED = 0 GOOS = linux GOARCH = amd64 ir compilar -ldflags "-w" -a -o / main.
# Construa o aplicativo React
Nó: alpine AS node_builder
COPY --from = construtor / aplicativo / cliente ./
RUN npm install
RUN npm run build
# Construção final do estágio, este será o container
# que vamos implantar para produção
FROM alpine: latest
RUN apk --no-cache adicionar ca-certificados
COPY --from = construtor / main ./
COPY --from = node_builder / build ./web
RUN chmod + x ./main
EXPOSE 8080
CMD ./main

Como você pode ver aqui, estamos criando três contêineres docker, o primeiro a criar a API Go, o segundo para o aplicativo React e o terceiro para criar um contêiner leve que contém apenas código de produção – não é necessário enviar dependências e ferramentas isso é necessário apenas no momento da criação.

Antes de dar uma .dockerignore , uma pequena dica aqui é criar um arquivo .dockerignore para garantir que não .dockerignore arquivos desnecessários para o contexto do docker. No nosso caso, o arquivo client/node_modules aqui é bem grande. Então, vamos adicionar isso ao arquivo .dockerignore .

 $ echo '** / node_modules'> .dockerignore 

Executando um contêiner docker

 $ docker build -t golang-heroku. 
$ docker run -p 3000: 8080 -d golang-heroku

docker build irá criar uma imagem com uma tag golang-heroku , agora você pode executar uma instância desta imagem usando o comando run. Observe que o comando docker run está encaminhando nossa porta local 3000 e encaminhando isso para a porta 8080 no contêiner, isso significa que agora podemos dar uma olhada no nosso trabalho localmente. Navegue para http: // localhost: 3000 para ver seu site.

Heroku

Agora temos uma versão local do que gostaríamos que Heroku atendesse, este é um processo simples, toda vez que formos direcionar nosso código para o controle remoto do Heroku, uma nova construção será iniciada. A Heroku cuidará da construção e das implantações do docker para nós!

Não vou entrar em muitos detalhes, mas vamos supor que você já criou uma conta Heroku e instalou as ferramentas CLI. Por favor, certifique-se de que você está logado:

 $ heroku login 

Na raiz do projeto, adicione um novo arquivo chamado heroku.yml – isso dirá ao Heroku como implementar nosso aplicativo.

 construir: 
janela de encaixe:
web: Dockerfile
trabalhador:
dockerfile: Dockerfile

Git

Se você ainda não o fez, queremos criar um repositório git na raiz do projeto. Por favor assegure-se de ter removido o diretório client/.git para evitar confusão.

 $ git init 
$ git add.
$ git commit -m 'Initial Commit'

Esses comandos devem criar um repositório inicial com um único commit que contenha todo o nosso bom trabalho.

Agora vamos criar um novo aplicativo Heroku 🙂

 $ heroku cria 
Criando app ... feito, ? hidden-chamber-90878
https://hidden-chamber-90878.herokuapp.com/ | https://git.heroku.com/hidden-chamber-90878.git
$ heroku stack: set container
Conjunto de pilha. O próximo lançamento em ? hidden-chamber-90878 usará container.
Execute git push heroku master para criar uma nova versão em ? hidden-chamber-90878.

Primeiro, criamos um novo aplicativo, você pode ver o URL proposto e o git remote (a ferramenta cli adicionou um controle remoto do Heroku ao seu .git/config ). Então precisamos dizer ao Heroku que pretendemos implantar um contêiner nessa pilha. Feito isso, podemos ir em frente e implantar.

 $ git add. 
$ git commit -m 'Initial commit'
$ git push heroku master
# Se você precisa recuperar seu url prod etc
$ heroku apps: info

É onde a magia de uma PaaS realmente acontece! Eu troco um pequeno pedaço de código, algum HTML talvez, e quando eu o empurro para o heroku remoto heroku , ele apenas enfia a bola e faz um monte de trabalho para criar um novo recipiente imutável para implantar para mim.

A ideia de empurrar o pequeno git se compromete através da rede (como a minha conexão móvel no trem) e ter o Heroku construindo e implantando para mim é bem emocionante!

Resumo

Acho que esse é um excelente primeiro passo, ter a capacidade de trabalhar facilmente localmente e enviar mudanças à produção à vontade (e fazer com que a plataforma cuide do provisionamento de computação e implemente a coisa).

Mas uma API e cliente burro simplesmente não cortam. Na Parte 2 , veremos o provisionamento de um complemento do Heroku Postgres, o desenvolvimento local até o zero e garantiremos que poderemos enviar e migrar o banco de dados no momento do lançamento usando o estágio de lançamento do processo de implantação do Heroku.