1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【クラウド開発環境】GCPを使って快適なフロントエンド環境を構築する〜実践編〜

Last updated at Posted at 2021-10-09

この記事は続きものになっています。今回は実践編です。
前回→紹介編

前回のあらすじ

クラウド開発環境はいいぞ。

構築してみる

ここからは実際にクラウド開発環境を構築していきましょう!
なお今回はMacからやってますんで、Windowsだとコマンドとかちょっと違う場合があるかもしれません。
まあ細かいところが違うだけで流れは同じです。なんかできなさそうなことあったら調べてみてください。代替するものはあるはずです。

1. Compute Engineのインスタンスを作成する

Compute Engineにアクセスし、プロジェクトが無い場合はプロジェクトを作成します。

create_project.png

課金の設定がなければ課金設定に飛ぶので、カード情報とかを入力して課金情報を登録しましょう。
課金情報が無ければ当然インスタンスを使用することはできません

課金情報も登録できたら、Compute Engine APIを有効にします。有効にするだけなら特にお金はかかりません。
activate.png

有効になったらこんな画面になります!インスタンスを作りましょう!
dashboard.png

インスタンス作成画面では、スペックを選択することができ、そのスペックに応じた費用を右側に出してくれます。
create_instance.png

自分は以下の設定にしていますが、こちらは臨機応変に変えていきましょう。クラウドの強みであります💪

項目
シリーズ N1
マシンタイプ n1-standard-2(2 vCPU、7.5 GB メモリ)
OS Debian
ディスク種類 バランス永続ディスク
ディスク容量 30GB
その他 デフォルト

ファイヤーウォールには何もチェックを入れないようにしましょう。後で設定します
firewall.png

作成ボタンを押せばインスタンスが作成され、さっきは何も無かったインスタンス一覧に新しくインスタンスが起動した状態で追加されます!
new_instance.png

ステータスが緑のチェックになり、外部IPにそれっぽいIPアドレスが入ってると思います(ここでは隠してます)

これで無事インスタンスが作成されました!しかしこれだけだとまだインスタンスに入って作業できません。次にインスタンスにSSH接続できるようにしましょう。

2. 作成したインスタンスに接続できるようにする

外部IP右の「SSH」を使えばブラウザからインスタンスに入れはするんですが、まあ使い勝手は悪いので自分のローカル環境からSSH接続してインスタンスに入るようにします。

2の1. ssh-keygenする

SSH接続するために、公開鍵と秘密鍵を作成しましょう。

適当にターミナル開いて

$ ssh-keygen

sshキーの保存先が聞かれます。デフォルトは~/.ssh/id_rsaです。
複数の鍵を作る場合は名前分けたほうがいいですが、まだ何もない場合はデフォルトで良いのでそのままEnterでもOKです。
その後パスフレーズが聞かれますが、こちらは特に何も書かずにEnterでいいと思います。1

こんなやつ出てくれば成功です

The key's randomart image is:
+---[RSA 3072]----+
|        . oo. o. |
|         o o.=.. |
|          + =.o. |
|           oooE  |
|        S .o * . |
|       .oo .% +  |
|       .==+B B . |
|       o+O+ * .  |
|       .=o++ .   |
+----[SHA256]-----+

ls ~/.sshでファイルを確認すると、id_rsaid_rsa.pubが生成されているはずです。

2の2. 公開鍵をGCPに登録

Compute EngineのSSH認証鍵から公開鍵(id_rsa.pub)を登録します
ssh.png

出てきた入力欄にid_rsa.pubの中身をコピペしてください
pasted.png

これで保存すればOKです!

2の3. 接続の確認

これで起動しているインスタンスにSSH接続できるようになってるはずです!
接続してみましょう

# ssh [ホスト] 的な感じ
$ ssh 111.111.111.111

ホストのところには入りたいインスタンスの外部IPを入れましょう。
鍵ファイルの名前を自分で指定した場合はファイル先のパスを指定してやる必要があります。例えばこんな感じ

$ ssh 111.11.1.0 -i ~/.ssh/bo_id_rsa

初回ログイン時はなんかcontinue connecting?とか聞かれますが、適当にyesしておきましょう。

なんかターミナルの感じが変われば成功です!これでインスタンスに接続できるようになりました!

2の4. ファイアウォールの設定

このままだとインスタンスにhttpで接続できない(=ブラウザから実行結果が開けない)ので、ファイアウォールを設定してhttpとhttpsで接続できるようにします。

ファイアウォールの設定を開きます。
スクリーンショット 2021-10-09 12.54.28.png

デフォルトでなんか色々ありますが、全部使わないので削除しちゃって大丈夫です
必要になったらルール作りゃいいんすよ

スクリーンショット 2021-10-09 12.57.09.png

まっさらになりましたね。それではルールを作成しましょう。
スクリーンショット 2021-10-09 13.00.50.png

色々設定する項目ありますが、以下のように設定しましょう

項目 なんなんそれ 設定例
名前 ルールの名前。そのまんま bo-dev-ip
ターゲット このルールを適用するインスタンスをフィルタリングできる。設定分けないならネットワーク上のすべてのインスタンスでおk ネットワーク上のすべてのインスタンス
ソースフィルタ フィルタを設定して接続範囲を限定する。IP範囲を選択 IP 範囲
ソースIPの範囲 指定したIPアドレスでしか接続できないようにする。
自分のIPアドレスの確認はこちらから。サブネットマスクまで指定する必要がありますが、/32って書いときゃ大丈夫です
114.51.4.19/32
プロトコルとポート 接続できるポート番号を指定する。プロトコルはTCPで、SSH、http、httpsで接続できるようにしたいのでそれぞれに対応する番号22,80,443を入力します。 ✅ tcp: 22,80,443
その他 デフォルトでおk

あとは「作成」ボタンを押して完了です👍
今一度SSH接続をやってみて接続できることを確認しておきましょう。22番ポートが解放されていればSSH接続できますので、それでファイアウォール設定がうまくいってるか確認できます。

3. エディタからインスタンスに接続する

ここではVS Codeでの接続例を提示します。他のエディタの接続方法はわからんぽよなので、他のエディタを使用する場合、このステップはなんとかご自身で頑張ってください。

3の1. 拡張機能のインストール

ぼくが大好きRemote - SSHくんをインストールしましょう
スクリーンショット 2021-10-09 19.26.14.png

VS Codeの拡張機能で「Remote SSH」なんかで検索すれば一番上に出てきます。それをインストールしましょう。

3の2. 設定ファイルを書く

以下のいずれかの方法で設定ファイル(~/.ssh/config)を開きます
config.png

  • F1remoteと検索して出てくるRemote-SSH: Open SSH Configuration File...を選択
  • Remote - SSHで追加されるタブ「リモートエクスプローラー」の設定アイコンをクリックし、Remote-SSH: Open SSH Configuration File...を選択リモートエクスプローラー.png
  • nanoとかviで直接開く(nano ~/.ssh/config)

設定ファイルが開けたら、以下の設定を追記します。

Host bo-dev # 名前。なんでもいい

    # 起動させたインスタンスの外部IP。
  HostName 11.45.14.19

    # 公開鍵についてるユーザー名。
  # 今回のようにssh-keygenでユーザー名指定してないならローカルでログイン中のいつものユーザー名でおk
  User bo-yakitarako

  # 秘密鍵への絶対パス。ssh-keygenでファイル指定してないなら「~/.ssh/id_rsa」になるはず
  IdentityFile /Users/bo-yakitarako/.ssh/bo_id_rsa

言わなくても大丈夫だと思うけど上記のものは一例であって、そのまんま書いてもダメですからね?各々で対応するものに値を設定してください。

これで上記の場合はbo-devという接続先に接続する準備が整いました。

3の3. 接続!

以下のいずれかの方法で接続します。

  • F1remoteと検索して出てくるRemote-SSH: Connect to Host...を選択すると、さっき設定した名前で接続先が出てくるのでそれを選ぶbaka.png

  • リモートエクスプローラータブからさっき設定した名前の接続先の右側のアイコンをクリックするooo.png

設定がうまくいってれば、VS CodeでSSHに接続した形になります!
👍.png

うまく接続できたら最初にエクスプローラーからフォルダを開いておきましょう。フォルダを開いておけば、後から直接開いたフォルダに行けるようになります。
Connect to Host...から来るよりフォルダに行ったほうがなにかと便利やね

こうして こうじゃ
step1.png step2.png

ひとまずOKしてユーザーのホームディレクトリを開いておきます。

フォルダから入るには以下の方法があります。

  • ファイル最近使用した項目を開くフォルダのパス [SSH: 接続名]を選択
    ※下記画像は会社のプロジェクト含まれてるんで一部隠してますselect_folder.png

  • リモートエクスプローラータブから開くtab.png

3の4. watch上限を最大にする

なにやらwatch上限なるものがあって、HMRとかgitとかが監視するファイルの最大数が設定されているらしいのです。
デフォルトでも65536くらいあるっぽいのででかくなんなきゃ大丈夫だと思うんですが、これ超えちゃうとHMRができなくなっちゃうんで、一応最大まで上げておきましょう。

このコマンドを実行してくだせえ

$ sudo sh -c 'echo fs.inotify.max_user_watches=524288 >> /etc/sysctl.conf' && sudo sysctl -p

fs.inotify.max_user_watches=524288とか言われたら適用できてます🌞

3の5. 拡張機能入れる

ローカルとクラウドで拡張機能の管理は別なので、ローカルに入ってる拡張機能は入れ直す必要があります。
といってもLocal - インストール済みって具合にローカルで入れてる拡張機能に絞って表示してくれて楽にインストールできると思います。ありがたや...ありがたや...
extension.png

Remote-SSHのトラブルあるある

Q. Permission Deniedとか言われて接続できない!

以下の原因が考えられます。

  • 秘密鍵の絶対パスが違うかも(よくやる)
  • ユーザー名間違えてるかも
    • SSH認証鍵に登録した公開鍵のユーザー名と同じにするようにしましょうpublic.png
  • そもそもssh-keygenで鍵作ってないかも
Q. Could not establish connectionとか言われるんだけど?

→**known_hostsにIPが登録されてるかも**

同時に起動しないと複数のインスタンスで同じ外部IPを共有します。known_hostsには最初にcontinueしたインスタンスとそのときのIPアドレスが登録されるのですが、それ以外のインスタンスでそのIPアドレスに接続しようとするとこのエラーになります。

対応策は簡単で、~/.ssh/known_hostsを開いて該当するIPアドレスが書かれてる行を削除するだけです。

4. nginxでhttp接続できるようにする

ブラウザからアクセスできるようにするために、nginxを設定します。
ここからはDockerでやったほうが良さみですが、Dockerよくわかんない(大敗)のでシステム直接いじっていきます。

とにもかくにもまずはインスールじゃい!

$ sudo apt-get update
$ sudo apt-get install nginx

インストールが完了したっぽかったら、nginxが動いてるか確認しましょう。

$ sudo systemctl status nginx

なにやら仰々しく色々でてきてたらOKです。

そうしたら、設定ファイルを書きます。
詳しい説明は省きますが、/etc/nginx/conf.d以下に設定ファイル(***.conf)を置くようにしていきます。

$ nano /etc/nginx/conf.d/dev.conf

nanoとかviで開いたら、以下のように入力します。(nanoとかviの使い方はググってちょ)

/etc/nginx/conf.d/dev.conf
server {
    listen 80;
    server_name bo-dev;

    proxy_set_header    Host    $host;
    proxy_set_header    X-Real-IP    $remote_addr;
    proxy_set_header    X-Forwarded-Host    $host;
    proxy_set_header    X-Forwarded-Server    $host;
    proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for;

    location / {
        proxy_pass http://localhost:3000/;
    }
}

書けたら保存して、nginxを再起動させて設定を適用しましょう。

$ sudo systemctl restart nginx

特になんも言われなければおkでごぜーます。

ブラウザからhttp://bo-devに接続すると、nginxがプロキシになってインスタンス内のlocalhost:3000に繋いでくれるという流れですね。
とはいえbo-devの名前解決もやってないですし、そもそもlocalhost:3000も立ってないのでこの段階では接続はできません。

5. 開発用ドメインを名前解決する

突然http://bo-devが出てきてちょっと困惑したかもしれません。申し訳NASA
というのもクラウド環境にlocalhostで接続するのはちょっとアレなんで、開発用ドメインを勝手に用意してそこに接続する形にしたいんですよね。

その開発用ドメインというのが今回でいうところのbo-devドメインです。これはわりと自由に決められるのでお好きな文字列をお使いいただけます。
自由に決められると言いつつ、多分これを見てるあなたにbo-devは使えないかもしれませんが。は?

というのもですね、他の人が既にどこかで開発用ドメインを名前解決してたら使えないっぽいんですよね。bo-devは僕が名前解決しちゃったのでみなさんは使えないというわけです。
でももしかしたら使えるかも。DNSようわからんぽよ...
ちなみにdevは使えませんでした。残念でした〜

話が逸れましたね。名前解決するとかなんか物々しいこと言ってますが、そんなに難しいことじゃありません。ローカルPCのhostsファイルに1行追加すればいいだけです

ローカルPCだからね!インスタンスのほうじゃないからね!間違えないでね!

  • Mac/Linuxの場合: nano /etc/hostsで開きます。(sudo必要かも)
  • Windowsの場合: Winキー+Rを押して出てきた入力欄にdriversと入力→etcフォルダに行ってその中のhostsを管理者権限で開く

末尾に以下のように入力して保存しまつ。

/etc/hosts
# 開発用ドメイン
xxx.xxx.xxx.xxx XXXXXX

なにやらxxxとか並んでますが**xxx.xxx.xxx.xxxにはインスタンスの外部IPを、XXXXXXには開発用ドメインを入力します**。bo-devの場合は

/etc/hosts
# 開発用ドメイン
114.51.4.19 bo-dev

みたいな感じです。

保存できたらブラウザからhttp://開発用ドメインに接続してみましょう。nginxの502画面が開くはずです。
502.png

ここで、外部IPは間違えてないのにうまく接続できなかったら残念ながらそのドメインは使えません。別のドメインをhostsファイルに書きましょう。

そしてこれでようやく準備が整いました。長かったぜベイベー

6. フロントエンド開発するぜ!

ぶっちゃけあとはローカルで開発するときの感覚と変わりないです。Node.js入れてyarn入れて2create-xxx-appしてっていういつもの流れですね。

今回は試しにNext.jsやってみますね。

最初にNode.jsのバージョン変えたりしたいのでnvm入れます。

↓nvmの最新バージョンのインストールスクリプトはこちらから↓
https://github.com/nvm-sh/nvm#install-script

以下のcurlはバージョンが古い可能性があるので最新バージョンのインストールスクリプトをご使用くだせえ

$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
$ source ~/.bashrc
$ nvm ls-remote # インストールできるバージョンの確認
$ nvm install v14.18.0 # 現時点の良さげなバージョン入れました
$ node --version # Node.jsが入ってることの確認
$ npm install --global yarn # グッバイnpmお前のことは忘れねえぜ

yarn入れるとこまでです。特別なことは特にやってないですね。

それではここでは~/projects以下にNext.jsプロジェクトを展開したいと思います。この辺はお好みですね

$ mkdir ~/projects
$ cd ~/projects
$ yarn create next-app demo --typescript

いにしゃらいず終わったらフォルダをプロジェクトのトップのところで開き直しましょう。ここでは~/projects/demoですね。

これで こうして こうじゃ!
1.png 2.png 4.png

フォルダが開けたらいつも通りターミナルも開いておきましょう。これで開発プロジェクトを開くのも容易になったZOY!
next_project.png

したらyarn devして開発サーバーを立ち上げましょう。
compiled successfullyになったらさっき502になってたhttp://開発用ドメインにアクセスし直してみましょう。
welcome.png

成し遂げたぜ。

盛り上がってきたのでちょっとタイトル変えてみましょう。

pages/index.tsx
        <h1 className={styles.title}>
-          Welcome to <a href="https://nextjs.org">Next.js!</a>
+          Welcome to <a href="https://nextjs.org">成し遂げたぜ。</a>
        </h1>

ふおおお.png

ふおおおおおおおおおお変更がすぐ反映されてりゅうううううううううううううううううう

このように、**クラウド環境でもHMRでの開発が可能です!**スゴイデスネ
あとは煮るなり焼くなり好きに開発していきましょう。

注意点

インスタンスは再起動するたびに外部IPが変わります。なので、起動する度に~/.ssh/config/etc/hostsを書き換える必要があります

毎回ファイル開いて変えるのもめんどいんで、僕はコマンドラインから$ devip xxx.xxx.xxx.xxxってすると、~/.ssh/config/etc/hostsの中身が入力したIPアドレスに変わるようにしてます。
具体的にはTypeScriptでスクリプト書いて.zshrcでエイリアス設定してる感じです。
スクリプトはこんな感じ↓

src/index.ts
import { readFileSync, writeFileSync } from 'fs';

(() => {
  if (process.argv.length <= 4) {
    console.log('引数ねンだわ');
    return;
  }
  const [, , hostTitle, domain, IP] = process.argv;
  
  const etcReg = new RegExp(`^[0-9|\\.]+[\\s]+${domain}$`);
  const hostsLines = readFileSync('/etc/hosts', 'utf-8')
    .split('\n')
    .map((text) => {
      if (etcReg.test(text)) {
        return `${IP} ${domain}`;
      }
      return text;
    });
  writeFileSync('/etc/hosts', hostsLines.join('\n'));
  
  type ConfigLines = [string[], boolean];
  const configFilePath = '/Users/bo-yakitarako/.ssh/config';
  
  const [configLines] = readFileSync(configFilePath, 'utf-8')
    .split('\n')
    .reduce(
      ([lines, canRewrite], text) => {
        if (canRewrite && text.includes('HostName')) {
          const spaces = [...Array(text.indexOf('HostName') + 1)].join(' ');
          return [[...lines, `${spaces}HostName ${IP}`], false] as ConfigLines;
        }
  
        const reg = new RegExp(`^[\\s]*Host ${hostTitle}$`);
        const isUpdate = canRewrite || reg.test(text);
        return [[...lines, text], isUpdate] as ConfigLines;
      },
      [[], false] as ConfigLines
    );
  
  writeFileSync(configFilePath, configLines.join('\n'));
  
  console.log(`${IP}に書き換えといたわよ`);
})();
$ ts-node ./src/index.ts hostTitle domain IP

みたいに使います。(実際にはコンパイルしてます)

  • hostTitle: ~/.ssh/configで作った設定の名前
  • domain: 開発用ドメイン
  • IP: インスタンスの外部IPアドレス

hostTitledomainを指定してIPアドレスだけコマンドライン引数にするという形でエイリアスを作ってます。

~/.zshrc
alias devip='(){node ~/Desktop/Node/ipreset/build/index.js bo-dev bo-dev $1}'

おわりに

思ったより長くなってしまいましたが、これにてクラウド開発環境の構築は完了です。

ただまだできていないことがあります。httpsでの接続です。
これまたかなり曲者だったので、気が向いたらまた別で記事にしようと思います。

ほいじゃさいなら〜

  1. パスフレーズを設定しても、他で使ってるパスワードを使い回したり、強固なパスフレーズをローカルに保存しておくとかしたら意味ないです。SSH接続時に毎回パスフレーズ聞かれるようになって正直めんどいので今回は無くてヨシ!

  2. deyarn?知らない子ですね...

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?