Docker for MacでAWSにアクセスするコンテナがエラーになるときの対処方法

docker

ども、大瀧です。
Docker for MacでAWSにアクセスするコンテナを動かすと、リクエストが毎回400エラーになるトラブルに遭遇したので、その原因と対処法をシェアします。

検証環境

  • macOS Sierra バージョン 10.12.1
  • Docker for Mac バージョン 1.12.3

トラブルの現象と原因

Bloxのローカル(Docker)実行を試すと一部のコンテナが不正終了してしまい、以下のエラーログが確認できました。

$ docker logs  conf_css_1
2016-12-06T09:05:47Z [INFO] Reconciler loading tasks and instances
2016-12-06T09:05:48Z [CRITICAL] Error starting event stream handler: Error bootstrapping: Failed to reconcile. Could not load tasks.: Error listing clusters from ECS: Failed to list ECS clusters.: InvalidSignatureException: Signature not yet current: 20161206T090547Z is still later than 20161206T012112Z (20161206T011612Z + 5 min.)
	status code: 400, request id: 936c1dbf-bb51-11e6-b842-b9f0e3cab7be
$

Amazon ECSのAPIリクエストについている署名のタイムスタンプが古いよ!というエラーですね。AWSのAPIを呼ぶときのエラーとしてはポピュラーなものですが、手元のMacの時刻が特にずれている様子はありません。"Docker for Mac time sync"などでググると原因が見えてきました。

Docker for Macの内部で利用している仮想化ソフトウェアのxhyveが、macOSのスリープ時に仮想マシンの時刻をうまく扱えていないようです。以下のIssueとしても挙がっていますが、未解決のようです。

対処方法

現時点では、手動で仮想マシンの時刻合わせを行うしかなく、以下の二通りが比較的簡単そうでした。

  • GUI: Dockerの再起動
  • CUI: ハードウェアクロックからの時刻同期

GUI: Dockerの再起動

Dockerの再起動によって仮想マシンも一緒に再起動されるようです。Docker for Macの常駐アプリの[restart]ボタンで再起動が実行できます。

docker-timesync01

実行前

$ LANG=C date -u; docker run -ti --rm alpine /bin/date
Tue Dec  6 03:35:43 UTC 2016
Tue Dec  6 03:35:41 UTC 2016

実行後

$ LANG=C date -u; docker run -ti --rm alpine /bin/date
Tue Dec  6 03:37:11 UTC 2016
Tue Dec  6 03:37:13 UTC 2016

コンテナの起動で時間が余計にかかるので、2,3秒遅れになるのが通常です。

CUI: ハードウェアクロックからの時刻同期

ターミナルであれば、コンテナ内でハードウェアクロックからの時刻同期を実行するのがお手軽です。xhyve環境でのハードウェアクロックがMac側のシステムクロックないしハードウェアクロックに相当するようなので、hwclock -sで同期させます。ホスト側のシステムクロックを変更するので--privilegedオプションが必要な点に注意してください。

$ LANG=C date -u; docker run -ti --rm alpine /bin/date
Tue Dec  6 03:43:34 UTC 2016
Tue Dec  6 00:05:04 UTC 2016
$ docker run --rm --privileged alpine hwclock -s
$ LANG=C date -u; docker run -ti --rm alpine /bin/date
Tue Dec  6 03:44:04 UTC 2016
Tue Dec  6 03:44:06 UTC 2016

同期しましたね!

ちなみに、実行するDockerイメージはdateコマンドとhwclockコマンドが含まれる任意のイメージで良いのですが、軽量なAlpine Linuxのイメージだとこのような単発コマンドを実行するときにサクッと動かせて便利ですね。

まとめ

Docker for MacでAWSにアクセスするときには時刻のずれが問題になるという話と、対処方法として時刻を同期する手順をご紹介しました。以前のDocker Toolboxと比べて、コンテナを実行する仮想マシンの存在はより薄く、意識することは少なっていますが、トラブルになると仕組みを理解する必要が出てくるものですね。