とある学生エンジニアがぶつぶつと独り言を呟いているだけのブログサイトです。 生きとし生けるものは幸せでありますように。
AppサーバーデプロイRTA

突然気温が暑くなって眠れないニッシー☆です。

先日、とあるイベントにてAzure App Serviceを使ったアプリケーションのデプロイについてハンズオン形式で受けました。

驚いたことにたったの10分ほどでデプロイは愚かCI/CDパイプラインまで組まれてしまったので感動しました。すごい。。

ハッカソンは時間との勝負。開発という本質的な取り組みに時間を割くためにもCI/CDパイプラインを組み、デプロイの自動化をしておきたいところですね。

ここでふと思ったのは敢えてめんどくさい方のデプロイ方法ではどのくらいの時間が掛かるのだろう、、と。。

めんどくさい方のデプロイ方法とは

以下のことを愚直にやることです!

  • 実際のLinuxPCを用意する(VPSを使ったのでインターネット上に公開する作業は省略)
  • ssh接続する
  • OSのアプデをする
  • ファイアウォールを設定する
  • アプリに必要なライブラリやランタイムをインストールする
  • アプリをgit cloneする
  • デーモンとしてアプリを起動させる
  • Nginxをリバースプロキシとして設定する
  • ドメインを紐付ける
  • SSL化する
  • etc…

それでは行ってみよう!!

本編スタート

今回はNode.jsアプリケーションをUbuntu20.04に最速でデプロイする手順をメモしていきます。もちろんエンタープライズな場では参考にしないでください。

Linux機を1台用意する

公開する物理的なサーバーが無いと始まらないので用意します。今回はレンタルサーバーサービスであるConoHa VPSのUbuntu20.04イメージを契約することで準備とします。

VPSにSSH接続できるようにする

ConoHa VPSでは管理画面での設定を弄ることで公開鍵認証方式の公開鍵をVPSのホストにセットできます。対になる秘密鍵を手元のパソコンにセットしてSSH接続できるようにします。例えば以下のような情報を ~/.ssh/config に設定します。

Host ubuntu
  HostName <your-server-ip>
  User root
  Port 22
  IdentityFile ~/.ssh/ubuntu.pem

この設定により以下のコマンドでVPSにSSH接続できるようになります。

ssh ubuntu

以後rootユーザーでの操作を前提とします。

OSのアップデートをする

後に入れるNginxがパッケージ一覧にデフォルトでなかったりするので必須です。以下のコマンドでできます。

apt update -y && apt upgrade -y

Ubuntuのアップデートについて↓

https://ubuntu.com/server/docs/upgrade-introduction

少し休憩。

休憩もつかの間。

ところで、、

アプデが終わったら確実に反映させるためにOSの再起動をしましょう。

Nginxを入れる

Webサーバーの一種であるNginxを入れます。複数のアプリを同一インスタンス上で動かす予定があったのでリバースプロキシとして動いてもらうことが目的です。以下の記事を参考にインストール&設定しました。

https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-20-04-ja

ファイアウォールを有効にする

必須ではないですが宗教上の理由で有効化させます。ポイントはWebサーバー用で利用する80番ポートと443番ポートの他にSSH接続で使う22番ポートを許可する設定にすることです。こうしないと次回のSSH接続で繋がらなくなくなります。こうなると直接サーバーにアクセスしないといけなくなります。(まあこのあたりはConoHa VPSではWeb上の管理画面から端末を開くことでアクセスできるのですが、、初学者だったころのぼくはテンパりました。。)

参考にしたサイトはこちら↓

正しく設定できればブラウザからグローバルIPアドレスにアクセスすることでNginxのWelcomeページが見られます。

グローバルIPまたはサーバーのIPアドレスは以下のコマンドで参照できます。
hostname -I
# もしくは
curl -4 icanhazip.com

アプリケーションを配置する

ここまで書くまで意識していませんでしたがここから先の工程がいわゆるデプロイの本質的な部分です。

デプロイユーザーを作成する

デプロイに必要な権限だけを持ったユーザーでアプリケーションのコードを管理します。以下のコマンドで作成します。

adduser deployuser

アプリ配置先のディレクトリを作成する

アプリを配置するディレクトリを作成します。その際にディレクトリの所有者をdeployuserにします。

mkdir /var/www/nodejsapp/
chown deployuser: /var/www/nodejsapp/

git cloneする

GitHubなどのリモートリポジトリからコードをクローンします。

cd /var/www/nodejsapp/
sudo -u deployuser -H git clone <your awesome nodejs app repository url> code

deployuserとしてコマンドを実行するために sudo -u deployuser -H ... といった形にコマンドがなっています。それからgit cloneの第2引数にcodeという文字列を渡しているのでクローンしたリポジトリのディレクトリ名はcodeになります。

Node.jsをインストールする

コードをクローンするだけではNode.jsアプリは動きません。Node.jsランタイムを入れていきます。今回は宗教上の理由でanyenvからのnodenvからのnode16系を入れます。RTAなのでapt install nodejsで適当なNodeを入れればよいのは確かです。

ローカル開発環境にはanyenvanyenv-updatenodenv-yarn-installを脳死でいつも入れてます。

Node.jsのインストール完了後、ローカルでやるのと同じ通りにプロジェクトのルートへ行き、npm i && npm startを実行します。(環境によってコマンドは変わると思います)

一旦、実行したままにしておきます。

リバースプロキシの設定をする(その1)

現状でNginxの設定を弄り、リバースプロキシの設定をします。新しく端末を開き、VPSに接続します。

以下の内容で/etc/nginx/conf.d/nodejsapp.confを作成します。

server {
        client_max_body_size 50M;
        server_name <サーバーのグローバルIPアドレス>;
        location / {
                proxy_pass http://localhost:8000; # nodeアプリが待機しているアドレス
        }
}

Nginxの設定を再読み込みします。

systemctl reload nginx

グローバルIPアドレスにアクセスしてnodeアプリが応答することを確認します。

http://<your-server-ip>/

アプリをデーモン化する

動かし続けるために端末を一個犠牲にするなんてことはしたくないので裏側で起動させるための設定をしていきます。systemdの仕組みを利用します。

https://qiita.com/bluesDD/items/eaf14408d635ffd55a18

一旦、nodeアプリが動いている端末に戻り、ctrl+Cで停止させてください。

以下のような内容を /etc/systemd/system/nodejsapp.serviceに記述します。

[Unit]
Description=cicd handson js sample app
After=syslog.target network.target

[Service]
Type=simple
ExecStart=/home/deployuser/.anyenv/envs/nodenv/shims/node /var/www/azure-web-app-js/code/bin/www
Working/Directory=/var/www/nodejsapp/code
KillMode=process
Restart=always
User=deployuser
Group=deployuser

[Install]
WantedBy=multi-user.target

以下のコマンドでnodeアプリを起動できるようになります。

systemctl start nodejsapp

改めてグローバルIPで挙動を確認します。

systemd化のために参考にしたサイト↓

https://qiita.com/you21979@github/items/588bddb59378ce7303a2

ドメインを紐付ける

IPアドレスで直接アクセスするのはダサいのでドメインを紐付けます(個人の意見です)

ドメインを管理しているサービスで例えば以下のようなレコードを追加します。

レコード名レコードタイプ
js.yukinissie.com (your domain)A118.27.22.88 (your-server-ip)
DNSに登録するレコードの例

リバースプロキシの設定をする(その2)

ドメインを紐付けたのでNginxの設定を変更し、ドメインからのアクセスをNodeアプリに中継するようにします。/etc/nginx/conf.d/nodejsapp.confを以下のコードに修正します。

server { 
        client_max_body_size 50M;
        server_name js.yukinissie.com; # 変更点。ここは人によって異なる
        location / {
                proxy_pass http://localhost:8000; # nodeアプリが待機しているアドレス
        }
}

ドメインでアクセスできるようになりました。

SSL化する

httpじゃなくてhttpsにして通信内容を暗号化し情報を守る仕組みですね。

今どきSSL化されてないとかダサいとしか言いようがないのでします。(個人の偏見です)

無料で且つ自動的に発行を行うためにcertbotを使います。証明書の発行自体はLet’s Encryptが使われます。以下のコマンドでcertbotを入れます。(snapが入っている前提です)

snap install core && snap refresh core
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot

そして以下のコマンドを打ってcertbotを実行します。

certbot --nginx

いくつかの質問を対話的に答えることでSSLの設定が完了します。

certbotを実行しているときの様子

これでSSL化ができます。(うまく行かないときはNginxをreloadすると動くかもしれません)

https://js.yukinissie.com/

ちなみにcertbotがNginxの設定を自動的に書き換えてくれるのでSSL化させたドメインでアクセスできるようになる仕組みです。/etc/nginx/conf.d/nodejsapp.confを改めて見るとその痕跡がみれて勉強になります。

SSL化のためにみたドキュメント↓

https://certbot.eff.org/instructions?ws=nginx&os=ubuntufocal

ようやくデプロイができました!!!!🚀

RTAに掛かった時間は、、

1時間50分でした!うん、長い!!

感想

やっぱりクラウドサービスって偉大なんだなって思いました。。

Portfolios

Portfolios

これまで作ったアプリの要約とURLを書き留めました。

ホームページ(yukinissie.com – ニッシー☆のブログ)

今ご覧になられているWebサイトです。自分でレンタルしたVPSに1から構築しました。

https://yukinissie.com

Wa:talk

話題提供アプリです。その場にいる人との親睦を深めたいときにどうぞ。概要はこちらから。

※[注意]パソコンからのアクセスの場合、音が出ますのでご注意ください。

https://watalk.yukinissie.com

Meguru Cosmos

モダンな技術を銀河にしました(?)。とあるハッカソンにて製作した作品です。概要はこちらから。

※[注意]若干身内ネタが混ざっています。ご了承ください。

https://lonely1.yukinissie.com

Mazakan

とあるハッカソンに野良で且つ1人で参加したときに作ったWebアプリ。エナジードリンクを日常的に飲む皆さんに専用チャットにて報告してもらいそのチャット数を集計・ランキング化するというもの。

LambdaのようなファンクションサービスやDynamoDBのようなNoSQLサービスを扱うことが初めてだったのでさまざまな面で苦労しました。まずLambdaはフロントが永続化したいデータをDyanamoDBに保存したり、保存済みのものを取得したりするために作成しました。小さなスクリプトを書くに等しいのですが、DynamoDBの扱いに慣れてない(というか知らない)のも相まってとても手こずりました。

React.jsについてもハッカソン中しか学ばないのもあって非同期でデータをフェッチする箇所を書くのに少し時間がかかりました。

この時はDynamoDBにソートのための仕組みを実装できなかったため、チャットによる表示の時系列はめちゃくちゃになってしまいました。

https://mazakan.yukinissie.com

Keiziban(Vue Chat)

開発合宿にてVue.jsで作った掲示板アプリです。ほぼはじめてのVueでしたがなんとか2日で形になったのでよかったです。手こずった点は、APIゲートウェイにてCORS設定を適切に設定していなかったためにリクエストを拒否され続けていたことに半日ぐらい気づけなかったことです。。

元となるソースコードを公開しています。(ソースコードはこちらから)

https://vue-chat.yukinissie.com

勉強で作ったサンプルアプリ

チュートリアルで作った成果物です。ホスティングに費用はかかってないのでドメインをつけて公開しています。

https://nextjs-tutorial.yukinissie.com

https://hello-gatsby.yukinissie.com

https://hello-gatsby-and-netlify.yukinissie.com

https://learnjs.yukinissie.com

その他

なにかしらの作品になるかも??

https://nyannyan.yukinissie.com

https://www.yukinissie.com

以上です。

最後まで見てくださりありがとうございます。

他にもデプロイしていないものがいくつかあるのでこのページに追加していきたいと思います。

watalk
Wa : talk(わトーク)

#watalk
#eye_of_the_cyclone
#キャンプハッカソン
#ハックツハッカソン
#made_in_kyushu

さっそくはじめる

※音量注意(PCユーザーのみ)

What’s “Wa:talk”?

トークテーマと話す人をランダムで表示してくれる話題提供アプリです。

こんな人にオススメです。

  • みんなで楽しみたい
  • その場にいる人との親睦を深めたい
  • 大人数でトークをしたい
  • トークしたいけどおもしろい話題が浮かばない

そんなあなたに以下を提供します。

  • 5 種類 100 個以上のトークテーマ
  • トークテーマの趣に合わせた BGM (PCユーザーのみ)

特徴

  • ユーザーとトークテーマの選択は完全ランダム
  • その場かぎりのインスタントユーザー管理機能
  • トーク時間を管理するタイマー機能
  • トークターン数を管理するカウンター機能
  • すべてオリジナル BGM

さっそくはじめてみる

プロダクトの URL を掲示します。

ぜひお試しください。

※音量注意(PCユーザーのみ)

「Wa:talk」 プロダクトURL:https://watalk.yukinissie.com

※URL はいずれ変更されます。ご了承ください。(このページや、Twitter(@yukinissie) で予告します)
※このプロダクトの利用によって起きた利用者のいかなる損害についての責任は負いかねますのでご理解のほどよろしくお願いします。
※このプロダクトはα版です。

追記1:Wa:talkのURLが変わりました。上記の通りです!(2021/05/30)

開発経緯

このプロダクトは株式会社ハックツ主催のハッカソン「キャンプハッカソン」にて大学生 2 人(企画/プレゼン:@oyamamanao, 開発:@yukinissie)の手によって開発されました。

BGM提供者

以下の方にBGMを提供していただいています。

使用技術について

以下に概要だけを示します。

フロントエンド

サーバーサイド・インフラ

Node.js 環境構築(Mac × fish × anyenv)

Node.jsを使う機会があったのでメモ。

前提要件

以下の環境上で構築する。

  • OS
    • MacOS Catalina v10.15.6
  • shell
    • fish v3.1.2
  • Xcodeインストール済み。
  • Homebrewは使わない。
  • **env系は入っていない。

anyenv のインストール

nodenvを使ってNode.jsを管理したいので、まずはnodenvそのものを管理するanyenvをインストールする。

必ず本家サイトを参照すること。

git clone でダウンロード

$ git clone https://github.com/anyenv/anyenv ~/.anyenv

パスを通す

$ echo 'set -x PATH $HOME/.anyenv/bin $PATH' >> $HOME/.config/fish/config.fish

anyenv の初期化

$ ~/.anyenv/bin/anyenv init

結果

# Load anyenv automatically by adding
# the following to ~/.config/fish/config.fish:
status --is-interactive; and source (anyenv init -|psub)

言われた通りに以下を~/.config/fish/config.fishに追記。

※環境によって追記内容が違うかも。

status --is-interactive; and source (anyenv init -|psub)

anyenv install の初期化

ターミナルに再ログインする。

結果

ANYENV_DEFINITION_ROOT(/Users/riywo/.config/anyenv/anyenv-install) doesn't exist. You can initialize it by:
> anyenv install --init

anyenv-installフォルダ(install manuifest)が無いよと注意される。

以下のコマンドで作成。

$ anyenv install --init

途中、Do you want to checkout ? と聞かれるので「y」を押してリターン。

anyenv自体のインストールは完了。

以下のコマンドでinstallできるもののリストを確認できる。

$ anyenv install -l

各**envをアップデートするためのプラグインをインストール

$ mkdir -p (anyenv root)/plugins
$ git clone https://github.com/znz/anyenv-update.git (anyenv root)/plugins/anyenv-update

プラグインの本家サイトはこちら

以下のコマンドでアップデートできるようになる。

$ anyenv update

nodenvのインストール

$ anyenv install nodenv
$ exec $SHELL -l

yarnも一緒に入れてくれるプラグインをインストール

$ git clone https://github.com/pine/nodenv-yarn-install.git (nodenv root)/plugins/nodenv-yarn-install
$ exec $SHELL -l
$ nodenv hooks install

Node.js をインストールする

Node.jsのバージョンリストを表示

$ nodenv install -l

バージョンを指定してインストール

$ nodenv install 14.10.1

globalで使うバージョンの指定

$ nodenv global 14.10.1

Node.jsのバージョン確認

$ node -v
v14.10.1

これでNode.jsの環境構築ができた。

以上。

参考

fishでanyenvを使う

anyenvを使う

anyenv.github.io

anyenv-update

ndenv / nodenv で Node.js をインストールする際、同時に Yarn もインストールする方法

nodenv-yarn-install

はじめてのiOS勉強会からの1人ハッカソン

勉強会で作ったアプリを元に挑むハッカソン

先日、とあるSwift勉強会に参加し、はじめてのiOSアプリをビルドしました。
その勉強会の裏イベントで、iOSアプリをテーマとした1人ハッカソンが開催されるということで、学んだことをアウトプットする機会として参加してみました。
以下、関連URLです。

CountUpGame

このアプリについて

勉強会で作ったアプリを拡張して、ゲーム要素を取り入れてみました。
+ボタンやーボタンを押すと表示されている数字の値が変化する仕様だったので、新たにターゲットとなる数字をランダムに用意し、プレイヤーはそれに合わせる形でカウントアップやカウントダウンをしてもらい、スコアを稼いでもらうようにしました。
制限時間を用意したのでどれだけ速くターゲットと数字を合わせられるかがスコアゲットの鍵になります。

プレイ映像

play映像

技術的概要

  • Xcode Version 11.6 (11E708)
  • Swift Version 5.2.4
  • StoryBoardを使用
  • アダプティブユーザーインターフェイスに挑戦
  • ダークモードでも使用できるように調整(プレイ映像はダークモード)
  • import GamePlayKit
  • 乱数を生成: GKRandomDistribution(lowestValue: Int, highestValue: Int)
  • Timerを使用
  • プレイヤーの扱う数字はcount、ターゲットの扱う数字はquestionで集約(リファクタリングの余地がありそうです。)

まとめ

はじめてのネイティブアプリ制作でしたが自分なりにアウトプットできてとても楽しかったです。
ヒミツ機能としてオンライン対戦機能を付けようと思っていたのですが、、
サーバーとの通信を用いたアプリを作るには、まだまだ僕の技術的スキルでは及ばない感じです。。

大学のテスト頑張ります(^^)(全く関係ない)

リポジトリはこちらhttps://github.com/yukinissie/CountUpGame