素人基盤エンジニアがDockerでDjango REST Frameworkとreactを触るシリーズ②:Django REST Frameworkのつづき。
①からみたい場合はこちら。素人基盤エンジニアがDockerでDjango REST Frameworkとreactを触るシリーズ①:Djangoの導入
reactの導入
最終的には、S3上にreactのアプリを配置してCloudFront経由で表示させたいが、構築/テストまでは同じEC2上でreactとdocker上のDjango REST frameworkを動作させて連携させることとする。
動作が確認出来たら、ビルドしS3に移行する。
node.jsの導入
reactのビルド環境として、node.jsが必要なので、下記手順に従いインストールする。
https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/setting-up-node-on-ec2-instance.html
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
. ~/.nvm/nvm.sh
nvm install node
node -e "console.log('Running Node.js ' + process.version)"
Running Node.js v15.12.0
↑のような形でバージョンが表示されたらインストールは完了。
create-react-app
今回は、reactアプリを簡単に作成することができるツールであるcreate-react-appを利用する。
(本格的にreactアプリを作成したい場合は自分で一から作成したほうが良いと思うが、今回はあくまでreactとDjango REST Frameworkを利用してとりあえず動くものを作るというところを目標とする。)
djangoのためのファイル群をbackendというディレクトリに作成したので、一旦/home/ec2-userまで戻り、下記コマンドを実行する。
cd /home/ec2-user
npm install -g yarn
yarn global add create-react-app
create-react-app frontend
しばらくすると、frontendというディレクトリが作成され、下記のような構成になっているはず。
frontend
∟node_modules
∟パッケージ多数
∟package.json
∟public
∟favicon.ico
∟index.html
∟logo192.png
∟logo512.png
∟manifest.json
∟robots.txt
∟README.md
∟src
∟App.css
∟App.test.js
∟index.js
∟reportWebVitals.js
∟App.js
∟index.css
∟logo.svg
∟setupTests.js
∟yarn.lock
まずはデフォルトの状態で、reactアプリを起動させてみる。
cd frontend
yarn start
http://<ip-address>:3000
にアクセスする。
reactアプリが動作していることがわかる。
ctrl+Cで一旦終了し、下記ソースを修正してみる。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link href="https://use.fontawesome.com/releases/v5.6.1/css/all.css" rel="stylesheet">
<title>ReactSampleApp</title>
</head>
<body>
<h1 class="title">ToDo Apps(React+DjangoRestFramework)</h1>
<div id="root"></div>
</body>
</html>
import React, { Component } from 'react';
import axios from 'axios';
class App extends Component {
constructor(props) {
super(props);
this.state = {
todos: [],
hostname: ""
};
}
componentDidMount() {
this.getTodos();
this.getHostname();
}
getTodos() {
axios
.get('http://<ip-address>:8000/api/todos/')
.then(res => {
this.setState({ todos: res.data });
})
.catch(err => {
console.log(err);
});
}
getHostname() {
axios
.get('http://<ip-address>:8000/api/hostname/')
.then(res => {
this.setState({ hostname: res.data });
})
.catch(err => {
console.log(err);
});
}
render() {
return (
<div>
{this.state.todos.map(item => (
<div key={item.id}>
<h2>{item.title}</h2>
<p className="item_body">{item.body}</p>
</div>
))}
<div className="box30">
<div className="box-title">HOSTNAME</div>
<p>{this.state.hostname.hostname}</p>
</div>
</div>
);
}
}
export default App;
<ip-address>の部分を、EC2のIPアドレスにすることを忘れないように注意。
ここは、CloudFrontでの構成に移行すればIPアドレスを書かなくてもよくなる。
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
h1.title {
font-family: 'Segoe Print',sans-serif;
padding: 0.5em;
color: #494949;/*文字色*/
background: #fffaf4;/*背景色*/
border-left: solid 5px #ffaf58;/*左線(実線 太さ 色)*/
}
.box30 {
margin: 0 auto 0 20px;
width: 300px;
background: #f1f1f1;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.22);
}
.box30 .box-title {
font-size: 1.2em;
background: #5fc2f5;
padding: 4px;
text-align: center;
color: #FFF;
font-weight: bold;
letter-spacing: 0.05em;
}
.box30 p {
text-align: center;
padding: 15px 20px;
margin: 0 0;
}
h2 {
position: relative;
padding: 8px 15px;
margin-left: 40px;
background: #def3ff;
border-radius: 20px;
}
h2:before {
font-family: "Font Awesome 5 Free";
content: "\f111";
position: absolute;
font-size: 15px;
left: -40px;
bottom: 0;
color: #def3ff;
}
h2:after {
font-family: "Font Awesome 5 Free";
content: "\f111";
position: absolute;
font-size: 23px;
left: -23px;
bottom: 0;
color: #def3ff;
}
p.item_body {
font-family: 'Mv Boli',sans-serif;
margin-left: 80px;
}
ソース内で、axiosというパッケージを利用しているので、frontendディレクトリで下記コマンドを利用してパッケージを追加しておく。
yarn add axios
また、Django側の設定も、別サイトからのクロスオリジンアクセスがあるため、下記のように書き換える。
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
CORS_ORIGIN_ALLOW_ALL = True
一行目のcorsheaders~と最後のCORS_ORIGIN_ALLOW_ALLを追加。
docker-compose upでdbとdjangoのコンテナを起動する。
(この後reactも起動したいのでバックエンドで起動する。)
cd backend
docker-compose up &
コンテナを起動させたまま、reactを起動。
cd ../frontend
yarn start
http://<ip-address>:3000/
にアクセスしてみる。
無事、todoとhostnameが表示されていることがわかる。
次回は、今回構築したreactアプリをビルドしS3へ配置して最終系であるCloudfrontの形に変更する。