Technology Topics by Brains

ブレインズテクノロジーの研究開発機関「未来工場」で働くエンジニアが、先端オープン技術、機械学習×データ分析(異常検知、予兆検知)に関する取組みをご紹介します。

WindowsのDockerで慣れないこと(実践編)

Neuron開発チームの木村です。

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:
 Version:           master-dockerproject-2018-07-18
 API version:       1.38
 Go version:        go1.10.3
 Git commit:        48fbb12b
 Built:             Wed Jul 18 23:51:23 2018
 OS/Arch:           windows/amd64
 Experimental:      false

Server:
 Engine:
  Version:          master-dockerproject-2018-07-18
  API version:      1.38 (minimum version 1.24)
  Go version:       go1.10.3
  Git commit:       7f91801
  Built:            Thu Jul 19 00:00:43 2018
  OS/Arch:          windows/amd64
  Experimental:     true

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-nanoserverpowershellをシェルに指定しています。


コンテナ実行編

[LinuxOSコンテナ] メモリ割り当てが変更できない

LinuxOSコンテナに対して、docker run時に--memoryオプションから割当メモリを指定しても無視され、 以下のように、約1GBのメモリが割り当てられます。

PS C:\> docker run --rm --memory 2g alpine:3.8 cat /proc/meminfo
MemTotal:         985568 kB
MemFree:          870932 kB
MemAvailable:     805808 kB
...

WindowsOSコンテナに対しては、以下のように、指定通り約2GBのメモリが割当たります。

PS C:\> docker run --rm --memory 2g microsoft/windowsservercore:1803 systeminfo
...
Total Physical Memory:     2,559 MB
Available Physical Memory: 2,194 MB
...

mobyのissueを読む感じでは、 LCOWを使用しているために起きる問題のようです…


[LinuxOSコンテナ] user指定が効かない

LinuxOSコンテナに対して、docker run時に--userオプションを指定しても無視され、 以下のように、rootユーザで実行されます。

PS C:\> docker run --rm --user guest alpine:3.8 whoami
root

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
total 0
-r-xr-xr-x 1 root root  102 Jul 30 05:02 copy_reference_file.log
drwxrwxrwx 1 root root 4096 Jul 30 05:02 init.groovy.d
root@fcdd7ae24179:/var/jenkins_home# chmod 755 copy_reference_file.log
root@fcdd7ae24179:/var/jenkins_home# echo $?
0
root@fcdd7ae24179:/var/jenkins_home# ls -la
total 0
-r-xr-xr-x 1 root root  102 Jul 30 05:02 copy_reference_file.log
drwxrwxrwx 1 root root 4096 Jul 30 05:02 init.groovy.d

既知の問題ではあるようですが、回避策は特にない状況です。
このことが起因する問題には色々当たりましたが、大きかったのはjenkinsでリポジトリをダウンロードする際にエラーが起きることでした。 volume指定を使わないことでエラーを回避しましたが、docker cpでjenkins設定の永続化を行うことになってしまいました…


稼働中のコンテナに対してdocker cpできない

稼働中のコンテナに対してdocker cpを実行すると、以下のエラーが発生してコピーができません。

PS C:\Users\user\Documents> docker cp 7961ee45d606:/var .
Error response from daemon: filesystem operations against a running Hyper-V container are not supported

なお、停止中のコンテナに対しては正常にコピーできます。


おわりに

Windows上のdockerにて、イメージビルドやコンテナ実行の際に慣れないことを紹介しました。 LinuxOSコンテナについて、「volume周りの問題」と「メモリが最大1GB」がかなり厄介な問題です。

上記の他にも以下のようなことがありました。

  • コンテナ自体を作成できないイメージがある
    • 例えば、openjdk:8u171-jdk-nanoserver
    • しかし、openjdk:8u171-jdk-windowsservercore はコンテナ実行可能
  • LinuxOSコンテナ用のDockerfileを、WindowsOS用に書き換えるには細かいところも気にしないとならない
    • javaのclasspath区切りは、Windowsでは:ではなく;、など
  • dockerdを再起動すると、元々稼働していたコンテナがstartできなくなる

やはり、experimentalなLCOWを使ってLinuxOSコンテナを扱うのは、まだ早いのでしょうか。 WindowsOSコンテナのみに絞ればよいかもしれませんが、そうするとLCOWを使う理由もないですし…

docker上でのWindows利用について、LCOWは引き続き試してゆきますが、 現状では、Docker for Windowsが可能な範囲で模索してゆくほうがよさそうです。


ブレインズテクノロジーではエンジニアを募集中です
採用ページはこちら