Vagrant+VirtualBoxによるDocker環境構築

#はじめに
これまで.NETの開発をメインでやってきて、一昨年からPHPのプロジェクトに参画した。
それまで VM Wareを使っていたとは言え、普段意識しないし、コンテナとかも使ったことが無かったが、
PHPのプロジェクトではVagrantやDockerなど（自分的には）最新技術に触れて衝撃を受けた。

今更ながら勉強する為、まずはPythonの開発環境をDockerで用意しようと考えたが、
Winodws 7 な環境しか手元にない。

Dockerは、LinuxもしくはWindowsではWindows 10 からしか使えないので、
Vagrant+VirtualBoxで用意した仮想環境（CentOS）へDockerを載せて環境を用意してみます。

# Vagrant
 - 構成情報を記載した設定ファイル（vagrantfile）を元に、仮想環境の構築から設定まで自動でやってくれます。
 - https://ja.wikipedia.org/wiki/Vagrant_(ソフトウェア)

# VirtualBox
 - 現在利用しているOS（Windows7）上で、別のOS（今回はCentOS）を実行できる仮想化ソフトウェア。
 - 現在利用しているOS（Windows7）をホストOS、VirtualBox上に構築したOS（CentOS）をゲストOSと呼ぶ。
 - ホストOSでは導入できないソフトウェア（今回はdocker）を利用したい場合や、開発チーム全体で開発環境を統一したい場合、もしくは単にホストOSを汚したく無い場合にも利用する。
 - https://ja.wikipedia.org/wiki/VirtualBox

# 今回の構築環境
 - Vagrant+VirtualBoxで、CentOSを載せて、そこでDockerを動作させコンテナを起動します。
 - イメージは↓こんな感じ。

![kankyo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477633/357302cd-51b8-246b-9afb-e9b30b07b24e.png)


# 用語の定義
ホストとかゲストとかが分かりにくいと思うので、この後の文章では以下のように用語を使います。

| Windows 7 | VirtualBox内のCentOS | CentOS内のDockerコンテナ |
|:--|:--|:--|
| ホスト | ゲスト 又は Dockerホスト | Dockerコンテナ | 

# インストール
全て仮想環境上で環境構築する為、基本的にWindows7環境は汚れませんが、
VagrantとVirtualBoxだけはインストールする必要があります。

* Vagrant
\\https://www.vagrantup.com/downloads.html

* VirtualBox
\\https://www.virtualbox.org/wiki/Downloads


# 環境構築（仮想環境構築）
コマンドプロンプトを起動し、適当なフォルダへ移動します。

```
> d:
> cd d:\work
```

CentOSのイメージをダウンロードします。（これ、結構かかります）

```
> vagrant box add centos/7
```

CentOS起動用のVagrantfileの雛形を作成します。

```
> vagrant init centos/7
```

作成したVagrantfileの雛形をカスタマイズします。
D:\work フォルダに Vagrantfileファイルが出来ているので、テキストエディタで開いて、以下の編集を行います。
以下の行のコメントアウトを解除するだけです。

```lang:Vagrantfile
35|  config.vm.network "forwarded_port", guest: 80, host: 8080
```

 - 35行目の編集はホストOSとゲストOS間のポートマッピング設定です。後でホストOSのブラウザからコンテナ上のWebAppへアクセスする為に必要です。

さあ、Vagrantを起動しましょう。

```
> vagrant up
```
カレントフォルダのvagrantfileを参照して、そこに記載してある仮想環境を構築、起動します。

恐らくこれで、仮想環境（CentOS）が起動しているので、仮想環境にSSHで接続しましょう。

```
> vagrant ssh
```

# 環境構築（コンテナ環境構築）
ここからはDockerコンテナを利用する為の準備をしていきます。

Dockerを利用するのに必要なパッケージ(yum-utils, device-mapper-persistent-data, lvm2)をインストールします。

```
$ sudo yum install -y yum-utils device-mapper-persistent-data lvm2
```

Dockerをダウンロードするリポジトリをyum(パッケージ管理)に追加します。

```
$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
```

yumのパッケージインデックスを更新(DockerのINSTALLやUPGRADEの前に一回実行することが推奨されている)

```
$ sudo yum makecache fast
```

最新版のDockerをインストールします。

```
$ sudo yum install docker-ce
```

Dockerデーモンを起動します。

```
$ sudo systemctl start docker
```

# Dockerコンテナ動作確認

これでDockerの起動まではできました。
（DockerイメージからDockerコンテナを作り出して起動する為のソフトウェアが動きました）
Dockerの動作確認の為、DockerイメージからDockerコンテナを起動して動作確認をしてみます。

ここでは、training/webappというWebアプリケーション動作確認用コンテナを持ってきて起動してみます。
（やっぱりブラウザとかで動いているのが見えるのがいいよね）

```
$ sudo docker run -d -p 80:5000 training/webapp python app.py
```
 - -dオプションはバックグランド実行用のオプションです。これが無いと、「training/webapp」が終わるまで他のコマンドが打てません。
 - -pオプションはポートマッピングです。vagrantfileでホストOSとゲストOS間で8080→80でマッピングしたポートを、さらに80→5000にマッピングします。
 - 「python app.py」は「training/webapp」コンテナ内で実行するコマンドです。（とりあえずおまじないだと思って入力）

「training/webapp」イメージは350MBくらいあるので、少しダウンロードに時間がかかります。
動作確認はホストOS（Windows7）のブラウザで以下のURLを指定してください。

```
http://localhost:8080/
```

以下のように出てくればOKです。

![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477633/5683eea2-5bb8-ec34-151c-708f6698934c.png)


ホストOSとゲストOS間のポートマッピングはvagrantfileで 8080→80 で設定されており、
上記のdocker runコマンドで -p を指定して、ゲストOSとdockerコンテナ間のポートマッピングを 80→5000 で設定しています。

その為、ホスト側でのポート指定は8080になります。

# コンテナの停止、他
Dockerコンテナを確認します。

```
$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                  NAMES
1c763df10ac5        6fae60ef3446        "python app.py"     About a minute ago   Up About a minute   0.0.0.0:80->5000/tcp   frosty_wing
```

起動しているDockerコンテナをコンテナID（ここでは、1c763df10ac5）を指定して、停止します。

```
$ sudo docker stop 1c763df10ac5
```

停止されたか確認しましょう。（先ほどまで表示されていたコンテナ（1c763df10ac5）が消えています）

```
$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                  NAMES
```

起動しているコンテナは無くなりましたが、コンテナ自体は残っていて、-aオプションで全てのコンテナが表示できます。

```
$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                       PORTS               NAMES
1c763df10ac5        6fae60ef3446        "python app.py"     8 minutes ago       Exited (137) 3 minutes ago                       frosty_wing
```

このコンテナも削除してみましょう。
コンテナの削除は docker rm です。

```
$ sudo docker rm 1c763df10ac5
$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                       PORTS               NAMES
```

これでコンテナは消えましたが、イメージは残っています。

```
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
training/webapp     latest              6fae60ef3446        4 years ago         349MB
```

折角なので、イメージも削除しましょう。
イメージの削除は docker rmi です。

```
$ sudo docker rmi 6fae60ef3446
Untagged: training/webapp:latest
Untagged: training/webapp@sha256:06e9c1983bd6d5db5fba376ccd63bfa529e8d02f23d5079b8f74a616308fb11d
Deleted: sha256:6fae60ef344644649a39240b94d73b8ba9c67f898ede85cf8e947a887b3e6557
Deleted: sha256:875bde2b9e2d99e7c1362993645a474fe621475c6fc1b1623c9ed5312b7bdeae
Deleted: sha256:bbdb5ee3757ef8f2633694016df5840fc3410422b37c22f98c0300e295ce75cc
Deleted: sha256:d718446240e3f48a904ad4bbf2a1f61737c5d70df35b8210d674a9517cdc9803
Deleted: sha256:a890440f4933412f9aafb056eb2f07f2276ed756631a81e960d4a8a6de5857a3
Deleted: sha256:68a74799a9e67953725058ef21a530f100025088943446aa60c73fba7beebd47
Deleted: sha256:b23e4b6b440d0e9ab4ffd7852fbf81edd6d5eb606e24d4950d83502e14af2856
Deleted: sha256:f115b0453c71fb4d21fdb6f579201984bd5033ae28ed5908978576a19282418b
Deleted: sha256:b0da82df3229cd06a2992449f2310caaa42f09fdfb088f4a98c5ea587ea85c7e
Deleted: sha256:f6f162dad6e64715d3d07e21d4574733860a557f2f89228d07909c1f6f04e882
Deleted: sha256:088f9eb16f16713e449903f7edb4016084de8234d73a45b1882cf29b1f753a5a
Deleted: sha256:799115b9fdd1511e8af8a8a3c8b450d81aa842bbf3c9f88e9126d264b232c598
Deleted: sha256:3549adbf614379d5c33ef0c5c6486a0d3f577ba3341f573be91b4ba1d8c60ce4
Deleted: sha256:1154ba695078d29ea6c4e1adb55c463959cd77509adf09710e2315827d66271a
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
```


# バイバイ

コンテナを抜けます。

```
$ exit
```

仮想マシン（centos）を停止します。

```
> vagrant halt
==> default: Attempting graceful shutdown of VM...
```

仮想マシンの一覧は以下のコマンドで確認できます。

```
> vagrant box list
centos/7       (virtualbox, 1905.1)
```

# おわりに
とりあえず、Vagrant+VirtualBox上のCentOSでDockerコンテナを起動するところまでできました。

当初は仮想環境とDockerイメージとDockerコンテナがゴチャゴチャになっていましたが、
実際に手を動かして環境を作っていくと、理解が深まりました。

# 参考
https://www.tohuandkonsome.site/entry/2018/03/21/193730
https://qiita.com/inakadegaebal/items/be9fecce813cebec5986