Quarkus /WSL 蜜柑水、だけどおまけもあるよ

**※ 未完遂です**

世の中では Quarkus なり GraalVM なるものが流行っているそうで、新しい構成・開発にも対応していくぞという風潮は、いい加減 Java にも見飽きたわたしたちにも新鮮な期待を感じさせます。
そこで今回も、いつものように、むしろ WSL でやってみましょう。

### TL;DR
まあまあ動きますが、肝心の native 版がつくれませんでした。情報をお持ちのかた、教えていただけるとありがたいです。

## 前提

Docker が動いている必要があります。わたしは予算の都合で Windows 10 Home ですので、Docker for Windows が使えません。ちょっと苦労が必要になります。
こちら https://qiita.com/koinori/items/78a946fc74452af9afba にすばらしい記事があり、以下の組み合わせで動作することが確認されています。
- WSL Ubuntu 16.04
- Docker CE 17.03.3
※ 実際ここまでやるだけでわりと面倒です

Ubuntu 18.04 などあたらしいものを使いたいところですが、現状 Docker をうまく動かす方法が無いようです。16.04 を使うことを強いられることになるわけで、そうすると apt install では JDK などで新しいものが入れられません。binary distribution などを個別で入れる必要があります。

以下がインストールされている必要があります。カッコ内は実際に試したバージョン。
- OpenJDK 11 (11.0.2) : OpenJDK 12 では現状うまくいきませんでした
- Apache Maven 3.5.3+ (3.6.1)
- GraalVM (ce-1.0.0-rc15)
※ 上記のとおり apt では入れられませんが、install 手順は難しくないので省略します

## Quarkus - dev

やるのはこちら、公式の getting started です。
https://quarkus.io/guides/getting-started-guide

```
mvn io.quarkus:quarkus-maven-plugin:0.14.0:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=getting-started \
    -DclassName="org.acme.quickstart.GreetingResource" \
    -Dpath="/hello"
```
早い話が、これだけです。これで必要なものを集めて最小限の project を作成してくれます。以下のコマンドで実行します。

```
./mvnw compile quarkus:dev
```

これで、http://localhost:8080/hello でアクセスができるようになります。"hello" って返ってくるだけですが。ここまで動くのにまあまあの手順が必要になりますので、なかなかの達成感があるでしょう。ソースを変更すると、なんと hot reload します。すばらしいです。(ブラウザは reload してください...)
そのままガイドの続きを読みつついろいろ試してみるのもよいでしょう。

## Quarkus - native

さて、目玉の native 版です。公式ガイドでも続きとして紹介されています。こちらをやります。
https://quarkus.io/guides/building-native-image-guide.html

以下のコマンドで native 版を build します。

```
./mvnw package -Pnative.
```

生成された以下を実行すると、dev 版を実行していたとき同様に動作することが確認できるでしょう。

```
./target/getting-started-1.0-SNAPSHOT-runner
```

続きを見ていくと、以下のコマンドで (local ではなく) docker で動かすためのものを build する、とあります。

```
./mvnw package -Pnative -Dnative-image.docker-build=true
```

これが私の環境ではうまくいきませんでした。以下のようなエラーになります。

```
[INFO] [io.quarkus.creator.phase.nativeimage.NativeImagePhase] docker run -v /mnt/c/Users/odistagon/Documents/projects/getting-started/target:/project:z --rm --user 1000:1000 quay.io/quarkus/centos-quarkus-native-image:graalvm-1.0.0-rc15 -J-Djava.util.logging.manager=org.jboss.logmanager.LogManager -H:InitialCollectionPolicy=com.oracle.svm.core.genscavenge.CollectionPolicy$BySpaceAndTime -jar getting-started-1.0-SNAPSHOT-runner.jar -J-Djava.util.concurrent.ForkJoinPool.common.parallelism=1 -H:FallbackThreshold=0 -H:+PrintAnalysisCallTree -H:-AddAllCharsets -H:EnableURLProtocols=http -H:-SpawnIsolates -H:-JNI --no-server -H:-UseServiceLoaderFeature -H:+StackTrace
[getting-started-1.0-SNAPSHOT-runner:6]    classlist:   8,022.44 ms
[getting-started-1.0-SNAPSHOT-runner:6]        (cap):     418.82 ms
[getting-started-1.0-SNAPSHOT-runner:6]        setup:   1,107.75 ms
Fatal error: com.oracle.svm.core.util.VMError$HostedError: java.nio.file.AccessDeniedException: /tmp/SVM-6092077881174118427/LibCHelperDirectives.c
        at com.oracle.svm.core.util.VMError.shouldNotReachHere(VMError.java:70)
        at com.oracle.svm.hosted.c.codegen.CSourceCodeWriter.writeFile(CSourceCodeWriter.java:182)
        at com.oracle.svm.hosted.c.codegen.CSourceCodeWriter.writeFile(CSourceCodeWriter.java:160)
        at com.oracle.svm.hosted.c.codegen.QueryCodeWriter.write(QueryCodeWriter.java:77)
        at com.oracle.svm.hosted.c.CAnnotationProcessor.process(CAnnotationProcessor.java:78)
        at com.oracle.svm.hosted.c.NativeLibraries.finish(NativeLibraries.java:306)
        at com.oracle.svm.hosted.NativeImageGenerator.processNativeLibraryImports(NativeImageGenerator.java:1524)
        at com.oracle.svm.hosted.NativeImageGenerator.setupNativeLibraries(NativeImageGenerator.java:998)
        at com.oracle.svm.hosted.NativeImageGenerator.setupNativeImage(NativeImageGenerator.java:830)
        at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:522)
        at com.oracle.svm.hosted.NativeImageGenerator.lambda$run$0(NativeImageGenerator.java:442)
        at java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1386)
        at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
        at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
        at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
        at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Caused by: java.nio.file.AccessDeniedException: /tmp/SVM-6092077881174118427/LibCHelperDirectives.c
        at sun.nio.fs.UnixException.translateToIOException(UnixException.java:84)
        at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
        at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
        at sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:214)
        at java.nio.file.spi.FileSystemProvider.newOutputStream(FileSystemProvider.java:434)
        at java.nio.file.Files.newOutputStream(Files.java:216)
        at java.nio.file.Files.newBufferedWriter(Files.java:2860)
        at com.oracle.svm.hosted.c.codegen.CSourceCodeWriter.writeFile(CSourceCodeWriter.java:174)
        ... 14 more
Error: Image build request failed with exit status 1
```

なんとなく解決できる気がしません。解決法をご存知のかたいらしたら、ぜひ教えてください...
ダメ元で local 版の runner を入れたものを docker build したのですが、走らせたら派手に crash しました。

これができたら image を kubernetes で走らせて... とかまた時間が吸われるところでしたが、ある意味たすかりました。

## おまけ

最近では VSCode を好んで使っているのですが、WSL 上での作業では (あやしげな) drvfs 等に起因する使い勝手に癖がありました。そんな中、それを解決する extension が出たのです。
https://twitter.com/code/status/1124057230624665620
https://aka.ms/vscode-remote/download/extension

これを入れると、直接 WSL 内の folder を開けるようになります。非常にシンプルに使い勝手が向上します。試していませんが Docker container にも直接接続ができるようで、これも環境によっては便利そうです。