どうもこんにちは、久しぶりのScala投稿です。
今回も安定のdocker上でScalaを動かしていきたいと思います。
どうでもいいけど「〜てみた」というタイトルYouTuber感出るのであれですね…
環境のセットアップ
アプリケーションのディレクトリ構造はこんな感じ
シンプルにmain.scala内でサーバーとコントローラを宣言してます。
build.sbt
buildcache
project/
src/main/scala/main.scala
とりあえずdocker単体のコンテナで動かします。
使用イメージ: takashioshikawa/scala-2.11.7
ポート: 9000:9000
ボリューム: $(pwd)/buildcache/.ivy2/cache:/root/.ivy2/cache
ボリューム: $(pwd)/buildcache/.sbt/boot:/root/.sbt/boot
ボリューム: $(pwd):/var/app
くっっっっそ遅いビルドを少しでも高速化するためにキャッシュディレクトリをマウントしています。
これやっとかないとコンテナ消すたびに色々ダウンロードしだすので病みます
DockerでScalaを使う時のベストプラクティスがまだ分かってないので良い情報を持っている方はぜひ情報の方よろしくお願いします
最終的に実行するコマンドはこちら
docker run --rm -it -p 9000:9000 -v $(pwd)/buildcache/.ivy2/cache:/root/.ivy2/cache -v $(pwd)/buildcache/.sbt/boot:/root/.sbt/boot -v $(pwd):/var/app --name finatra-server takashioshikawa/scala-2.11.7
build.sbtとmain.scalaファイル
コピーしてもらえば動きます、多分
lazy val root = (project in file(".")).
settings(
name := "finatra-server",
version := "1.0",
scalaVersion := "2.11.7",
libraryDependencies ++= dervy,
resolvers ++= resolve
)
lazy val dervy = {
Seq(
"com.twitter" % "finatra-http_2.11" % "2.6.0"
)
}
lazy val resolve = {
Seq(
Resolver.sonatypeRepo("releases"),
"Twitter Maven" at "https://maven.twttr.com"
)
}
import com.twitter.finagle.Http
import com.twitter.finagle.http.Request
import com.twitter.finagle.stats.NullStatsReceiver
import com.twitter.finagle.tracing.NullTracer
import com.twitter.finatra.http.filters.HttpResponseFilter
import com.twitter.finatra.http.routing.HttpRouter
import com.twitter.finatra.http.{Controller, HttpServer}
object Main extends FinatraBenchmarkServer
class FinatraBenchmarkServer extends HttpServer {
// 色々な設定項目はBaseHttpServerを参照
// override def defaultFinatraHttpPort: String = ":9000"
// override def defaultHttpServerName: String = "0.0.0.0"
override def configureHttpServer(server: Http.Server) = {
server
.withCompressionLevel(0)
.withStatsReceiver(NullStatsReceiver)
.withTracer(NullTracer)
}
override def configureHttp(router: HttpRouter): Unit = {
router
.filter[HttpResponseFilter[Request]]
.add[FinatraBenchmarkController]
}
}
class FinatraBenchmarkController extends Controller {
private[this] val helloWorldResponseText = "Hello, World!"
get("/json") { request: Request =>
Map("message" -> "Hello, World!")
}
get("/plaintext") { request: Request =>
helloWorldResponseText
}
}
finatraを起動する
コンテナ内に入っていると思うのでアプリケーションディレクトリに移動
cd /var/app
アプリケーションを起動してみましょう。
-http.port=:9000
がポートの設定
-http.name=:0.0.0.0
がホストの設定
0.0.0.0
はdockerでlocalhostは使えないから
sbt 'run -http.port=:9000 -http.name=:0.0.0.0'
※FinatraBenchmarkServerにoverride def defaultFinatraHttpPort = ":9000"
と書くとsbt run時じゃなくてもポートの設定が出来る
※FinatraBenchmarkServerにoverride def defaultHttpServerName: String = "0.0.0.0"
と書くとsbt run時じゃなくてもサーバー名の設定ができる
上の2つを設定するとsbt run
と実行するだけでsbt 'run -http.port=:9000 -http.name=:0.0.0.0'
と同じ動作になる
なんか情報としてホストの設定が全然見つからなくてfinatraでは設定できない?と思ったけど普通にsbt runのエラーに出力されました
あとパラメータ入れる時は''で囲まないといけないっぽいので注意が必要です。
sbr 'run'の''の中に間違ったパラメータ入れると色々出てきます。
flags:
-admin.announce='java.lang.String': Address for announcing admin server
-admin.port=':9990': Admin http server port
-cert.path='': path to SSL certificate
-doc.root='': File serving directory/namespace for classpath resources
-help='false': Show this help
-http.announce='java.lang.String': Address for announcing HTTP server
-http.name='http': Http server name
-http.port=':8888': External HTTP server port
-http.response.charset.enabled='true': Return HTTP Response Content-Type UTF-8 Charset
-https.announce='java.lang.String': Address for announcing HTTPS server
-https.name='https': Https server name
-https.port='': HTTPs Port
-key.path='': path to SSL key
-local.doc.root='': File serving directory for local development
-log.append='true': If true, appends to existing logfile. Otherwise, file is truncated.
-log.async='true': Log asynchronously
-log.async.inferClassNames='false': Infer class and method names synchronously. See com.twitter.logging.QueueingHandler
-log.async.maxsize='4096': Max queue size for async logging
-log.level='INFO': Log level
-log.output='/dev/stderr': Output file
-log.rollPolicy='Never': When or how frequently to roll the logfile. See com.twitter.logging.Policy#parse documentation for DSL details.
-log.rotateCount='-1': How many rotated logfiles to keep around
-maxRequestSize='5242880.bytes': HTTP(s) Max Request Size
-mustache.templates.dir='templates': templates resource directory
-shutdown.time='1.minutes': Maximum amount of time to wait for pending requests to complete on shutdown
ではサーバーが起動している状態で
main.scalaに設定されていたルーティングの/json
を確認してみましょう
まずはdocker-machineのIPアドレスを確認して
docker-machine ip あなたのVM名
僕は192.168.99.100
なので
192.168.99.100:9000/json
にアクセスします
ブラウザに表示された結果は以下の通りでした
{"message":"Hello, World!"}
plaintextも設定していた文字列がそのまま表示されました。
設定していないエンドポイントにアクセスしようとすると特に何の設定もされていない404ページが表示されました
今回はサンプルのリクエストを叩いてみるだけで終了します
次回があるかわかりませんが何かメモしたくなったらまた書きます
所感
なんか公式見ながらやっても普通に動かない印象がありました笑
とりあえずコピペしたらサーバーくらい起動するくらいが理想なのでそのへんは割りと不親切かもしれません。
あと日本語情報が少ないので英語少しくらい読めたほうが良いはず
僕自身Sprayが昔好きでakka-httpやろうかなと思ってたんですけどふと目に入ってきたので触ってみました、APIに特化してると軽量スタートできるのが嬉しいです。
今回はただサンプルのリクエストを行っただけなので全然全体の触り心地はわからないですが、もう少し何か作ってみて判断したいと思います。
参考
Finatra
finatraはじめの一歩
travis-ciのキャッシュ機能を使って、Scalaプロジェクトのビルドを少しだけ高速化する
Maven Repository finatra-http_2.11: 2.6.0