gcloudコマンドへの移行
とある日
「goappがなくなる」そんな一報が入ってきました。 goappはGoのGAESDKをダウンロードするともれなくついてくるコマンドで、 GAEのローカルでの開発サーバや、デプロイに使用しているコマンド。
実際噂しているGitHubのリポジトリを見に行くと
とたしかに移行している。
GCPのアドボケートをやられていて世界中で飛び回りながらGCPの解説をされているFrancesc氏のワークショップ用リポジトリでの修正なので多分間違いはないだろう。 たしかにGAEだけ特別にコマンドがあるような現状はGCPの将来には好ましいことではないかな?と感じたので、移行しとこー!ってことになりました。
GCP周りはあまり使わないのでgcloudコマンドは多用してないいのですが、少しやってみました。
注意
2017-5-21辺りに行ってこの記事までの問題なので、今後変更される可能性はあります。というより、最終的にやりたいことはできなかったので、きっと解決されると思っています。 一応私の環境を書いておきます。
- Linux(Ubuntu 16.04)
- gcloud version 155
- app-engine-go 1.9.52(google-cloud-sdk内
また、goappが変な動作をしないように以前から存在したappengineのSDKはパスの中から削除しました。 ※gcloudの中身などが間違ってそっちが実行されないように
変更する箇所
まずは
# goapp serve [.] # goapp deploy [.]
が
# dev_appserver.py [app.yaml] # gcloud app deploy [--version application_version] [--project your_project_id]
に変更になります。 ディレクトリや設定ファイルの指定は各自の環境で変更してください。 また、バージョンの指定やプロジェクトIDの指定は設定ファイルでの指定ではなくなりました。 gcloudの設定にしたりもできるみたいです。(gcloud config辺りで調べてください
まずは作成
以前からやりたいことがあった(実際にJava実装がある)けど、まだ作ってなかったので、それを作りながら検証しようと思いました。
構成
app |-src/handler.go |-static/ |-templates/ |-app.yaml
$GOPATH={コンピュータ上の他のディレクトリです}
srcにはgoのソースをおいています。(はじめに試した時はhandler.goしかありませんでした。 staticは静的なファイル、templatesはHTMLテンプレートをおいています。※この2つは動作以外には関係ないので以降は割愛
gcloudでデプロイ
簡単なログインの処理を書いたところでローカルでの実行を行いデプロイをしてみました。
could not get package for dir "ディレクトリ": no buildable Go source files ディレクトリ
というエラーが出ます。 これはダミーでdoc.goなどを作って(パッケージ名だけを各)デプロイを行うと
can't find import: "google.golang.org/appengine"
というエラーが出ます。 ここで問題なのは開発サーバでは動作しているということです。 ※自分の指定したGOPATHにはもちろんあります
ちなみにですがこの構成でもgoappではデプロイできるので、びみょいです。
解決策:srcディレクトリをやめる
解決策というかとりあえず動作させるにはsrcディレクトリをやめて
app |-handler.go |-app.yaml
と構成してデプロイするとOKになります。
ルートにGoのファイルがないことも自然とクリアしますし、上記エラーも出なくなるので軽いアプリケーションを作成するにはこれでOKだと思います。ちなみにですが、後述するアプローチでも一応解決します。
appをGOPATHに指定してみる
上記解決策はアプリケーションが小さい時の話であって、アプリが大きくなってきてパッケージで区切ったりしたくなってきたりすると思います。なのでsrcディレクトリ上で管理したくなるわけです。なおかつアプリ独自のパッケージも使いたいので、GOPATHには指定したいわけです。
app |-src/handler.go |-app.yaml |-doc.go
$GOPATH={app:コンピュータ上のディレクトリ}
としました。
再度 gcloud でデプロイ
GOPATHを指定していても、指定しない時と上記と同様の問題が発生します。 ※なので構成にdoc.goが存在します ただこの場合はsrcディレクトリを削除したら意味がないので、この解決策ではうまく行きません。
解決策:importする
結局src内でライブラリを見ているとデプロイ先で見てくれない。 という問題になりますのでルートディレクトリに存在するdoc.goに
package dummy import { _ "google.golang.org/appengine" }
と書きます。”_”はインポートはする(init()だけ実行を行う)よ。という宣言ですね。 ※もちろん書かないと「使ってないよ」とコンパイルエラーになります。
もちろんですが、プロジェクトで使用するライブラリを全部書きます。 これは、、、はっきり言って無駄です。 無理やりプロジェクトで使っているライブラリを管理できる。。。位かな?
GOPATHを指定しているのは独自パッケージをつかいたいだけなので、 簡素な場合は別にディレクトリをGOPATHに指定しなくても大丈夫な状態です。
vendoringを行う
GOPATH汚染問題もありますのでこれが本命になってくると思います。 構成は
app |-src/ |-{mypackage}/handler.go |-vendor/{ライブラリ} |-app.yaml |-doc.go
$GOPATH={app:コンピュータ上のディレクトリ}
開発サーバで問題
Failed parsing input: parser: bad import "syscall" in vendor/パッケージ
が発生します。 ※対象ライブラリがsyscallしてくれてて逆に検証になった!
app.yamlに以下を追加します。
nobuild_files: src/vendor
でsyscallによる問題は解決します ちなみに前述で解決策に使用した「doc.go」へのインポートですが、 vendorに入れるパッケージに関してはここでimportしなくても動作しました。
gcloud でデプロイできない
でこの構成でデプロイして、、、
Failed parsing input: parser: bad import "syscall" in vendor/パッケージ
・・・おい、、、
※ちなみにですが、エラーを起こしているパッケージは将来的に使う為においただけなので、 実行は絶対されてない状態(importもしてない)です。
感想
開発サーバで動作する状況になるけど、デプロイでエラーになるという結果になりました。 goappではデプロイできるのもそうですが、基本的には「挙動がしっかり決定するまで待った方がいい」って思いました。
goapp はコンパイルしてデプロイ gcloud はGCS上に展開してコンパイル、デプロイ
という手法をとっている部分で問題が発生しているように見えます。(雰囲気で言っている
issuetracker.google.com/issues/35900848
比較的最近でもgoapp使えばOKじゃね?っていう雰囲気もあります。
app.yamlの位置や実行の位置などでもいろいろ起こりそうな雰囲気でしたが、 そこまで試す余裕もなかったので今回のところはこれにてクローズします。