Visual Studio CodeからCloud9に接続して開発する


AWS Cloud9

AWSのサービスとなって早くも数年が経過するCloud9ですが、気軽に開発環境を立ち上げてすぐに壊すことができたり、ペアプログラミングができたりと便利なサービスです。

最近ではAWSの公式ハンズオンなどでも利用されることがよくありますので、各種セミナーを受講した方の中にも触ったことがある人は多いのではないでしょうか。

AWS Cloud9 は、ブラウザのみでコードを記述、実行、デバッグできるクラウドベースの統合開発環境 (IDE) です。これには、コードエディタ、デバッガー、ターミナルが含まれています。Cloud9 には、JavaScript、Python、PHP などの一般的なプログラム言語に不可欠なツールがあらかじめパッケージ化されているため、新しいプロジェクトを開始するためにファイルをインストールしたり、開発マシンを設定したりする必要はありません。Cloud9 IDE はクラウドベースのため、インターネットに接続されたマシンを使用して、オフィス、自宅、その他どこからでもプロジェクトに取り組むことができます。また、Cloud9 では、サーバーレスアプリケーションを開発するためのシームレスなエクスペリエンスが提供されており、リソースの定義、デバッグ、ローカルとリモートの間でのサーバーレスアプリケーションの実行の切り替えを簡単に行えます。Cloud9 を使用すると、開発環境をすばやくチームと共有し、ペアプログラミングを行って互いの入力をリアルタイムで追跡できます。

引用:AWS Cloud9

ローカルマシンのVSCodeを使いたい

そんな便利なCloud9ですが、「普段に近い環境で使いたい」や「異動したばかりで開発専用機がまだないけど研修は先輩と同じIDEでやってみたい」など、Cloud9とVSCodeのメリットを両取りできるような使い方ができれば良いのになという声も社内からちらほら。

そこで今回は手元のローカルマシンのVisual Studio Code(VSCode)からRemoteSSHでCloud9に接続し、さらにもう少し手を加えてもう少しだけ便利に使ってみたのでご紹介します。

Cloud9およびAWSにおける設定

今回は新しいEC2インスタンスでCloud9を起動しました。

ちなみにCloud9を起動するとCloud Formationが動いてAMIからEC2が立ち上がっていることがわかります。「VSCodeからSSH接続するならこのAMIで作ったEC2でいいじゃん」というのは今回はなしにしましょう。

外部からSSHで接続するので、セキュリティグループの設定をしておきましょう。
当該EC2のセキュリティグループの設定を開いて、SSHを許可しておきます。
社内のネットワークからのみ接続を許可するためソースのアドレスを絞って設定するなど、自分の環境に合ったルールに合わせましょう。


ローカルマシン側の設定

SSHキーペアの作成

まずはSSHで接続するのでキーペアを作っておきましょう。
一般的なWindowsのPCが社用PCというシチュエーションを想定して、PowerShellでの作成方法を以下に示します。
$ ssh-keygen -t ed25519

このようにして作った公開鍵(id_ed25519.pubなど)の中身をCloud9のIDEで、~/.ssh/authorized_keysの最終行に貼り付けておきます。



VSCodeでRemoteSSHのインストール

Remote - SSHをインストールしましょう。




VSCode上でSSHの設定を開きます。

以下はconfigファイルの例です。このあとサンプルアプリケーションでWebサーバを8080番ポートで立ち上げてローカルのブラウザで見てみますのでポートフォワードの設定もしています。
# Read more about SSH config files: https://linux.die.net/man/5/ssh_config
Host Higtat_on_Cloud9
    HostName (EC2のIPアドレス)
    User ec2-user
    Port 22
    IdentityFile C:\Users\hogehoge\.ssh\id_ed25519_cloud9など(秘密鍵のパス)
    LocalForward   8080 localhost:8080 

この状態でリロードボタンを押して接続することで、SSH接続に成功します。
パスフレーズを設定している場合は入力してください。
以下のようにディレクトリも見えています。



ウェブアプリケーションの開発などをする場合、フロントエンドの確認でlocalhostのポートをブラウザで見たいこともあると思います。
今回はdockerでApacheサーバを動かしてみます。
$ docker run -d -p 8080:80 httpd:latest



これでCloud9上のアプリケーションをクライアントPCのブラウザで確認することができました。



もう少し便利にする

ここまででVSCodeからCloud9に接続することはできたので、ほとんどの目的は達成できたわけですが
「SSH接続だけだとEC2がシャットダウンしちゃいました」
「毎回Cloud9のコンソールから起動するの面倒くさい」
などの声が聞かれます。

SSH接続中にEC2が停止するのを防ぐ

これはCloud9のEC2環境ではデフォルトではIDEの接続が切れてから30分でシャットダウンする設定によるものです。

これがEC2上ではどのような挙動をしているのか、もう少し詳しく見てみます。
EC2上の~/.c9/stop-if-inactive.shのスクリプトを眺めてみると、自動でシャットダウンを実行するスクリプトだということがわかります。
このスクリプトは別ファイルで設定された停止までの時間を読み取り、その時間が経過後にシャットダウンされるようにシャットダウンコマンドを実行しています。一方でvfs-workerというプロセスがある場合はシャットダウンを停止するような記述があり、ブラウザからIDEにアクセスしている間は、このプロセスが存在するためシャットダウンがキャンセルされ、インスタンスは動き続けます。


一方で、本記事の方法でSSH接続している場合は上記プロセスは存在しないため、デフォルトのままでは30分後にインスタンスは停止してしまいます。

これを防ぐにはSSHのプロセスを探してシャットダウン停止条件に追加してやればいいだけなのですが、AWSの公式ブログに同様の手順を紹介する記事がありました。
# Save a copy of the script first
$ sudo mv ~/.c9/stop-if-inactive.sh ~/.c9/stop-if-inactive.sh-SAVE
$ curl https://raw.githubusercontent.com/aws-samples/cloud9-to-power-vscode-blog/main/scripts/stop-if-inactive.sh -o ~/.c9/stop-if-inactive.sh
$ sudo chown root:root ~/.c9/stop-if-inactive.sh
$ sudo chmod 755 ~/.c9/stop-if-inactive.sh

ここで取得したシェルスクリプトの差分を見てみると、以下のVSCodeからの接続プロセスの有無をチェックする関数が追加され、これがシャットダウン判定の条件に追加されていることがわかります。
is_vscode_connected() {
    pgrep -u ec2-user -f .vscode-server/bin/ -a | grep -v -F 'shellIntegration-bash.sh' >/dev/null
}

これにてSSH接続中にEC2がシャットダウンするのを防ぐことができました。

VSCodeのtasksでEC2を起動する

「毎回コンソールからEC2を起動するのは面倒くさい」
と言った声への対応方法は様々あると思いますが、今回はVSCodeのtasksを使ってEC2を起動するスクリプトを実行してみましょう。

今回はローカルマシンにAWS CLIがインストール済みという前提で、さらにアカウントの切り替えもしないという簡易なスクリプトでご紹介します。

まずは手元でEC2の状態を確認し、停止していたら起動するスクリプトを作成します。
参考までにWindows用にPowerShellスクリプトと、LinuxやMac用のシェルスクリプトを紹介します。

StartEC2Instance.ps1
# インスタンスID
$instanceId = "(起動したいインスタンスのID)"

 # インスタンスの状態を取得
$instanceState = $(aws ec2 describe-instances --instance-ids $instanceId --query "Reservations[*].Instances[*].State.Name" --output text)

 # インスタンスの状態によって処理を分ける
if ($instanceState -eq "running") {
    Write-Output "The instance is already running."
} elseif ($instanceState -eq "stopped") {
    Write-Output "The instance is stopped. Starting the instance now."
    aws ec2 start-instances --instance-ids $instanceId
    aws ec2 wait instance-running --instance-ids $instanceId
    Write-Output "The instance has been started."
} else {
    Write-Output "The instance is in a $instanceState state."
}


StartEC2Instance.sh
#!/bin/bash

# インスタンスID
instanceId="(インスタンスID)"

# インスタンスの状態を取得
instanceState=$(aws ec2 describe-instances --instance-ids $instanceId --query "Reservations[*].Instances[*].State.Name" --output text)

# インスタンスの状態によって処理を分ける
if [ "$instanceState" == "running" ]; then
    echo "The instance is already running."
elif [ "$instanceState" == "stopped" ]; then
    echo "The instance is stopped. Starting the instance now."
    aws ec2 start-instances --instance-ids $instanceId
    aws ec2 wait instance-running --instance-ids $instanceId
    echo "The instance has been started."
else
    echo "The instance is in a $instanceState state."
fi

これらのスクリプトを手元のPowerShellやbash/zshで実行すると、EC2が起動することを確認してください。

これをVSCodeで実行するためのスクリプトを書いてやります。
VSCodeの
Tasks: Configure Task
をクリックするとtasks.jsonファイルの編集画面が開きます。



そこにtaskを記述してやりましょう。labelは何でも良いのでわかりやすい名前を付けておきましょう。以下はWindowsの場合の例です。

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "start Cloud9",
            "type": "shell",
            "command": "C:\\Scripts\\CodeToCloud9\\CodeToCloud9.ps1"
        }
    ]
}

保存が完了すると、
Tasks: Run Task
で先ほどのタスクのラベル(上記例だとstart Cloud9)が出てきますので
“Continue without scanning the task output”
でtaskを実行します。



無事結果が画面に表示されますのでこれでVSCode1つだけでEC2の起動もできるようになりました!


まとめ

VSCodeからCloud9のEC2環境に接続することができました。
身軽な開発環境をカスタマイズして使いたい方にも良い方法かと思います。
また、VSCodeにはSSHのセッションが切れないような機能があるため、EC2起動したままにならないように注意することが必要です。

Next Post Previous Post