ホストの/etc/localtimeをコンテナの/etc/localtimeにマウントすることでDockerイメージを使用する人のローカルの時刻に合わせる手法はよく行われますが、ある日Mac OSでそれができなくなって困ってしまいました。

環境

  • Mac OS Mojave 10.14.4
  • Docker Desktop Community 2.0.0.3
  • Docker Engine 18.09.2

再現方法

実際は某OSSを動かそうとして発生しましたが、最小構成のdocker-compose.ymlを書いて再現させてみます。

version: "3"

services:
  hello:
    image: hello-world
    volumes:
      - /etc/localtime:/etc/localtime:ro

docker-compose upすると/etc/localtimeがOS XからDockerに共有されていないと言ってマウントがエラーになリます。

$ docker-compose up
Starting work_hello_1 ... error

ERROR: for work_hello_1  Cannot start service hello: b'Mounts denied: \r\nThe path /etc/localtime\r\nis not shared from OS X and is not known to Docker.\r\nYou can configure shared paths from Docker -> Preferences... -> File Sharing.\r\nSee https://docs.docker.com/docker-for-mac/osxfs/#namespaces for more info.\r\n.'

ERROR: for hello  Cannot start service hello: b'Mounts denied: \r\nThe path /etc/localtime\r\nis not shared from OS X and is not known to Docker.\r\nYou can configure shared paths from Docker -> Preferences... -> File Sharing.\r\nSee https://docs.docker.com/docker-for-mac/osxfs/#namespaces for more info.\r\n.'
ERROR: Encountered errors while bringing up the project.

ログに書かれたURLを見ると、デフォルトだと/Users/Volumes/private/tmpが共有されているがそれ以外のディレクトリはDockerに共有されていないようです。
現在の設定はDocker -> Preferces -> File Sharingで確認できます。

/etcが共有されていないように思えますが、/etc/private/etcにリンクが張られており/privateが共有されているので問題ないはずです。
また、/etc/localtimeの実態は/var/db/timezone/zoneinfo/Asia/Tokyoで、/varの実態は/private/var なのでこれも問題ないはずです。

$ readlink /etc
private/etc

$ readlink /etc/localtime
/var/db/timezone/zoneinfo/Asia/Tokyo

$ readlink /var
private/var

と言うか、もともとは使えてたので問題ないはずなんですよね。

対処法

https://github.com/docker/for-mac/issues/2396

本家のリポジトリでもIssueが上がっていますが現在のところ対症療法しかないようです。

対処法1.

/etc/localtimeの代わりにファイルの実態である/var/db/timezone/zoneinfo/Asia/Tokyoを指定します。

version: "3"

services:
  hello:
    image: hello-world
    volumes:
      - /var/db/timezone/zoneinfo/Asia/Tokyo:/etc/localtime:ro

さらに共有フォルダに/var/dbを追加します。

これでdocker-compose upすると無事起動できました。
このことから、/var/etcのサブフォルダを明示的に共有することでマウント出来ることが分かりました。

/etcを共有できれば/etc/localtimeがマウントできそうですが、それは出来ないようです。
これが出来れば設定ファイルを書き変えず実行できるのに残念。

対処法2.

参照できるディレクトリにtimezoneファイルを作成する方法です。/etc/localtimeはバイナリのファイルですが、テキストファイルにタイムゾーンを指定する方法もあるようです。この例では/Users下にファイルを作成しました。

$ mkdir ~/etc
$ echo Asia/Tokyo > ~/etc/timezone

docker-compose.ymlを書き換えて/etc/timezoneをマウントさせます。

version: "3"

services:
  hello:
    image: hello-world
    volumes:
      - ~/etc/timezone:/etc/localtime:ro

対処法3.

最後はTZ環境変数を使用する方法です。
docker-compose.ymlのenvironmentにTZ=Asia/Tokyo を追加してタイムゾーンを指定します。
設定ファイルを書き換えるだけで済むのが楽なので、自分はこの方法で回避しています。

version: "3"

services:
  hello:
    image: hello-world
    environment:
      - TZ=Asia/Tokyo

おわりに

どれも設定ファイルを書き換える方法なのがイマイチですが回避はできました。
早いところ根本的に対応してくれないかな。