Neuronは、ほとんどの場合Windowsにインストールされるため、テスト環境をWindows上に構築しています。 このテスト環境構築を効率化するため、docker上でのWindows利用を模索しています。
前回に引き続き、 Windows上のdockerでイメージをビルドする際・コンテナを動かす際に慣れないことを紹介します。
前回検討した導入方法から、dockerは「Hyper-Vコンテナ + LCOW」の形態で利用しています。 (そのため、Docker for Windowsを利用する場合とは異なる状況であることに注意ください。)
Windowsのバージョンは、
Windows 10 Pro バージョン 1803 (Version 10.0.17134.165
)、
dockerのバージョンは、
Client: |
LCOWのバージョンは、4.14.29-0aea33bc
です。
以下、OSがWindowsであるコンテナを「WindowsOSコンテナ」、OSがLinuxであるコンテナを「LinuxOSコンテナ」と呼びます。
目次
イメージビルド編
multi-stage buildsで、名前に半角スペースを含むファイルをCOPY
できない
multi-stage buildsでイメージビルドする際、名前に半角スペースを含むファイル(または、それを含むディレクトリ)を、WindowsのイメージにCOPY
しようとすると、ビルドが以下のエラーで止まります。
COPY failed: file does not exist
|
よくある半角スペースの問題と考え、"
で括るためにCOPY --from=builder ["src/sample file", "."]
のJSON形式で指定しても、今度は別のエラーで止まります。
COPY failed: Forbidden path outside the build context
|
昔からあるファイル・ディレクトリ名の半角スペース問題に、久しぶりに遭遇しました。(厳密には別の問題のようですが…)
RUN
/CMD
で使われるシェルを意識する
RUN
/CMD
にシェル形式でコマンドを指定する際、コマンド実行に使われるシェルがcmd
(コマンドプロンプト)なのかpowershell
なのかを意識することが重要です。powershell
特有のコマンドを使う際は自然と意識すると思いますが、このふたつは環境変数の取得方法がだいぶ異なるため、java
のような自分でパスを通すコマンドを使う時に注意が必要です。
cmd |
powershell |
|
---|---|---|
環境変数VAR の取得方法 |
%VAR% |
$env:VAR |
存在しない環境変数NONE から取得される値 |
%NONE% という文字列 |
空文字列 |
シェル形式で書かれたRUN
/CMD
のコマンド実行に使われるシェルは、デフォルトがcmd
(cmd /S /C
)ですが、SHELL
で変更することができます。
使用するイメージのDockerfileを読むか、docker inspect
でイメージのCmd
プロパティからシェルを特定するとよいでしょう。たとえば、openjdk:8u171-jdk-nanoserver
はpowershell
をシェルに指定しています。
コンテナ実行編
[LinuxOSコンテナ] メモリ割り当てが変更できない
LinuxOSコンテナに対して、docker run
時に--memory
オプションから割当メモリを指定しても無視され、 以下のように、約1GBのメモリが割り当てられます。
PS C:¥> docker run --rm --memory 2g alpine:3.8 cat /proc/meminfo |
WindowsOSコンテナに対しては、以下のように、指定通り約2GBのメモリが割当たります。
PS C:¥> docker run --rm --memory 2g microsoft/windowsservercore:1803 systeminfo |
mobyのissueを読む感じでは、 LCOWを使用しているために起きる問題のようです…
[LinuxOSコンテナ] user指定が効かない
LinuxOSコンテナに対して、docker run
時に--user
オプションを指定しても無視され、 以下のように、rootユーザで実行されます。
PS C:¥> docker run --rm --user guest alpine:3.8 whoami |
LCOW使用時の既知のバグのようです。 イメージビルド時のUSER
指定も効かないため、LinuxOSコンテナは常にroot
で動くことになります。
そして、この影響なのか、コンテナ内のディレクトリ・ファイルの所有者とグループが大体root:root
になってしまいます。
[LinuxOSコンテナ] mountされたvolumeに対してchmod
/chown
が効かない
「イメージビルド時のVOLUME
」や「docker run
時の--volume
オプション」でvolumeに指定されたディレクトリ以下に対して、chmod
/chown
が効きません。
以下の例のように、chmod
を行っても、終了コードが0であるにも関わらずパーミッションが変更されません(例ではjenkins/jenkins:2.134
イメージを使用)。
root@fcdd7ae24179:/var/jenkins_home# ls -la |
既知の問題ではあるようですが、回避策は特にない状況です。
このことが起因する問題には色々当たりましたが、大きかったのはjenkinsでリポジトリをダウンロードする際にエラーが起きることでした。 volume指定を使わないことでエラーを回避しましたが、docker cp
でjenkins設定の永続化を行うことになってしまいました…
稼働中のコンテナに対してdocker cp
できない
稼働中のコンテナに対してdocker cp
を実行すると、以下のエラーが発生してコピーができません。
PS C:¥Users¥user¥Documents> docker cp 7961ee45d606:/var . |
なお、停止中のコンテナに対しては正常にコピーできます。
おわりに
Windows上のdockerにて、イメージビルドやコンテナ実行の際に慣れないことを紹介しました。 LinuxOSコンテナについて、「volume周りの問題」と「メモリが最大1GB」がかなり厄介な問題です。
上記の他にも以下のようなことがありました。
- コンテナ自体を作成できないイメージがある
- 例えば、
openjdk:8u171-jdk-nanoserver
- しかし、
openjdk:8u171-jdk-windowsservercore
はコンテナ実行可能
- 例えば、
- LinuxOSコンテナ用のDockerfileを、WindowsOS用に書き換えるには細かいところも気にしないとならない
- javaのclasspath区切りは、Windowsでは
:
ではなく;
、など
- javaのclasspath区切りは、Windowsでは
- dockerdを再起動すると、元々稼働していたコンテナがstartできなくなる
やはり、experimentalなLCOWを使ってLinuxOSコンテナを扱うのは、まだ早いのでしょうか。 WindowsOSコンテナのみに絞ればよいかもしれませんが、そうするとLCOWを使う理由もないですし…
docker上でのWindows利用について、LCOWは引き続き試してゆきますが、 現状では、Docker for Windowsが可能な範囲で模索してゆくほうがよさそうです。