はじめに
どうも、Shakkuです。
都内某高専情報科の3年生です。(2023/10/21時点)
以前、Go+Echo+GORM(mysql)+DockerでSession,JWT付きログインWebアプリというものを作成しました。
現状、自分のMacBookAirで起動してlocalhostでのみアクセスできる状態になっています。
そのため、作成したアプリで遊んでみたいときに毎回自分のMacBookでサーバーをたてて、同じLANに入って...という作業をしており、めんどくさいなーというのと、MacBookに負荷がかかるなーと毎回感じていました。
そんな時に近々再度AWSを触るタイミングがやってきたので、ちょっとした復習も兼ねて今回は自身で作成したこのアプリケーションをEC2にデプロイしてみました。
今回はお試しということで、費用をかけずに無料枠だけを使用してやってみました。
(高専の授業でAWSを触った際は、アベイラビリティーゾーン,パブリック/プライベートサブネット,IGW,ロードバランサ,ElasticIPなどなど、可用性がありセキュリティもちゃんとした構築を作っていましたが、配られた100ドルがどんどん減っていって悲しかったので、今回は無料枠だけの悲しい構築です...)
概要
今回の構築は以下のようなセキュリティガバガバで可用性のない貧乏構築です。
EC2回りだけ触りたいので、インターネットゲートウェイとかVPCとかサブネットとかはデフォルトのものを基本的に使っちゃってます。
AWSのコンソールへの登録やログイン方法に関しては省略しています。
今回は私は学校から配布されたAWS Academyのアカウントを使用していますが、通常のアカウントで構築する際は、アカウントを作成してから12ヶ月のみ無料枠を使用できるそうなのでご注意を。(https://aws.amazon.com/jp/free/?all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc&awsf.Free%20Tier%20Types=*all&awsf.Free%20Tier%20Categories=*all)
リージョンもどこでも問題なさそうではあるが、今回はデフォルトのバージニア北部を使用しました。
(追記:アクセス元のリージョンと異なるリージョンで作成すると、リージョン間の通信によって少量の料金が発生してしまうようです。今回使用しているAWSAcademyのLearner Labでは、us-east-1とus-west-2しか使用できないため、少量の料金が発生してしまっています。アメリカに移住するしかないか...)
そんなに!?意外と知らないAWSでお金がかかるポイント5選
構築
EC2作成
サービスからEC2を選択して、インスタンスからインスタンスを起動を選択する。
お好みの名前を入力し
マシンイメージ(AMI)はAmazon Linux
の無料枠のものを使用する。
インスタンスは無料枠のt2.micro
を使用する。(1CPU,1GBメモリなので、そのままだとDocker Composeを動かすには物足りないが、後程手を加える)
インスタンスに接続するためのキーペアを、新しいキーペアの作成から作成する。
作成したらダウンロードして、ダウンロードした秘密鍵を/.sshに移動して、パーミッションを設定しておく
$ cp ~/Downloads/echo-login-app-server-key.pem ~/.ssh/
$ chmod 400 ~/.ssh/echo-login-app-server-key.pem
ネットワーク設定から編集を押して、VPCはデフォルトのものを使っちゃう。
サブネットもデフォルトのものを使っちゃう(どのアベイラビリティーゾーンでも問題ないが、今回はus-east a1を使用した。)
パブリックIPは自動で割り当てしてもらう。
セキュリティグループを作成するを選択し、お好みの名前を入力
インバウンドルール(EC2へのアクセスを許可するポートやプロトコルの設定)を基本的なssh:20
HTTP:80
HTTPS:443
の他に、今回デプロイするプログラムで使用している8081
8082
ポートも入れておく。
基本的にはどこからでもアクセス許可しているが、apiで使用している8081
ポートは、アプリケーション内でしか使用しないため、自分のIPにしている。
ストレージはデフォルトのまま。
高度な詳細から、念の為終了保護を有効化
して間違えて吹っ飛ばさないようにした。
そして、インスタンスを起動!
インスタンスの一覧から、作成したインスタンスが緑の実行中になったら、起動完了。
EC2の環境構築
1.起動したEC2にsshする。
インスタンスの一覧から、起動したインスタンスのチェックボックスをクリックして、下の詳細をみてみると、パブリック IPv4 アドレス
というものがある。
そのIPへ以下のコマンドでsshした。
$ ssh -i ~/.ssh/echo-login-app-server-key.pem ec2-user@パブリックIP
2.Dockerのインストール
以下のコマンドを実行。
$ sudo yum install -y docker # インストール
$ sudo service docker start # 起動
$ sudo usermod -a -G docker ec2-user # ec2-userをDockerグループに入れる。(これによって、dockerコマンドを実行できる。)
3.Docker Composeのインストール
以下のコマンドを実行。
私のローカル環境のDocker Composeのバージョンがv2.18.1
だったので、このバージョンでインストールした。
$ sudo mkdir -p /usr/local/lib/docker/cli-plugins
$ sudo curl -SL https://github.com/docker/compose/releases/download/v2.18.1/docker-compose-linux-x86_64 -o /usr/local/lib/docker/cli-plugins/docker-compose
$ sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
$ docker compose version # バージョン確認
4.gitのインストール
以下のコマンドを実行
$ sudo yum install git
5.作成したプログラムのclone
今回デプロイするプログラムをGithubからcloneしてきた。
$ git clone https://github.com/Shakkuuu/echo-login-app
6.スワップメモリの増加
今回の肝であるスワップメモリの増加。
無料枠のt2.microでは、メモリが少なくDocker Compose実行時などのメモリを多く使用する処理を行うと落ちてしまう。(これでずっと起動できなくて悩んでた。)
そこで、スワップメモリを増やして落ちるのを回避する。
# 今回は2GBのスワップファイルを作成
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048
# スワップファイルに読み書き権限付与
sudo chmod 600 /swapfile
# スワップ領域のセットアップ
sudo mkswap /swapfile
# スワップ領域を有効化
sudo swapon /swapfile
# スワップ領域の確認
sudo swapon -s
実際にコマンドで確認してみると、しっかりメモリとして認識されていることがわかる。(以下は一部コンテナ起動済みの出力結果)
[ec2-user@ip-172-31-95-82 ~]$ sudo swapon -s
Filename Type Size Used Priority
/swapfile file 2097148 1792 -2
[ec2-user@ip-172-31-95-82 ~]$ free
total used free shared buff/cache available
Mem: 972188 549576 65836 1800 356776 279660
Swap: 2097148 1792 2095356
また、スワップを起動時に有効にするように追記する
$ sudo nano /etc/fstab
# 末尾に以下の一行を追加
/swapfile swap swap defaults 0 0
Docker Composeの実行
いよいよDocker Composeでアプリの起動!
docker compose up -d
で起動!
ちゃんと落ちないで起動できた。
[ec2-user@ip-172-31-95-82 echo-login-app]$ docker stats --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
111b2ee86291 echo-login-app-api 0.00% 66.25MiB / 949.4MiB 6.98% 96.9kB / 67.1kB 131MB / 222MB 12
2803a06ee682 echo-login-app-db-1 0.34% 195.7MiB / 949.4MiB 20.61% 44.4kB / 65.7kB 123MB / 211MB 38
dcdb4545dc45 echo-login-app-app 0.00% 61.71MiB / 949.4MiB 6.50% 33.8kB / 29.6kB 109MB / 211MB 12
同じLAN内でなくてもアクセスできた!
終わりに
今回は、無料枠のEC2にGoで作成したアプリケーションをデプロイし、Docker Composeで起動してみました。
自身のローカル環境でサーバーを起動せずとも、アプリケーションを使用することができるようになりました。
無料枠のインスタンスであるt2.microではメモリが足りず、Docker Composeを実行すると落ちてしまうため、スワップメモリを増加させることで、解決しました。
また、今回の構築ではパブリックIPアドレスを固定していないため、何かのタイミングでアドレスが変わってしまう可能性があったため、後日Elastic IPを使用して、パブリックIPアドレスの固定も行いました。
しかし、今年7月ごろにパブリックIPアドレスの料金体系に関して変更があったため、現時点はこの構築では料金がかからないが、2024年2月より料金が発生してしまう可能性があるため気をつけておきたいです。パブリック IPv4 アドレスの利用に対する新しい料金体系を発表 / Amazon VPC IP Address Manager が Public IP Insights の提供を開始
おまけ
プロキシの設定などで、8082ポートにリモートでアクセスできない時があったので、ポート転送を設定してみました。
今回はfirewalld
というツールを使用しました。
# インストール
$ sudo yum -y install firewalld
# 起動
$ sudo systemctl start firewalld
# 自動起動有効化
$ sudo systemctl enable firewalld
# 80ポートから8082ポートへのリダイレクト設定
$ sudo firewall-cmd --add-forward-port=port=80:proto=tcp:toport=8082
# 設定永続化
$ sudo firewall-cmd --runtime-to-permanent
# 設定確認
$ sudo firewall-cmd --list-all
...
forward-ports:
port=80:proto=tcp:toport=8082:toaddr=
...
これによって、ブラウザでポートを指定しなくても(デフォルトの80番ポートで)ページが表示されました!