はじめに
HerokuにCloud9をデプロイして無料オンラインIDEを使おうと頑張ってます。
その努力の経過をまとめています。
GithubもHerokuも知ってるよ。
過程は良いから、Dockerfileが早く見たい。って人は、GitHubに公開しているので、リンクを参照してください。
なぜ、始めたのか?
友人のAWS Cloud9が13ヶ月目に入り、お金がかかってきたので、無料でやる方法を模索していて思いつきました。
無料オンライン開発環境についてぐぐってみた
レガシーなCloud9のアカウントを持ってるなら、Cloud9使えばいいんですが、持っていない場合、、、
HTML, CSS, JSだけでいいなら、Thimbleが良さげ。
Pythonでデータの処理とか、機械学習系をするなら、Jupitor Notebookとか、Google Colabになるのかな。
JSONを返すだけとか、静的なファイルを置くだけなら、myjsonとか、GASがいいかも。
あと、オンラインのコンパイラとかは、言語ごとに探せばあるって感じですね。
やり方をググってみた。
ない。。。
Cloud9から、Herokuにデプロイする方法は引っかかるが、
HerokuにCloud9をデプロイする方法は見つからない。。。
具体的に何がしたいかというと、、、
とりあえず、思いついた方法、3つ
1. GithubにあるCloud9のリポジトリをフォークして、Herokuにデプロイ
2. Cloud9のDockerfileを使って、コンテナをHerokuにデプロイ
3. ローカルでCloud9を動かし、SSHトンネリング(ポートフォワーディング )でアクセスさせる
実現可能性は高いが、 オンプレ のサーバを置く時点で、無料ではない
1. GitHubからデプロイ
GitHubのアカウント 、Heroku のアカウント, CLIはすでに持っているものとして、話を進めます。
「なんだそれ?」ってひとは、上のリンクにアクセスするか、よしなにぐぐってください。
a. シンプルにフォークして、デプロイしてみる
Cloud9のGitHubページ にアクセスしてForkする
Herokuにアクセスして、Create new app をする
Create appを押す(App nameは入力しなくていい)
GitHubにつなぐ
Forkしたリポジトリを探して、Connectする
Deploy Branchする
すると、Buildが進んで、
“Your app was successfully deployed”と表示されたら、Viewをクリックする。
全然Successfullyじゃないじゃん。
アプリの設定ページに戻って、Activity → View build logをクリック
ログを見てみると
-----> Node.js app detected
-----> Creating runtime environment
NPM_CONFIG_LOGLEVEL=error
NODE_ENV=production
NODE_MODULES_CACHE=true
NODE_VERBOSE=false
-----> Installing binaries
engines.node (package.json): unspecified
engines.npm (package.json): unspecified (use default)
Resolving node version 10.x...
Downloading and installing node 10.14.1...
Using default npm version: 6.4.1
-----> Building dependencies
Prebuild detected (node_modules already exists)
Rebuilding any native modules
c9@0.1.0 /tmp/build_75f4baa91a3c7c165659cc801c15ba00/node_modules/c9
kaefer@0.1.0 /tmp/build_75f4baa91a3c7c165659cc801c15ba00/node_modules/kaefer
amd-loader@0.0.5 /tmp/build_75f4baa91a3c7c165659cc801c15ba00/node_modules/amd-loader
architect@0.1.11 /tmp/build_75f4baa91a3c7c165659cc801c15ba00/node_modules/architect
connect-architect@0.2.0 /tmp/build_75f4baa91a3c7c165659cc801c15ba00/node_modules/connect-architect
frontdoor@0.0.1 /tmp/build_75f4baa91a3c7c165659cc801c15ba00/node_modules/frontdoor
msgpack-js@0.1.5 /tmp/build_75f4baa91a3c7c165659cc801c15ba00/node_modules/msgpack-js
smith@0.1.22 /tmp/build_75f4baa91a3c7c165659cc801c15ba00/node_modules/smith
treehugger@0.0.2 /tmp/build_75f4baa91a3c7c165659cc801c15ba00/node_modules/treehugger
Installing any new modules (package.json)
added 183 packages from 273 contributors, removed 9 packages and audited 253 packages in 11.329s
found 40 vulnerabilities (11 low, 10 moderate, 18 high, 1 critical)
run `npm audit fix` to fix them, or `npm audit` for details
-----> Caching build
- node_modules
-----> Pruning devDependencies
audited 253 packages in 1.963s
found 40 vulnerabilities (11 low, 10 moderate, 18 high, 1 critical)
run `npm audit fix` to fix them, or `npm audit` for details
-----> Build succeeded!
-----> Discovering process types
Procfile declares types -> (none)
Default types for buildpack -> web
-----> Compressing...
Done: 39.6M
-----> Launching...
Released v3
アプリ名 deployed to Heroku
HerokuのCLIで heroku logs -- tail -a アプリ名
を実行して、ログをみると、
$ heroku logs --tail -a safe-shelf-96289
2018-12-07T04:04:02.738118+00:00 app[api]: Release v1 created by user ユーザー名
省略
2018-12-07T04:05:20.248779+00:00 heroku[web.1]: State changed from starting to crashed
2018-12-07T04:05:20.250837+00:00 heroku[web.1]: State changed from crashed to starting
2018-12-07T04:05:20.222517+00:00 heroku[web.1]: Process exited with status 1
2018-12-07T04:05:19.969827+00:00 app[web.1]:
2018-12-07T04:05:19.969850+00:00 app[web.1]: > c9@3.1.5000 start /app
2018-12-07T04:05:19.969851+00:00 app[web.1]: > node server.js
2018-12-07T04:05:19.969853+00:00 app[web.1]:
2018-12-07T04:05:20.124000+00:00 app[web.1]: internal/modules/cjs/loader.js:582
2018-12-07T04:05:20.124004+00:00 app[web.1]: throw err;
2018-12-07T04:05:20.124005+00:00 app[web.1]: ^
2018-12-07T04:05:20.124007+00:00 app[web.1]:
2018-12-07T04:05:20.124009+00:00 app[web.1]: Error: Cannot find module 'amd-loader'
省略
2018-12-07T04:05:20.130850+00:00 app[web.1]: npm ERR! code ELIFECYCLE
2018-12-07T04:05:20.131414+00:00 app[web.1]: npm ERR! errno 1
2018-12-07T04:05:20.133176+00:00 app[web.1]: npm ERR! c9@3.1.5000 start: `node server.js`
2018-12-07T04:05:20.133438+00:00 app[web.1]: npm ERR! Exit status 1
2018-12-07T04:05:20.133806+00:00 app[web.1]: npm ERR!
2018-12-07T04:05:20.134072+00:00 app[web.1]: npm ERR! Failed at the c9@3.1.5000 start script.
2018-12-07T04:05:20.134327+00:00 app[web.1]: npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
2018-12-07T04:05:20.158427+00:00 app[web.1]:
2018-12-07T04:05:20.158771+00:00 app[web.1]: npm ERR! A complete log of this run can be found in:
2018-12-07T04:05:20.159000+00:00 app[web.1]: npm ERR! /app/.npm/_logs/2018-12-07T04_05_20_136Z-debug.log
2018-12-07T04:05:10.873607+00:00 app[api]: Release v3 created by user ユーザー名
2018-12-07T04:05:12.000000+00:00 app[api]: Build succeeded
2018-12-07T04:05:10.895893+00:00 app[api]: Scaled to web@1:Free by user ユーザー名
2018-12-07T04:05:10.873607+00:00 app[api]: Deploy c4d1c59d by user ユーザー名
2018-12-07T04:05:26.277205+00:00 heroku[web.1]: Starting process with command `npm start`
2018-12-07T04:05:30.026512+00:00 heroku[web.1]: State changed from starting to crashed
2018-12-07T04:05:29.989756+00:00 heroku[web.1]: Process exited with status 1
2018-12-07T04:05:29.665053+00:00 app[web.1]:
2018-12-07T04:05:29.665073+00:00 app[web.1]: > c9@3.1.5000 start /app
2018-12-07T04:05:29.665075+00:00 app[web.1]: > node server.js
2018-12-07T04:05:29.665076+00:00 app[web.1]:
2018-12-07T04:05:29.856720+00:00 app[web.1]: internal/modules/cjs/loader.js:582
2018-12-07T04:05:29.856725+00:00 app[web.1]: throw err;
2018-12-07T04:05:29.856726+00:00 app[web.1]: ^
2018-12-07T04:05:29.856728+00:00 app[web.1]:
2018-12-07T04:05:29.856729+00:00 app[web.1]: Error: Cannot find module 'amd-loader'
2018-12-07T04:05:31.263257+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" 省略
なんかamd-loaderモジュールが無いのが問題らしいけど、ぐぐっても、いまいちどうしたらいいかわからん。
とりあえずローカル環境にCloud9をインストールしてみる。
$ git clone フォークしたリポジトリのURL
$ cd core/
$ scripts/install-sdk.sh
$ node server.js
できた。
そういや、install-sdk.sh
スクリプトって、herokuデプロイの時、実行してないな。
Herokuで使われている言葉がよく分からなかったので、調べてみると、 Procfile ってのが、重要そう。
b. Procfileを作ってみる
web: scripts/install-sdk.sh
web: node server.js --port $PORT --listen 0.0.0.0 -a name:password
→ デプロイ → 失敗 😭
エラーのログにも変化がないし、
script/install-sdk.sh
が実行されてる様子がないな。
c. インストールコマンドと起動コマンドを一つのファイルにまとめる
Procfileを変更
web: scripts/install-sdk.sh
# 追記
node server.js --port $PORT --listen 0.0.0.0 -a name:password
→ 失敗
g++が無いから、インストールに失敗してるのかな?
d. cedar-14っていうスタック に変えてみる
# stackを指定してherokuのアプリをcreate
$ heroku create --stack cedar-14
# ディレクトリを移動
$ cd cloud9のディレクトリ
# herokuをリモートに追加
$ git heroku git:remote -a アプリ名
# herokuにpush
$ git push heroku master
-> 失敗
うん、、、わからん。ここで力尽きました。(泣)
2. Dockerでデプロイ
Docker のアカウントを持っていて、パソコンにDockerが入っているものとして話を進めます。
「なんだそれ?」ってひとは、上のリンクにアクセスするか、よしなにぐぐってください。
Cloud9コンテナをローカルのDocker上に置く
# docker イメージをダウンロードし、コンテナをつくる
$ docker pull kdelfour/cloud9-docker
# コンテナにbashで入る
$ docker exec -it コンテナID bash
# コンテナ内でcloud9を起動
$ node server.js --port 8080
→ 出来た
Heroku Docker のチュートリアルを進めてみる
# herokuにログイン
$ heroku container:login
# gitからcloneする
$ git clone https://github.com/heroku/alpinehelloworld.git
# herokuのアプリをcreate
$ heroku create
# ディレクトリを移動
$ cd alpinehelloworld
# イメージをherokuにアップロード
$ heroku container:push web -a アプリ名
# herokuにデプロイ
$ heroku container:release web -a アプリ名
# ページを開く
$ heroku open -a アプリ名
→ 出来た
a. Cloud9のコンテナをHerokuの上に送る
# webappディレクトリを削除
rm -rf ./webapp
# Dockerfileを編集
#Grab the latest alpine image
FROM kdelfour/cloud9-docker
RUN /cloud9/scripts/install-sdk.sh
# Expose is NOT supported by Heroku
# EXPOSE 5000
# Run the app. CMD is required to run on Heroku
# $PORT is set by Heroku
CMD node server.js --port $PORT --listen 0.0.0.0 --auth name:pass
→ 動いた?
ん?
でも、cloud9 インストールされてない(.c9が無い)のか??
ん?
Terminalが使えない(泣)
b. Dockerfileを編集
#Grab the latest alpine image
FROM kdelfour/cloud9-docker
RUN /cloud9/scripts/install-sdk.sh
RUN C9_DIR=$HOME/.c9
RUN PATH="$C9_DIR/node/bin/:$C9_DIR/node_modules/.bin:$PATH"
RUN cd $C9_DIR
RUN npm install pty.js
# Expose is NOT supported by Heroku
# EXPOSE 5000
# Run the app. CMD is required to run on Heroku
# $PORT is set by Heroku
CMD node server.js --port $PORT --listen 0.0.0.0 --auth name:pass
例のごとくインストールして、
きたーーーーーーー!!!!
→ 成功!!
GitHubにDockerfileを公開しています
3. トンネリング
あらかじめ、ssh接続先でアプリケーションを実行しておいてください。
接続先で動かす簡易ウェブアプリの例 cloud9を動かしてもOKです)
# bottleをインストール
$ pip install bottle
from bottle import route, run
@route('/')
def hello():
return "Hello World!"
run(host='localhost', port=8080, debug=True)
# バックグラウンドで実行
python3 server.py &
まず、トンネリングをコマンドラインで動かしてみる
$ ssh example.com -p 22 -L 8080:localhost:8080
0.0.0.0:8080にアクセスしてみる
→ 成功
pythonで実装
# sshtunnelライブラリをインストール
$ pip install sshtunnel
from sshtunnel import SSHTunnelForwarder
import sys
args = sys.argv
server = SSHTunnelForwarder(
('example.com', 22),
ssh_username="name",
ssh_password="pass",
remote_bind_address=('0.0.0.0', 8080),
local_bind_address=('0.0.0.0', 8080)
)
server.start()
# 実行
$ python3 connect.py
0.0.0.0:8080にアクセスしてみる
→ 成功
Herokuのpythonチュートリアルを進める
# GitHubからclone
$ git clone https://github.com/heroku/python-getting-started.git
# ディレクトリを移動
$ cd python-getting-started
# herokuのアプリをcreate
$ heroku create
# herokuにpush
$ git push heroku master
# デプロイ
$ heroku ps:scale web=1
# 開く
$ heroku open
→ 成功
修正して、Herokuにデプロイ
from sshtunnel import SSHTunnelForwarder
import sys
args = sys.argv
server = SSHTunnelForwarder(
('example.com', 22),
ssh_username="name",
ssh_password="pass",
remote_bind_address=('0.0.0.0', 8080),
local_bind_address=('0.0.0.0', int(args[1]))
)
server.start()
→ 成功
というか、これをするなら、AWSで良いんじゃない、、、??
一応、GitHubに上げときます。
まとめと今後の展望
HerokuとDocker、ポートフォワーディングについていい勉強になりました。
今後の展望としては、cloud9 でのプレビュー機能をつけることですね。
今更だけど、heroku dockerって、1日に1回リスタートされるみたいなんで、こまめにgit push remote master
しましょう。