8u191
でDocker対応がバックポートされたので、頭の整理と確認をしておいた。
## まとめ
Java 11使っておけばそもそも安心
なんだけど、Java 8でも8u191
以降を使えば安心
。
## 課題だったこと
DockerでJavaを動かすときJavaが「そのコンテナに割り当てられたCPU・メモリ」じゃなくて「Dockerが動いてるHostのCPU・メモリ」を見てしまうことが課題だった。
## Java 10以降
Java 10以降なら「そのコンテナに割り当てられたCPU・メモリ」を見る対応が入ってるから安心
になった。
## Java 8は?
Java 8で入ってた対応は8u131
のこれ:
詳しくはここに書いてある:
メモリ用のオプションが追加されたので、それをつければメモリの認識は大丈夫。CPUは一部対応。という話。
そのメモリ用のオプションは将来的につけなくても大丈夫にする予定だったからExperimental扱い(そして実際にJava 10以降でも8でもつけなくてよくなった)。という感じ。
## 8u191
そして、Java 10の対応が8u191
でバックポートされたのでJava 8でも8u191
以降なら安心
になった。今の最新は8u192
かな。
(∩´∀`)∩ワーイ
## 追加されてるオプション
-XX:-UseContainerSupport
をつけるとこのコンテナサポートをオフにできる。-XX:ActiveProcessorCount=count
を指定すると自分でプロセッサーカウントを設定できる。
## 参照
- OpenShiftやKubernetes上でJavaを動かす際の注意 - nekop's blog
- Matthew Gilliard's blog || Better Containerized JVMs in JDK10
- Improved Docker Container Integration with Java 10 - Docker Blog
## 確かめる
てことで確かめてみる。いつも通り、確認したいこととは関係ないところで色々勉強になったや。
- 8u181
- 制限なしでどうなるかを見ておく(ベースライン)
- コンテナ制限を見てないことを確認
- メモリオプションつけたらメモリは認識されることを確認
- 8u192
- 制限なしでどうなるかを見ておく(ベースライン)
- コンテナ制限を見てることを確認
- 11 (11.0.1.13)
- 制限なしでどうなるかを見ておく(ベースライン)
- コンテナ制限を見てることを確認
くらいでいいかな。8u191
以降のOpenJDKのDockerイメージはまだ出てないみたいなので、AdoptOpenJDKで確認することにした。初めて使う!
実行環境はこんな感じ
❯ docker version Client: Version: 18.03.1-ce API version: 1.37 Go version: go1.9.5 Git commit: 9ee9f40 Built: Thu Apr 26 07:17:38 2018 OS/Arch: linux/amd64 Experimental: false Orchestrator: swarm Server: Engine: Version: 18.03.1-ce API version: 1.37 (minimum version 1.12) Go version: go1.9.5 Git commit: 9ee9f40 Built: Thu Apr 26 07:15:45 2018 OS/Arch: linux/amd64 Experimental: false ❯ docker-compose version docker-compose version 1.23.1, build b02f1306 docker-py version: 3.5.0 CPython version: 3.6.7 OpenSSL version: OpenSSL 1.1.0f 25 May 2017
## 実行する内容
これを実行する。こんなところ気にしたことなかったからavailableProcessors
とかmaxMemory
とか初めて使った。バージョンはRuntime.Version
ってのがあったから使おうとしたら導入されたのがJava 9やったから使えんかったw
public class A { public static void main(String[] args) { System.out.println("Version: " + System.getProperty("java.version")); System.out.println("availableProcessors: " + Runtime.getRuntime().availableProcessors()); System.out.println("maxMemory: " + Runtime.getRuntime().maxMemory()/1024/1024 + "M"); } }
## 設定周り
docker直接でやっても良かったんだけど、docker-composeでごにょごにょやった。
# use v2 because v3 stop supporting cpu and memory options. version: "2.4" x-common: &common command: sh -c "javac A.java -d /tmp && cd /tmp && java A" environment: JAVA_TOOL_OPTIONS: "" working_dir: /work volumes: - .:/work services: # jdk8u181 jdk8u181-base: &jdk8u181-base image: adoptopenjdk/openjdk8:jdk8u181-b13-alpine <<: *common jdk8u181-limit: &jdk8u181-limit <<: *jdk8u181-base cpus: 2 mem_limit: 512m jdk8u181-limit-option: <<: *jdk8u181-limit environment: JAVA_TOOL_OPTIONS: "-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap" # jdk8u192 jdk8u192-base: &jdk8u192-base image: adoptopenjdk/openjdk8:jdk8u192-b12-alpine <<: *common jdk8u192-limit: <<: *jdk8u192-base cpus: 2 mem_limit: 512m # jdk-11 jdk-11-base: &jdk-11-base image: adoptopenjdk/openjdk11:jdk-11.0.1.13-alpine <<: *common jdk-11-limit: <<: *jdk-11-base cpus: 2 mem_limit: 512m
### Compose file v2を使ってる理由
v3ではcpus
やmem_limit
周りの機能が削除されてるから。悲しみ。
docker-compose におけるメモリ使用量の制限方法 - reboooot.net
結局、v3はSwarm Mode用だから、それ使わんならv2使いなよってことらしい。Docker社っぽいやり方だなw
How to specify Memory & CPU limit in version 3 · Issue #4513 · docker/compose · GitHub
### YAMLのAnchorについて
YAMLのAnchorはこの辺を参考に:
Don’t Repeat Yourself with Anchors, Aliases and Extensions in Docker Compose Files
Compose fileのExtension fields (x-
)についてはここを参考に:
Compose file version 2 reference | Docker Documentation
今回は遊びだから適当に使ったけど、実際に仕事とかで使うときは「DRYにしすぎて意味がわからない」ってならないようにしたいね。
### JAVA_TOOL_OPTIONS
AdoptOpenJDKのイメージにはJAVA_TOOL_OPTIONS
が設定されてるので、今回の検証ではそれを一旦空にしてから動かしてる。
@sugarlifeさんありがとうございます!OpenJDKのソースコード初めて読んだw
特殊環境変数なので起動時に読まれますねhttps://t.co/CIkiF83PBo
— KUBOTA Yuji (@sugarlife) November 10, 2018
PickedはArguments::parse_options_environment_variableで出力されます。
ちなみに設定されている値はこんな感じ。勉強になるー。
- Java 8の場合は
JAVA_TOOL_OPTIONS="-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap"
- Java 11の場合は
JAVA_TOOL_OPTIONS="-XX:+UseContainerSupport"
- https://github.com/AdoptOpenJDK/openjdk-docker/blob/047540bba24b338ca6916c736fe15e04a76107c8/11/jdk/alpine/Dockerfile.hotspot.releases.full#L86
- これ指定しなくてもデフォルトでONなんだけど、明示的に「ONだよ!」って教えてくれてるって意図なのかな。
javac
とかjava
を実行したときに毎回ログに出るからうざいなと思って消せないか探してみたけど
[JDK-8039152] Need a way to suppress message when picking up JAVA_TOOL_OPTIONS - Java Bug System
This will not be implemented, as it may introduce a vulnerability
ってことで脆弱性につながるから実装しないってことみたい。申し訳ございませんでした。納得。
## 実行スクリプト
docker-compose up
するとログが混ざるから、こんなスクリプトを用意した。
#!/bin/bash list=( jdk8u181-base jdk8u181-limit jdk8u181-limit-option jdk8u192-base jdk8u192-limit jdk-11-base jdk-11-limit ) for item in ${list[@]}; do echo "# $item" docker-compose run --rm $item echo "" done
## 結果
ちなみに、JAVA_TOOL_OPTIONS
が2回出てるのはjavac
の分とjava
の分。
❯ ./check.sh # jdk8u181-base Picked up JAVA_TOOL_OPTIONS: Picked up JAVA_TOOL_OPTIONS: Version: 1.8.0_181 availableProcessors: 4 maxMemory: 3504M # jdk8u181-limit Picked up JAVA_TOOL_OPTIONS: Picked up JAVA_TOOL_OPTIONS: Version: 1.8.0_181 availableProcessors: 4 maxMemory: 3504M # jdk8u181-limit-option Picked up JAVA_TOOL_OPTIONS: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap Picked up JAVA_TOOL_OPTIONS: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap Version: 1.8.0_181 availableProcessors: 4 maxMemory: 114M # jdk8u192-base Picked up JAVA_TOOL_OPTIONS: Picked up JAVA_TOOL_OPTIONS: Version: 1.8.0_192 availableProcessors: 4 maxMemory: 3504M # jdk8u192-limit Picked up JAVA_TOOL_OPTIONS: Picked up JAVA_TOOL_OPTIONS: Version: 1.8.0_192 availableProcessors: 2 maxMemory: 123M # jdk-11-base Picked up JAVA_TOOL_OPTIONS: Picked up JAVA_TOOL_OPTIONS: Version: 11.0.1 availableProcessors: 4 maxMemory: 3942M # jdk-11-limit Picked up JAVA_TOOL_OPTIONS: Picked up JAVA_TOOL_OPTIONS: Version: 11.0.1 availableProcessors: 2 maxMemory: 123M
想定通りの結果だね。今日のソースコードはここ。
## 本筋とは関係ないところで勉強になったこと
- AdoptOpenJDK使った
availableProcessors
とmaxMemory
を知ったRuntime.Version
がJava 9からだと知った(以前に一度確認したことがあったような気がしなくもないJAVA_TOOL_OPTIONS
の存在を知った- OpenJDKのソースコード初めて読んだ
JAVA_TOOL_OPTIONS
が使われてることをログから消すことはできないってことを知った- Compose fileのCPU・メモリ制限がv2までで、v3はSwarm Modeサポート用だと知った
- YAMLのAnchorについて勉強しなおした
- Compose fileのExtension fieldsの存在を知った
面白かったー(∩´∀`)∩ワーイ