ホエールテック株式会社 ホエールテック株式会社

  • ブログ

最小構成で始めるAWSデプロイ〜後編:EC2へのSSH接続からデプロイまで〜

遅くなりましたが、新年明けましておめでとうございます。
Webエンジニアのsimonです。

本年もしっかりとブログを更新していく予定ですので、ホエールテックをどうぞよろしくお願いいたします。

さて、本記事は前回投稿したこちらの記事の続きになります。

これまでの流れの整理

まずは、ここまでの流れを整理しましょう。

1.公開するアプリの作成

2.EC2サーバーの作成

3.EC2サーバーへのSSH接続 〜 デプロイ作業(本記事でやること)

今回はEC2に接続しデプロイ作業を行います。

コマンドによる作業がメインになりますので、前回よりも難しいかもしれませんが恐れずに頑張りましょう!

EC2サーバーへのSSH接続

まずは、作成したEC2サーバーにSSH接続します。

前回作成し、ダウンロードした秘密鍵(.pem)が必要になりますのでご用意ください。
秘密鍵はキーペアを新しく作成したタイミングで自動でダウンロードされていますので、ダウンロードフォルダにあるはずです。

※AWSから再度のダウンロードはできないようになっています
見当たらない場合、EC2インスタンスもしくはキーペアを再度作り直してからダウンロードしてください

まず最初に、ダウンロードした秘密鍵のあるディレクトリを移動します。

(※今回は「Downloads」に秘密鍵がある前提で進めますが、業務などでリモートホストにSSH接続する際にはわかりやすい場所に「Key」フォルダを作ってそこに秘密鍵を保管するようにしてください)

ターミナルを起動し、lsコマンドを実行してください。

ls

以下はカレントディレクトリにてlsコマンドを実行した場合の参考例になります。

秘密鍵のある場所に移動します。

cd Downloads

その後、lsコマンドを実行するとダウンロードした秘密鍵(.pem)が表示されるはずです。

次に、以下のコマンドを実行してください。

chmod 400 my-vue-app-key.pem

このコマンドを実行すると、秘密鍵が自分にしか読めない状態になります。

要素意味補足
chmodファイルの権限を変更するコマンド
400パーミッション(※)この数字が「400」の場合は、
所有者だけが「読む」ことを許可する設定となる

(表の補足)
パーミッション(※)について
→ファイル等の権限に関する設定で、以下のように3桁の数字で「誰が」「何をできるか」を表します

「誰が」
対象
1桁目所有者
2桁目グループ
3桁目その他
「何をできるか」(ベースの数字)
数字権限
4読む(read)
2書く(write)
1実行(execute)

上記の数字の組み合わせで(足し算)、以下のように実際の権限を設定できます。

「何をできるか」(実際の権限)
数字要素意味
74 + 2 + 1読む・書く・実行
64 + 2読む・書く
54 + 1読む・実行
44読むのみ
0なし何もできない


例えば「chmod 644 index.html」とした場合は、index.htmlを
所有者:読み/書きができる
グループ:読むことのみできる
その他ユーザー:読むことのみできる
という権限に設定する、という意味になります。

パーミッションの設定が終わったら、以下のコマンドを実行してEC2サーバーに接続してください。

ssh -i my-vue-app-key.pem ec2-user@<パブリックIP>

コマンドの意味は以下の通りです。

要素意味補足
sshSSH クライアントコマンド
-iiidentity file オプション使用する秘密鍵を指定
ec2-userユーザー名接続先OSのログインユーザー
<パブリックIP>接続先EC2インスタンスの「パブリックIPアドレス」


パブリックIPは、作成したインスタンス概要の以下の箇所からコピーできます。


SSH接続の際に

This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?


と聞かれたら、yesを入力してください。

成功すると、以下のような画面になります。

ここが 「AWS上のサーバーの中」 です。

💡SSH接続で、「Permission denied (publickey)」が出た時

原因は概ね以下のどれかです

・pemファイルが違う(別インスタンスの鍵orファイル名のスペルミス)
・ユーザー名が違う
・インスタンス作成時にそのpemを紐づけてない

🔧 確認

EC2 → 対象インスタンス → 「詳細」に キーペア名 が出ているので、それと手元のpemが一致してるかチェック。

ここまでをおさらいしておきましょう。
今は
「まっさらなAmazon Linux 2023のPCを1台借りて、
黒い画面(ターミナル等)で直接操作している」
状態です。

ここから
・OSの初期化
・Nginxのインストール
・アプリをgit管理下におく

といったことをやっていきます。
普通のLinuxサーバーをデプロイできるWebサーバーに育てる作業です。

Nginxのインストール

まずはパッケージを最新化します。

sudo dnf update -y

このコマンドはそれぞれ以下のような要素で成り立っています。

要素意味
sudo・コマンドを管理者権限で実行する際に使用する
dnf update・dnfはRedHatLinux系のパッケージマネージャー
updateコマンドで、インストール済みパッケージを、リポジトリ上の最新バージョンに合わせて更新する
-y・実行して良いかの確認をスキップし、全自動で実行するオプション
(今回は学習目的の為、dnf update時の確認をスキップしています)

次に、Webサーバー(として動作するソフト)である Nginx をインストールします。

以下のコマンドを順番に実行してください。

sudo dnf install -y nginx 

sudo systemctl start nginx 

sudo systemctl enable nginx

これで、Nginxをインストールし、さらに起動することができました。

「sudo systemctl enable nginx」によって、サーバーの再起動時も自動でNginxが

立ち上がるように設定されています。

この状態で、
ブラウザから

http://(EC2のパブリックIP)」

にアクセスすると
Welcome to nginx! が表示されます。

以下のような画面が表示されれば、ここまではバッチリです!

Node.js、npm、gitのインストール


GitHubに置いたVueアプリをクローンします。

まずは、nodejs、npm、gitをインストールしてください。

sudo dnf install -y nodejs

sudo dnf install -y npm

sudo dnf install -y git

上のような画面になっていればインストールは完了です。
それぞれ以下のような役割になります。

ツール役割
Node.js・JavaScriptの実行環境
 →ビルド処理を動かすために必要
npm・ライブラリ管理
 →Vue/Viteの依存関係を揃えるために必要
git・ソースコードのバージョン管理
 →GitHubからコードを取得・更新するために必要

それぞれのツールがきちんとインストールされたかを確かめるために、バージョンを確認します。

git --version

「git version 2.43.0」のようなバージョン情報が表示されるはずです。

今回gitのみを書いていますが、「(ツールの略称コマンド名) -v/–version」といった形で他のツールでも同じです!(–versionと-vどちらでも同じになります)

git clone https://github.com/xxx/my-vue-app.git 

以前作成したgithub上のリモートリポジトリにpushしているコードをEC2サーバーに用意します。

「xxx」:自分のgitのアカウント名
「my-vue-app.git」:リポジトリ名
を記入してください。

npm install、npm run build

cd my-vue-app 

npm install 

npm run build


「npm install」でアプリを実行するのに必要なライブラリを一通り揃え、「npm run build」でこれらを本番環境向けにビルド(開発用に書かれたソースコードを、実際に実行・配信できる形式へ変換・整理する処理)し、マシンが実行できる状態にします。

エラーの対処について

npm installの際に以下のようなエラーが出たかと思います。

[ec2-user@ip-xxx-xx-x-x my-vue-app]$ npm install
npm warn EBADENGINE Unsupported engine {
npm warn EBADENGINE   package: '@vitejs/plugin-vue@6.0.3',
npm warn EBADENGINE   required: { node: '^20.19.0 || >=22.12.0' },
npm warn EBADENGINE   current: { node: 'v18.20.8', npm: '10.8.2' }
npm warn EBADENGINE }
npm warn EBADENGINE Unsupported engine {
npm warn EBADENGINE   package: 'vite@7.3.0',
npm warn EBADENGINE   required: { node: '^20.19.0 || >=22.12.0' },
npm warn EBADENGINE   current: { node: 'v18.20.8', npm: '10.8.2' }
npm warn EBADENGINE }

added 35 packages, and audited 36 packages in 2s

これは「このパッケージは
Node 20.19以上 or 22.12以上で動く前提で作られている。
でも今の環境は Node 18.20.8。」

といった内容になります。

Vite(+ plugin-vue)が Node 20.19+ か 22.12+ を要求しているが、でもEC2には最初 Node 18.20.8 が入っていた。これが原因で依存関係が噛み合わない状態になっています。

これはEC2のバージョンであるAmazonLinux2023のデフォルト設定によるものとなります。

そこで、現在のNodeを削除し、Node20系を入れる作業を行います。

sudo dnf remove -y nodejs nodejs-npm nodejs-libs

curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -

sudo dnf install -y nodejs
node -v 

rm -rf node_modules package-lock.json
npm install

npm run build

上記では、以下のようなことをやっています。

① バージョン違いの Node.js を削除
(sudo dnf remove -y nodejs nodejs-npm nodejs-libs)

② Node.js 20 を使えるように設定変更
(curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -)

③ Node.js を再インストール・確認
(sudo dnf install -y nodejs / node -v)

④ 以前の依存関係ファイルを削除
(rm -rf node_modules package-lock.json)

⑤ 依存関係を再構築・ビルド
(npm install → npm run build)

さて、上記のコマンドの実行により、今度は画像のように、Node.jsでバージョン20系を入れることができ、これによりnpm install、npm run buildが成功したことがわかるかと思います。

ここまでが、環境構築等のデプロイの準備になります。

デプロイの核になるのはこの後の箇所になります。

デプロイ作業

ここでのデプロイは「Vue の build成果物(静的ファイル)をNginxが配信する場所へ置く」ことを意味します。

これにより、不特定多数の人に自分のWebページにアクセスしてもらい、みてもらうことができるようになるためです。

cd dist
ls
# assets index.html vite.svg

ls -la /usr/share/nginx/html

# (必要に応じて)Nginxが静的ファイルを読めるように、ディレクトリ/ファイルの権限を確認
多くの場合はデフォルトで問題ないが、コピー手順や権限状態によっては調整が必要
sudo chown -R root:root /usr/share/nginx/html
sudo chmod -R 755 /usr/share/nginx/html
sudo systemctl restart nginx

curl -s http://localhost/ | head -n 30

先ほどのnpm run buildにより dist ディレクトリが生成されています。
これは、元のsrcディレクトリ(vueファイル等が含まれます)の中身をビルドした成果物であり、これが今回世界に公開するものの中身となります。

ここのコマンドですが、全体としては以下のようなことをやっています。

———————————————————————————————-

①Vue のビルド成果物(dist)の中身を確認
→assets index.html があればOK

②Nginx が実際に公開しているディレクトリの権限設定等の確認
→その他のユーザー(Nginxもここに含まれる)が読み取りができる設定ならOK

※もし、Nginxが読めない状態ならNginx が読めるように、権限設定を修正
→Nginx を再起動して設定・状態を反映

③(ブラウザではなく)サーバー内部から HTTP 配信を確認

———————————————————————————————-

実際の結果をみると、おそらく以下のようになっているのではないでしょうか?

htmlファイルのその他ユーザーにrが設定されていることがわかります

ここまでで、元からあるhtmlファイルがきちんと読み取れることがわかります。


この段階では「curl -s http://localhost/ | head -n 30」の実行結果は以下のようになっていると思います。

デフォルトのNginxのhtmファイルですね。

これを、Nginxが公開場所と決めているディレクトリに置くことで、デプロイができます。



Nginxの公開ディレクトリに配置

Nginxの公開先は以下です。

/usr/share/nginx/html

既存のファイルを退避し、
Vueの dist をコピーします。

sudo mv /usr/share/nginx/html /usr/share/nginx/html.bak

sudo mkdir -p /usr/share/nginx/html

sudo cp -r ./* /usr/share/nginx/html/

curl -s http://localhost/ | head -n 30


🔹上記コマンドでは、

①今までのWebファイルを消さずに保管(バックアップ)

②空の公開ディレクトリを作り直す
(①のmvにより、「/usr/share/nginx/html」→「/usr/share/nginx/html.bak」と名称が変更され、公開ディレクトリはなくなっています)

③新しいビルド成果物をそこに配置する

④中身を再度確認

といったことをやっています。

「-p」は、途中の階層ディレクトリがなくてもまとめて作る、といった意味です。
また、sudoが全てについていますが、これは/usr配下は一般ユーザーに書き込み権限がない領域であるためです。他に、/varや/etcなども同様です。
試しにsudoなしで実行してみてください、「permission denied」が表示されるかと思います。

さて、今回の作業で言えば
「sudo cp -r ./* /usr/share/nginx/html/」
上記がデプロイの肝になります。

要素種類意味ここでの役割
cpコマンドcopy(コピー)ファイルを別の場所へ複製する
-rオプションrecursive(再帰的)フォルダと中身をすべてコピーする
./*コピー元カレントディレクトリ配下すべてdist 内の全ファイル(index.html, assets など)
※前の流れで、distがカレントディレクトリになっている
/usr/share/nginx/html/コピー先nginx の公開ディレクトリ世界に公開される場所

これにより、作成したWebページが世界に公開されたことになります!

一通り実行したあとの「curl -s http://localhost/ | head -n 30」の結果が、画像のように先ほどと変わっているのがわかるでしょうか?

実際に確認してみましょう。

ブラウザで、再度以下にアクセスします。

http://(EC2のパブリックIP)

最初は Nginx の初期画面がキャッシュされて表示されることがありますが、
ハードリロード(Cmd + Shift + R) を行うと、
Vueアプリが表示されます。


(IPアドレスは伏せていますが、ブラウザのレイアウトやcountボタンが押された形跡から、これがデプロイされたWebページ上のものであることがおわかりいただけると思います)
無事デプロイ完了です!

(余談)

実は、この後「今度、アプリのソースコードを更新した後で再度デプロイするには?」など、気になるテーマはあるのですが、今回はここまででご容赦ください‥
デプロイは、自動化や品質管理等、テーマが広く深い分野ですので、みなさまもぜひ学ばれてみてください。


終わりに

前回と今回に渡り

・AWSアカウント作成
・EC2起動
・SSH接続
・Nginx構築
・Vueアプリのデプロイ

という一連の流れを、
できるだけシンプルな構成 で体験しました。

最後まで読んでいただき、ありがとうございました。

参考サイト

初心者向け】 基本のLinuxコマンド一覧!操作別に紹介|Udemy メディア

【Node.js入門】npmとは?パッケージを管理するnpmの基礎的なコマンド一覧 │ TechMania

simon
simon
GPTをこよなく愛するWebエンジニア
初級Webエンジニアsimonです。

生成AIが大好き。休日もChatGPT、Gemini、Grokたちと戯れています。

最近GPTに助言をもらいながら2ヶ月で6kgのダイエットに成功。

以前の趣味は読書で、昨年末に銀河英雄伝説の文庫本を購入し綺麗に部屋に飾っています。
いつになったら読むのか。。。
採用情報
お問い合わせ