経緯
今年からWebエンジニアになる23卒エンジニアです。
在学中は主にFlutterとFirebaseで開発をしていたので、Webの知識に疎い&バックエンドを自作したことがありません。。
そこで、このシリーズで自作バックエンド+Webアプリの経験をすると共に
- Docker使いこなしたい
- Webの知識つけたい
- AWS触りたい
- CI/CDやってみたい
という野望をゆるーく掲げつつ、
APIサーバ / コンソールアプリ(Web)/ クライアントアプリ(Mobile)な構成の書籍管理アプリを作っていきます。
ざっくり
phpのapache入りイメージをベースにコンテナを作ります。
APIとコンソールアプリそれぞれサーバーを立てます。
こんな感じのURLにしていきます。
URL | |
---|---|
API | https://localhost:8000/api/* |
コンソールアプリ | https://localhost:8080/console/* |
フォルダ構成
book_app
├ api
├ console
└ docker
└ docker-compose.yml
docker-compose.yml
version: "3.6"
services:
api:
container_name: "api"
image: php:8.1-apache
ports:
- "8000:80"
volumes:
- ./../api/:/var/www/html/api/
console:
container_name: "console"
image: php:8.1-apache
ports:
- "8080:80"
volumes:
- ./../console/:/var/www/html/console/
自分なりの理解
php8.1及びapacheの環境が揃ったイメージ
php&apacheサーバ わくわくスターターキット!
コンテナの80番ポートとホストマシンの8000番ポートを繋ぐ
apacheがデフォルトだと80番ポートでListenしているので80番を指定。
ホストマシンの8000番に来たリクエストはapiコンテナのapacheサーバに繋がる。
apacheのプロジェクトルート配下にapiフォルダをマウントする
こうすればhttps://localhost:8000/api/* のURLにできる。
デフォルトのプロジェクトルートは/var/www/html
詰まったところ
-
Dockerfileで指定できるファイルには制限がある
Dockerfileで書いていた時に、apacheのプロジェクトルートにapiフォルダをCOPYしようとして詰まった。
apiフォルダはbuild contextの外側にあるので参照できないということだった。
詳しくはこの記事に書いてあった。この詰まりについてはそもそも手段がいまいちで、apiフォルダをCOPYする方法ではコードを触るたびにビルドし直す必要が出てくる。
それだと開発時には辛い思いをすることになるのでdocker-compose.ymlのvolumesを使ってバインドマウントするのが良かった。 -
docker-composeのポート指定が何をしているか分かっていなかった
<ホストマシンのポート指定>:<コンテナのポート指定>と書くんだなーとは思っていたが、好きな数字を入れたら良いんだ!くらいに思っていた。
今回はapacheサーバを使ったアプリケーションを作っているので、apacheがListenしているポート(デフォルトで80番)を指定してあげる必要があった。
成果
ベタ書きAPIをベタ書きJavaScriptでfetchして書籍一覧のリストを表示してみます。
API(参考: PHPでAPI作成)
<?php
header('Content-Type: application/json; charset=utf-8');
$response = array();
$book_1 = array("name" => "良いコード/悪いコードで学ぶ設計入門");
$book_2 = array("name" => "ドメイン駆動設計入門");
$book_3 = array("name" => "Clean Architecture");
$book_4 = array("name" => "超すごい本");
$book_5 = array("name" => "バリすごい本");
$books = array($book_1, $book_2, $book_3, $book_4, $book_5);
$response["status"] = "success";
$response["books"] = $books;
$json = json_encode($response, JSON_UNESCAPED_UNICODE);
print($json);
consoleアプリ
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>BookApp</title>
</head>
<body>
<h2>書籍一覧</h2>
<script type="text/javascript" src="./book_list.js"></script>
</body>
</html>
const ul = document.createElement("ul");
fetch("http://localhost:8000/api/v1/holding_book.php")
.then(async response => {
const json = await response.json();
json.books.forEach(book => {
let name = book.name;
const li = document.createElement("li");
li.textContent = name;
ul.appendChild(li);
});
})
.catch((reason) => {
console.log(reason);
});
document.body.appendChild(ul);
俺たちが求めていたもの
現実
次回の目標
フレームワークの力を借りてCORSの設定を行いたい!