はじめに
練習がてら、タイトルの技術を使用した簡単なアプリを作ってみました。
ソースコードはこちら(UI)とこちら(サーバ)です。
アプリそのものというより、構築方法に主眼を置いた記事です。
以下が本稿で説明する内容です。
- DenoコンテナをVS Code Remote Containersで開発するための環境構築方法
- DenoコンテナをGitHubからAzureに自動デプロイする方法
アプリの概要
Qiitaで良い記事を見つけると、ストックをしますが見返すことがほぼありません。これではストックの意味がないので、過去にストックした記事をランダムで表示させることで、過去に覚えた(はず)の知識のおさらいをするアプリです。
作成したアプリはこちらです。ユーザ名欄に任意のユーザ(ユーザ自身を想定)を入力し、表示ボタンを何回か押してみてください。
構築の練習が目的のため、アプリ自体はかなりしょぼいのでご了承ください。
またAzure Web Appsの無料枠を使っているため初回アクセス時は重いです。
主な使用技術
- Azure App Service ・・・ サーバアプリのデプロイ先
- Azure DevOps ・・・ サーバアプリの自動デプロイ
- Deno ・・・ サーバアプリ作成に使用
- VS Code Remote Containers(Docker) ・・・ 開発環境として使用
- GitHub Pages ・・・ 画面のデプロイ先1
- React ・・・ 画面作成に使用1
構成
UIとサーバのリポジトリを分けており、UIはGitHub Pages、サーバはコンテナ化してAzure DevOpsのPipelinesで自動デプロイするようにしています。
また、開発環境は二つともVS Code Remote Containersで開発するようにしています。
DenoコンテナをVS Code Remote Containersで開発するための環境構築方法
重要な部分だけかいつまんで説明します。コードの全体はこちらにあります。
VS Code Remote Containersの設定をする
devcontainer.json
を以下のように設定します。拡張機能のdenoland.vscode-deno
をインストールし、"deno.enable": true
とするところがポイントです。
{
"name": "Your-Memory-Server",
"dockerFile": "Dockerfile",
"shutdownAction": "none",
"appPort": "5000:5000",
"extensions": [
"denoland.vscode-deno",
"eamodio.gitlens",
"mhutchie.git-graph"
],
"settings": {
"terminal.integrated.shell.linux": "/bin/bash",
"editor.formatOnSave": true,
"editor.tabSize": 2,
"editor.detectIndentation": false,
"editor.insertSpaces": true,
"deno.enable": true
}
}
Dockerfileは以下のようにしました。denoのインストールは公式の通りですが、私の環境ではパスを設定しないとdeno
コマンドが動きませんでした。また、開発用にgitやcurlがほしかったためベースイメージをbuildpack-deps
としています。
FROM buildpack-deps:stretch
RUN curl -fsSL https://deno.land/x/install/install.sh | sh
ENV DENO_INSTALL /root/.deno
ENV PATH $DENO_INSTALL/bin:$PATH
この状態でVS CodeのRemote-Containers: Reopen in Container
をクリックすることでコンテナ内に入り、開発が可能です。
VS Codeでdenoアプリをデバッグする
launch.json
を以下のように設定し、F5
でデバッグ可能です。
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"runtimeExecutable": "deno",
"runtimeArgs": [
"run",
"--inspect-brk",
"--allow-net",
"--allow-read",
"-A",
"index.ts"
],
"port": 9229
}
]
}
--allow-net
はサーバ起動、--allow-read
は.env
読み込みのために指定しています。
本番ビルド用のDockerfileを作成する
上記のDockerfileはあくまで開発用のコンテナを作成するためのものなので、実際にAzureにデプロイするコンテナを作成するDockerfileも別で用意します。
FROM buildpack-deps:stretch-curl
ENV DIRPATH /opt/app
WORKDIR $DIRPATH
RUN apt-get update && apt-get install -y --no-install-recommends \
unzip
RUN curl -fsSL https://deno.land/x/install/install.sh | sh
ENV DENO_INSTALL /root/.deno
ENV PATH $DENO_INSTALL/bin:$PATH
COPY . $DIRPATH
ENTRYPOINT deno run --allow-net --allow-read --allow-env index.ts
本番環境では.envを介さずに直接環境変数を読み込むため、--allow-env
を追加しています。
コード
リクエストパラメータとしてユーザ名を投げるとそのユーザがストックした記事一覧をレスポンスとして返す簡単なサーバです。deno標準のhttpライブラリを使用していますが、どうやらルーティングやリクエストパラメータのパース機能が用意されていないようなので、しょうがなく自前実装しています。
本格的にやるなら以下のようなライブラリを使った方がよさそうです。
また、ストック記事は100件しか取得していませんしキャッシュもしていません。これは、単に実装の手を抜いたためです。
import { serve } from "https://deno.land/std/http/server.ts";
import { config } from "https://deno.land/x/dotenv/mod.ts";
let env = config();
if (Deno.env.get("API_KEY")) {
env.API_KEY = Deno.env.get("API_KEY")!;
}
for await (const req of serve({ port: 5000 })) {
if (req.method === "GET" && req.url.split("?")[0] === "/api/v1/article") {
let params: { [key: string]: any } = {};
const paramAry = req.url.split("?")[1].split("&");
for (const param of paramAry) {
const [key, value] = param.split("=");
params[key] = value;
}
const res = await fetch(
`https://qiita.com/api/v2/users/${params.username}/stocks?per_page=100`,
{
headers: {
Authorization: `Bearer ${env.API_KEY}`,
},
},
);
const json = res.json();
const data = await json;
req.respond({
status: 200,
headers: new Headers({
"Content-Type": "application/json",
}),
body: JSON.stringify(data),
});
} else {
req.respond({
status: 404,
body: JSON.stringify({}),
});
}
}
DenoコンテナをGitHubからAzureに自動デプロイする方法
デプロイ先のAzure Web Appsを作成する
はじめに、Azureポータルでデプロイ先のコンテナを作成します。
ここの詳細な手順は省略します。
自動デプロイ設定をする
-
次に、対象のリポジトリからビルド用のDockerfileと公開ポートを選択します。
今回は開発用と本番用で二種類のDockerfileがあるため、本番用を選択するように気をつけます。Portにはコンテナ内のアプリのポートを指定します(仮に5000とすると、docker run -p 80:5000
になるイメージ)。
完了すると、Azure DevOpsにデプロイ用のパイプラインが作成されます。これにより、指定したGitHubリポジトリのmasterブランチからビルドされたDockerイメージがAzure Container RegistryにPushされ、Azure App Serviceにアプリがデプロイされます。
おわりに
AzureはUIが綺麗で好きです。次はこの構成でちゃんとしたアプリを作成したいですね。
ちなみに、この構成を作るにあたって結構はまりました。
結果的には大した事のない問題だったのですが、一応記事にしてあります。
↓↓↓↓
Azure App Serviceに環境変数が設定されなくて困った。と思ったら原因が違った話