はじめに
こんにちは、Shioです。
インフラ学習の一環として、自作のGoアプリケーションをAWSにデプロイしました。
サーバーにはApacheを利用しましたが、個人的に設定が大変でした💦
PHPやPythonのようなインタプリタ言語は、Apacheのモジュール(例: mod_php
や mod_wsgi
)で簡単にサポートされます。しかし、Goはスタンドアロンで動作するバイナリのため、Apacheのモジュールでは直接対応できません。そのため、今回はApacheをリバースプロキシとして設定し、公開しました。
本来、リバースプロキシには軽量かつシンプルなNginxがよく選ばれますが、今回は認証の学習も目的として、Digest認証を標準でサポートするApacheを使いました。
本記事が少しでも皆さんのお役に立てれば嬉しいです🙇!
環境構成
- サーバー: AWS EC2(HTTPアクセスがセキュリティグループで許可されていることが前提)
- OS: Amazon Linux 2023 AMI
- Webサーバー: Apache
-
アプリケーション: Go言語APIサーバー(フロントエンドは用意していません)
- Dockerfileは使用せず、アプリケーションを転送後、直接ビルドしました。
-
データベース: SQLite(簡単に動作確認を行うため採用)
※ 本記事では、アプリケーションで使用するデータベースの設定や動作には触れません。
リモートサーバーにログインした状態から手順を開始します👀
1. 基本パッケージのインストール
Apache HTTPサーバーのインストール
httpd
はApache HTTP Serverのパッケージ名です。-y
オプションは全ての問い合わせに「yes」として応答します。
sudo yum install httpd -y
必要なモジュールの確認(proxy関連)
以下のコマンドで現在ロードされているApacheモジュールを確認し、mod_proxy
と mod_proxy_http
があることを確認します。
httpd -M | grep proxy
出力例:
proxy_module (shared)
…
proxy_http_module (shared)
…
-
mod_proxy
: Apacheをリバースプロキシとして動作させるために必要なモジュール -
mod_proxy_http
: HTTPリクエストをリバースプロキシとして処理するために必要なモジュール
Go言語のインストール
sudo yum install golang -y
2. Apacheの設定
リバースプロキシの設定
Apache設定ファイル(/etc/httpd/conf/httpd.conf
)に以下の内容を追加します。
⚠️ 管理者権限でファイルを開き編集します。
sudo vim /etc/httpd/conf/httpd.conf
以下の設定を追加:
<VirtualHost *:80>
ServerName example.com # EC2のパブリックIPやドメイン名に変更
ProxyPreserveHost On
# /v1/ へのリクエストをGoアプリケーションへ転送
ProxyPass /v1/ http://127.0.0.1:8080/v1/
ProxyPassReverse /v1/ http://127.0.0.1:8080/v1/
</VirtualHost>
設定の詳細
-
<VirtualHost *:80>
ポート80で受けた全リクエストに対して、この仮想ホストの設定を適用します。*
は全IPアドレスを意味します。 -
ServerName example.com
仮想ホストの対象となるIPアドレスまたはドメインを指定します。 -
ProxyPreserveHost On
クライアントからのリクエストヘッダーのHost
フィールドをそのままGoアプリケーションに渡します。 -
ProxyPass /v1/ http://127.0.0.1:8080/v1/
Apacheが受け取った/v1/
へのリクエストをローカルの8080番ポートにあるGoアプリケーションへ転送します。 -
ProxyPassReverse /v1/ http://127.0.0.1:8080/v1/
GoアプリケーションからのレスポンスでLocation
ヘッダー等が適切に修正されるようにします。
Apacheの起動と有効化
設定ファイルの構文チェックを行います。
sudo httpd -t
Syntax OK
と表示されたら、Apacheを起動し、サーバー起動時に自動的にApacheが起動するよう設定します。
sudo systemctl start httpd # Apacheの起動
sudo systemctl enable httpd # 自動起動を有効化
3. Goアプリケーションのデプロイ
アプリケーションの転送
ローカルPCからEC2インスタンスにアプリケーションを転送します。scp
コマンドを使用します。
scp -i <秘密鍵> -r ./myapp ec2-user@<EC2のIP>:/home/ec2-user/
コマンドの意味
-
scp
: セキュアコピーコマンド -
-r
: ディレクトリを再帰的にコピーするオプション -
-i <秘密鍵>
: 秘密鍵を指定 -
./myapp
: ローカルのディレクトリ -
ec2-user@<EC2のIP>
: リモートのEC2インスタンスのユーザー名とIPアドレス -
/home/ec2-user/
: 転送先ディレクトリ
転送が成功したら、再度EC2インスタンスにSSHでログインし、転送されたディレクトリが確認できるはずです👀
Goアプリケーションのビルドと実行
1. アプリケーションのビルド
アプリケーションのソースコードがあるディレクトリに移動して、ビルドします。
cd myapp
go build -o myapp main.go
2. アプリケーションの実行
ビルドしたアプリケーションをバックグラウンドで実行します。
./myapp &
&
を付けることでバックグラウンド実行されます。
ブラウザやcurlコマンドでアプリケーションが問題なく動作していることを確認します👀
4. Goアプリケーションのサービス化
バックグラウンド実行は一時的なものなので、サーバー再起動後も自動でアプリケーションを起動させるためにsystemd
を使用してサービスとして設定します。その前に使用中の8080ポートを開放します👀
1. プロセスの確認
ps aux | grep myapp
2. プロセスの停止
プロセスIDを指定して停止します。
kill -9 PID
systemd
サービスの設定
現在ディレクトリ構成は以下のようになっています。
/home/ec2-user/myapp/ # アプリケーションのディレクトリ
├── myapp # 実行ファイル(Goアプリケーション)
├── go.mod # Goのモジュール設定ファイル
├── go.sum # Goのモジュールチェックサムファイル
└── その他の設定ファイル
サービスファイルを作成
systemdのサービスユニットファイルを作成し、以下の内容を貼り付けます。
sudo vim /etc/systemd/system/myapp.service
以下を記述:
[Unit]
Description=My Go Application
After=network.target
[Service]
ExecStart=/home/ec2-user/myapp/myapp # アプリケーションのパスを指定
WorkingDirectory=/home/ec2-user/myapp # アプリケーションがあるディレクトリ
Restart=always
User=ec2-user # 実行ユーザー
[Install]
WantedBy=multi-user.target
詳細
[Unit]
-
Description
: サービスの説明です。 -
After=network.target
: ネットワークが有効になった後に開始する設定です。
[Service]
-
ExecStart=/home/ec2-user/myapp/myapp
: 実行するバイナリのパスを指定します。 -
WorkingDirectory=/home/ec2-user/myapp
: アプリケーションがあるディレクトリを指定します。 -
Restart=always
: サービスが停止した場合に自動で再起動します。 -
User=ec2-user
: アプリケーションを実行するユーザーを指定します。 -
EnvironmentFile=/home/ec2-user/myapp/app/.env
: (必要に応じて)環境変数を含むファイルを指定します
サービスの起動と自動起動の有効化
1. systemd
の設定をリロード
sudo systemctl daemon-reload
2. サービスの起動と自動起動の有効化
sudo systemctl start myapp
sudo systemctl enable myapp
3. サービスのステータス確認
アプリケーションが正しく起動しているかを確認します。
sudo systemctl status myapp
成功していれば以下のようなステータスが表示されます。
● myapp.service - My Go Application
Loaded: loaded (/etc/systemd/system/myapp.service; enabled; preset: disabled)
Active: active (running)
5. トラブルシューティング
Apacheログの確認
Apacheのエラーログを確認
sudo tail -f /var/log/httpd/error_log
Goアプリケーションのログ確認
Goアプリケーションのsystemd
ログを確認
sudo journalctl -u myapp -f
遭遇したエラーと対処方法
ポート8080がすでに使用中
ポート8080を使用しているプロセスを特定して終了
sudo lsof -i :8080
sudo kill -9 <PID> # 使用中のプロセスID(PID)を指定して終了
Apacheの設定ファイルミス
Apacheの設定に誤りがないか構文チェック
sudo httpd -t
6. 注意事項
ここまで読んでくださりありがとうございます。本記事はあくまでGoアプリケーションをAWS上でデプロイするまでの手順になります。セキュリティ対策(SSL/TLSの設定やファイアウォール、アクセス制御)については触れていません🙇