ComputeEngine で CoreOS を選ぶとスタートアップスクリプトから docker が見えない


# 概要
<img src="https://upload.wikimedia.org/wikipedia/en/4/40/Container_Linux_Logo.png" width="420px"/>

[Google Compute Engine](https://cloud.google.com/compute/) で [CoreOS](https://coreos.com/) イメージ（coreos-stable-1298-7-0-v20170401） を使ってインスタンスを作成すると，スタートアップスクリプトから docker コマンドが使えないような気がする．

~~~
Apr 21 12:20:59 xxx.internal rkt[1110]: + /usr/bin/google_metadata_script_runner --script-type startup
Apr 21 12:20:59 xxx.internal startup-script[1361]: INFO Starting startup scripts.
Apr 21 12:20:59 xxx.internal startup-script[1361]: INFO Found startup-script in metadata.
Apr 21 12:20:59 xxx.internal startup-script[1361]: INFO startup-script: /tmp/startup-qconLt/tmpI9QQlX: line 29: /usr/bin/docker: No such file or directory
Apr 21 12:20:59 xxx.internal startup-script[1361]: INFO startup-script: /tmp/startup-qconLt/tmpI9QQlX: line 33: /usr/bin/docker: No such file or directory
Apr 21 12:20:59 xxx.internal startup-script[1361]: INFO startup-script: Return code 1.
Apr 21 12:20:59 xxx.internal startup-script[1361]: INFO Finished running startup scripts.
~~~

仕方ないので， [Ignition](https://coreos.com/ignition/docs/0.13.0/) 経由で　docker.service に依存するサービスとしてスタートアップスクリプトを送り込むことにした．（そもそもこっちが本来の使い方なのかもしれないが・・・）

# Ignition
Ignition は [cloud-init](https://cloudinit.readthedocs.io/en/latest/) のように起動設定を簡略化してくれるツールで，cloud-init とは異なり設定を JSON フォーマットで渡す．Compute Engine の場合， この設定を user-data という名前のメタデータ経由で渡すことができる（参考: [Ignition Config](https://coreos.com/os/docs/latest/booting-on-google-compute-engine.html)）

設定例は[この辺](https://github.com/coreos/ignition/blob/master/doc/examples.md) にあるのだが，今回はスタートアップスクリプト用の Systemd サービス Unit が定義できれば良いので，

```json:user-data
{
  "ignition": { "version": "2.0.0" },
  "systemd": {
    "units": [{
      "name": "example.service",
      "enable": true,
      "contents": "[Service]\nType=oneshot\nExecStart=/usr/bin/echo Hello World\n\n[Install]\nWantedBy=multi-user.target"
    }]
  }
}
```

この設定を編集して利用する．

units には，登録したい Systemd サービスの Unit を配列で指定する．各 Unit の設定は，name, enable, contents の三つの属性を持つオブジェクトとなっていて，各属性はそれぞれサービス名，enable にするか，そして unit ファイルの中身を表している．


# スタートアップスクリプト用サービス Unit
Docker が起動した後に実行されるようにしておく．

```startup.service
[Unit]
Description=Startup Script
Requires=docker.service
After=docker.service

[Service]
ExecStartPre=-/usr/bin/docker stop myservice
ExecStartPre=-/usr/bin/docker rm myservice
ExecStart=/usr/bin/docker run --name myservice jkawamoto/myservice
ExecStop=/usr/bin/docker stop myservice
Restart=always
Type=simple

[Install]
WantedBy=multi-user.target
```

（参考: [dockerコンテナをsystemdで管理させる](http://qiita.com/74th/items/e8dc1ac1295140413dc8)）

この unit ファイルを登録するための Ignition config ファイルは次の通り．

```json:user-data
{
  "ignition": { "version": "2.0.0" },
  "systemd": {
    "units": [{
      "name": "startup.service",
      "enable": true,
      "contents": "[Unit]\nDescription=Startup Script\nRequires=docker.service\nAfter=docker.service\n[Service]\nExecStartPre=-/usr/bin/docker stop myservice\nExecStartPre=-/usr/bin/docker rm myservice\nExecStart=/usr/bin/docker run --name myservice jkawamoto/myservice\nExecStop=/usr/bin/docker stop myservice\nRestart=always\nType=simple\n[Install]\nWantedBy=multi-user.target"
    }]
  }
}
```

あとは，このテキストデータを user-data という名前のメタデータとして渡せば良い．