Mac上でDocker起動だけVagrant内で行い開発作業はすべてホスト側でするための手順

# 背景
Docker for Mac を使っていると、これを書いている2018年11月時点の最新版（18.06.1-ce-mac73）を使っていても、不意に

```
sh: 0: getcwd() failed: No such file or directory
```

とかなんとかでまともに動作しなくなり、急に運ゲーに持ち込まれることがある（[関連issue]( https://github.com/docker/for-mac/issues/1509)）。
それに、ホスト・ゲスト間のファイル共有の遅さの問題などもある（`cached`オプションで改善されていそうだけど。[該当の release note](https://docs.docker.com/docker-for-mac/release-notes/#docker-community-edition-17060-ce-mac18-2017-06-28)）。

そもそも Docker は道具として使えればええやという意識の低さの持ち主としては、OS X 上で Docker 使うことによって生じる面倒に向き合いたくないので、いまさらながら Vagrant + Docker という構成を試したところ、個人的には結局はこれが正解だったので、その手順をメモしておく。　

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">そういや Docker for Mac で <a href="https://t.co/WGDNeTxSV2">https://t.co/WGDNeTxSV2</a> が頻発するので Vagrant でコンテナ起動することにしてから快適になった</p>&mdash; 実装レビューマージ (@keik_117) <a href="https://twitter.com/keik_117/status/1063582000848691200?ref_src=twsrc%5Etfw">2018年11月16日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 手順

ホスト側で、Docker 用の VM を管理する Vagrant 設定を作る。今回は ~/vagrant に。
VM の OS には、個人的に馴染みがあるので CentOS を使う。

```
% mkdir -p  ~/vagrant/for-docker
% cd ~/vagrant/for-docker
% vagrant init centos/7
```

Vagrantfile を編集する。

```
% emacsclient -n Vagrantfile
```

以下のように編集。理由はコメントを参照。

```rb
Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"

  # メモリを増やしておく
  config.vm.provider "virtualbox" do |v|
    v.memory = 4096
    v.cpus = 2
  end

  # VM 上で初めから Docker を使えるようにしておく
  config.vm.provision "docker"

  # ホスト側にポートフォワーディングして Web の画面を見れたりデータベースアクセスできたりするようにしておく
  config.vm.network "private_network", ip: "172.12.8.150"
  config.vm.network "forwarded_port", host: 4000, guest: 3000 # Web 用
  config.vm.network "forwarded_port", host: 4306, guest: 3306 # DB(MySQL) 用

  # ホスト側の docker-compose.yml などのファイルを VM 内で参照するため共有しておく
  config.vm.synced_folder "/Users/kato-kei/work", "/home/vagrant/work", type: "nfs"
end
```

VM を起動し、ログインする。

```
% vagrant up
% vagrant ssh
[vagrant@localhost ~]$
```

VM 環境には docker-compose がインストールされていないので https://github.com/docker/compose/releases にある手順でインストールする。
Vagrant Box `centos/7` だと sudo が必要。

```
[vagrant@localhost ~]$ sudo curl -L https://github.com/docker/compose/releases/download/1.23.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
[vagrant@localhost ~]$ sudo chmod +x /usr/local/bin/docker-compose
```

Docker コンテナを起動する。

```
[vagrant@localhost ~]$ cd work/my-project
[vagrant@localhost my-project]$ docker-compose up -d
```

Docker コンテナ内で Web サーバが :3000 で開くようになっているという前提で、Vagrantfile 内で VM の :3000 をホストの :4000 にポートフォワーディングしているので、ホスト側で localhost:4000 を開くと画面が出る。同様に MySQL もホスト側で :4306 でアクセスできる。

これで開発時は `vagrant up; vagrant ssh` して VM 内で `docker-compose up -d` さえしておけば、あとはすべてホスト側で、 Rails アプリのソースコードなり `webpack -w` した状態でフロントエンドのソースコードなりを変更し、その結果をブラウザやデータベースクライアントで確認する、という実装作業ができる。

# [おまけ] Vagrant Box `centos/7` で Python 環境作る

ECR で Dockerfile を管理している場合などに `aws-cli` が必要だけど、CentOS 7 の system にプリインストールされている Python には pip すら付属していない状態なので、せっかくだから pyenv で Python 環境を作っておく。

Vagrant Box `centos/7` が最小構成なので、pyenv をインストールするために必要な Git がそもそも system にないのでインストール。

```
[vagrant@localhost ~]$ sudo yum install git
```

pyenv は https://github.com/pyenv/pyenv の README にある手順でインストールする。

```
# 手順が変わるかもしれないのと、上記の README が十分にわかりやすいのでそちらを見てくだされ。
```

Python 本体をインストールする前に、ビルドに必要なパッケージを https://github.com/pyenv/pyenv/wiki#suggested-build-environment を眺めて事前にインストールする。

```
[vagrant@localhost ~]$ sudo yum install gcc zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel tk-devel libffi-devel
```

ようやく Python 本体をインストールする。

```
[vagrant@localhost ~]$ pyenv install 3.7.1
[vagrant@localhost ~]$ pyenv global 3.7.1
[vagrant@localhost ~]$ python --version
Python 3.7.1
```

あとは普通に `pip` が使えるのでよしなに。

```
[vagrant@localhost ~]$ pip install --upgrade pip
[vagrant@localhost ~]$ pip install awscli
[vagrant@localhost ~]$ AWS_ACCESS_KEY_ID=XXXXXX AWS_SECRET_ACCESS_KEY=XXXXXX aws ecr get-login --region ap-northeast-1 --no-include-email
```