6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ReactとFlaskがGCPへ

Last updated at Posted at 2020-03-22

GCP使ってみたいドリブンでYelp API使ったテストサイトを作る

GCPでAPIテストサーバー作りたかった
言語: React, Flask
Screen Shot 2020-03-22 at 1.12.36.png

これにどこからかのapi付けて描画すればいいかなっと思ったけど味気ない (Learn Udonのリンク先は、うどんについて語るwiki)ので
image.pngYelp API使ってこんな感じにした

Yelp api

日本の食べ物系サイトはみんな知ってるし、海外のをちょっと見てるのもよいかなとyelp apiを使った

api keyの取得は簡単。yelp developersに入ってgoogleかfacebookのアカウントで登録すればすぐ発行してくれる

Flask

ディレクトリ構成

app
├── config.py
└── run.py
# run.py

from flask import Flask, request
from flask_cors import CORS
import requests

import config

app = Flask(__name__)
CORS(app)

URL = "https://api.yelp.com/v3/businesses/search"
headers = {'Authorization': f"Bearer {config.API_KEY}"}


@app.route('/')
def ramen_yelp():
    payload = {
        "term": request.args.get("term", "ramen"),
        "location": request.args.get("location", "ny")
    }
    response = requests.request("GET", URL, headers=headers, params=payload)
    return response.json()


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=config.PORT, debug=config.DEBUG_MODE)

root('/')の場合はデフォルトでニューヨークのラーメンランキングにしている

configにはflask, gunicornの設定
大事なことはenv変数に入れておく

# config.py

from os import environ
import multiprocessing

PORT = int(environ.get("PORT", 8080))
DEBUG_MODE = int(environ.get("DEBUG_MODE", 1))
API_KEY = environ.get("API_KEY")

bind = ":" + str(PORT)
workers = multiprocessing.cpu_count() * 2 + 1
threads = multiprocessing.cpu_count() * 2

ブラウザ(firefox or chrome)から0.0.0.0:8080に入ると
json_screen_shot.png

結果をjsonで吐き出すようになった

GCR (Google Container Registry)に登録

flaskをdocker化してGCRにup

Dockerfileはこんな感じでサクッと

# pull official base image
FROM python:3.8.1-alpine

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# install dependencies
RUN pip install --upgrade pip
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt

# set work directory
WORKDIR /usr/src/app

# copy project
COPY ./app .

ENV PORT 80
ENV API_KEY YOUR_API_KEY

CMD ["gunicorn", "run:app", "--config=config.py"]
# requirements.txt
Flask==1.1.1
gunicorn==20.0.4
requests==2.23.0
Flask-Cors==3.0.8

*本番はAPI_KEYをdotenv使ってconfig.pyにまとめる

  • gcloudをローカルにインストール(doc)
  • GCRの課金を有効にする

次に下記のようにコマンド打てば簡単に登録できる

#!/bin/sh
docker build -t flask-test-gcr 
docker tag flask-test-gcr [HOSTNAME]/[PROJECT-ID]/flask-test-gcr
docker push [HOSTNAME]/[PROJECT-ID]/flask-test-gcr
gcloud container images list-tags [HOSTNAME]/[PROJECT-ID]/flask-test-gcr

こんな感じ
Screen Shot 2020-03-22 at 14.08.08.png

GCE(Google Compute Engine)

インスタンスをgcpコンソール画面から作成

マシンスペックはテストなので最弱の最弱にしよう!
image.png

docker使ってコンテナからすぐデプロイしたい人は下記のチェックとコンテナイメージを忘れずに
image.png

GCE VMインスタンス画面の外部IPを http:[IP] にすれば同じ結果が出るようになった!
SSL証明書がない場合は外部IPを https じゃなくて http にしないとダメだよ
image.png

このIPアドレスをReactから呼び出すのでメモしておく

FrontはReact

create-react-appというステキなボイラープレートで簡単に

# app-nameは好きな名前で
npx create-react-app app-name

App.jsはほとんどテンプレで、画像やリンク、Yelp.jsのComponentを呼んでいる違いぐらい

// App.js

import React from 'react';
import logo from './logo.svg';
import './App.css';

import Yelp from './Yelp' //←これ

function App() {
  return (
    <div className="main">
      <Yelp />
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="Udon logo" />
          <a
            className="App-link"
            href="https://ja.wikipedia.org/wiki/%E3%81%86%E3%81%A9%E3%82%93"
            target="_blank"
            rel="noopener noreferrer"
          >
            Learn Udon
        </a>
        </header>
      </div>
    </div>
  );
}

export default App;
// Yelp.js

import React, { useEffect, useState } from 'react'
import './Yelp.css'

const Yelp = () => {
  const [error, setError] = useState(null)
  const [yelpData, setYelpData] = useState({})

  useEffect(() => {
    const API_URL = 'http://さっきメモした外部IP/'
    fetch(API_URL)
      .then(res => res.json())
      .then(
        result => {
          setYelpData(result)
        })
      .catch(e => {
        setError(e)
      })
  }, [])

  if (error) {
    return (
      <div className="Yelp">error</div>
    )
  } else if (yelpData.businesses) {
    const images = yelpData.businesses.map(item => {
      return (
        < a key={item.id} href={item.url} target="_blank" rel="noopener noreferrer" >
          < img
            height="150" width="150" crop="fill" radius="20"
            src={item.image_url} alt="ramen"
          />
        </a >
      )
    })
    return (
      <div className="Yelp">
        {images}
      </div>
    )
  } else {
    return (
      <div className="Yelp"></div>
    )
  }
}

export default Yelp

あとはローカルで起動すればラーメン画像が出てくる

# 起動
yarn start

好きな画像をクリックするとYelpのリンク先にとんで詳細が見れる
ラーメン

  • ニューヨークのラーメン屋さんはメニューが豊富。ラーメン一筋でやるのは文化的に合わないのかな
  • うどんのSVGがグルグル回ってるのがうっとうしい、良いかは賛否ある

参考

ContainerRegistry(GCR)に登録されたDockerイメージをGCE上で動かす

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?