プログラミング素人のはてなブログ

プログラミングも電気回路も専門外の技術屋の末端が勉強したことや作品をアウトプットするブログ。コードに間違いなど見つけられたら、気軽にコメントください。 C#、Python3、ラズパイなど。

Oracle Cloud上にWebアプリを構築してみた

はじめに

Oracle Cloud Infrastructure (OCI)とはOracleが提供するクラウドサービスです。
ここにWebサーバーを立ててみました。

同様のサービスにはさくらクラウドやAmazon AWSなどがよく知られています。
ここで、なぜシェアNo.1のAmazonではなく、日系のさくらでもなく、その他でもないか?というところですが、OCIでは無料でそこそこの性能のサーバーが利用できるからです。

以下が、私が調べたVPSで最安またはコストパフォーマンスがよさそうなプランを比較したものです。
VPS(Virtual Private Server)とは、1台の物理サーバー上に仮想的なコンピュータを構築できるもので、サーバーとして主にLinux系OSが使われます。
Core当たりのCPUの性能が同じとは限りませんが、OCIがとびぬけていると思います。(Amazon AWSは複雑なので見る気がしませんでした)

ベンダー 費用月額 CPU メモリー
OCI 無料 4core 24gb
Xserver VPS 792円/月 3core 2gb
さくらVPS 671円/月 1core 512mb
このは 468円/月 2core 1gb

ちなみに似たようなサービスでレンタルサーバーというものがありますが、こちらは今回構築したいものには合わないので対象外です。

今回作成したアプリは掲示板サイトで、Python/Django、DBはPostgreSQLで構築しました。
アプリもインフラ設定もほぼGeminiに作ってもらいました。
ここでは、どんなものができたかの紹介と手順をまとめておきたいと思います。

出来上がったインフラ構成が以下のようなものになります。(この構成図もGeminiに作ってもらいました)

アプリは以下で公開しています。
環境設定(.envファイル)を設定すれば、任意の名前の掲示板を構築することができます。
github.com

インフラの構築

アプリの開発は、クラウドを使うことを前提にWSLでOracle Linuxを作成し、そのうえで構築と動作確認を行いました。
アプリが一通りできたところで、OCI上にインフラを構築します。
また、Xserverでドメインを取得しCloudeflareでDNSを設定します。
現時点でコストは、Xserverでのドメインが初年度無料(2年目以降千数百円)、OCI無料、Cloudeflare無料、で行ける見込みです。

0.Oracle CloudeのアカウントとVMの作成

www.oracle.com
oracle-japan.github.io
応用情報の午前ぐらいの知識がある前提で、チュートリアルを見ながら実施すると半日ぐらいでOCI上にVMを起動するところまでできます。
OCIには無料で使えるAlways freeというプランがあります。
有料プランを契約しないとVMの取得に制限がありますが、じつは有料プランに契約すなわち課金ではなく、有料プランに契約して無料枠を使うという方法があります。
無料プランでも構築はできますが、固定IPの設定ができなかったり、CPUの増強に制限があったりします。
このあたりが、チュートリアルをみてもわかりにくいのですが、CPUの形状(ARMとかAMDとか)によってとれるコア数がちがったり設定できるメモリサイズに違いがあります。
結論としては、最大で無料で以下のようなVMを作ることができます。(厳密にいうと無料プランでも有料プランの無料枠と同じものが作れますが、無料ユーザー向けの枠が少なくなかなか取得できないが、有料プランにすると優先的に使えるようになります)

プラン CPU コア数 メモリ
無料プラン AMD 1 1GB
有料プラン(無料枠) ARM 最大4 最大24GB


Oracle Cloud Free Tier | オラクル | Oracle 日本
※時間に制限があるように見えるが、トータル4OCPU、24GBであれば24h x 31dayでこの時間に収まります。

最初、無料プランでAMD/1core/1GBでアプリを立ち上げましたが、かなりWebページの読み込みが遅いほか、Pythonのライブラリインストールも仮想メモリを使ってやっと、という感じでしたがARM/3core/20GBを使うとかなり快適になりました。

1. ドメインとネットワークの設定

まずは、インターネットからサーバーに辿り着くための道筋を作ります。
Xserverで好きなドメイン(ここではXXX.com)を取得しておきます。
Cloudflare上で、本番(XXX.com)と検証(stg.XXX.com)のAレコードを、OCI(Oracle Cloud Infrastructure)の固定IPアドレスに紐付けます。
SSL/TLS設定はCloudflareのSSLモードを Flexible に設定し、ブラウザとの間だけ暗号化するようにします。
これで、数分待つと有効になります。

2. インフラ(OCI)のセキュリティ設定

サーバーに通信が届くよう、OCIのファイアウォール(イングレス・ルール)を調整します。
OCIの「セキュリティ・リスト」で、HTTP(ポート80)を全世界(0.0.0.0/0)に向けて開放します。
OS内ファイアウォールはインスタンス内の iptables や firewalld で、ポート80へのアクセスを許可。

3. Webサーバー(Nginx)による振り分け

入り口となるNginxで、2つのドメインをそれぞれのDjango(Gunicorn)へ交通整理します。
本番環境(prod)とは別に動作確認用の検証環境(stg)もOCIに構築します。
本来は別インスタンスにするのが理想的ですが、検証環境は利用がそれほど多くないので、同一VMにポート振り分けで構築しました。
このようにすることで無料のVMのリソースを効率よく本番環境に利用することができます。
ちなみに、別インスタンスにする方が構築は簡単です。

バーチャルホストの設定:
XXX.com へのアクセス → ポート800X(本番)へ転送。
stg.XXX.com へのアクセス → ポート800Y(検証)へ転送。

プロキシ設定: proxy_set_header Host $host; を追加し、Djangoがアクセスされたドメイン名を正しく認識できるように設定します。

検証環境はその名の通り検証のために本番と同じ構成で作成したものです。
これにより環境はWSL上のローカル、OCI上の検証、本番と3種類があることになります。
実際に使ってみるとローカルでは動くのに、OCI上に上げると不具合がでる、ということが何度もありました。
検証環境は重要です。
それでも検証環境で動いたのに本番環境で動かない、ということも発生しました。
どうやらキャッシュ(Cloudeflare?)の挙動に差があるようで、CSS、Javascriptを更新したときに古いものが読み込まれるというものがありますが、これ以外は検証環境で確認できればOKそうです。
本当に本番環境を動かすつもりなら、早めにクラウド上の検証環境で確認しておくことが重要ということもわかりました。
アプリの断面でOKかどうかではなく、CD/CI的な観点も事前に確認しておく必要があります。

4. アプリサーバー(Gunicorn)の自動起動

サーバー再起動時もアプリが動くよう、systemd を使ってサービス化します。
サービスファイルの作成: /etc/systemd/system/ に gunicorn_prod.service と gunicorn_stg.service を作成。
環境変数の分離: EnvironmentFile を使い、/etc/opt/myproject/ 内の prod.env と stg.env をそれぞれ読み込ませるよう設定。
SELinuxの調整: サービス経由でのネットワーク通信を許可するため、setsebool -P httpd_can_network_connect 1 を実行。

5. Django(Python)の設定最適化

環境変数を本番と検証に分けて読み込むようにします。

まとめ

OCI上に(本格的な)Webアプリを構築してみることで、インフラの知見を少し得られました。
また、OCIが無料でそこそこ使えるということもわかりました。
ドメインの取得・設定もおもったより簡単でした。
コストも、サーバーはお金がかかる、と思っていましたが、現時点では無料でOKそうです。