BargeOSでPython環境を作る

[10]: https://qiita.com/daichannel/items/e4928c07f613ea9154c3 "Vagrant+VirtualBoxによるDocker環境構築"
[20]: https://qiita.com/A-I/items/8dc7ddc52e6038b5c74b "Barge（Docker ホスト用軽量 OS）って？"
[30]: https://qiita.com/daichannel/items/e4928c07f613ea9154c3#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB "Vagrant + VirtualBox のインストール"
[40]: https://moremagic.hateblo.jp/?page=1479098197 "Barge（Docker ホスト用軽量 OS） を試してみる"
[50]: https://github.com/docker-library/official-images/tree/master/library "公式の認定Dockerイメージ一覧"

# はじめに
[前回の記事][10]で CentOS上ではDocker環境を構築できた。
しかし、CentOSはデカイ（およそ2GB）。
ダウンロードに時間もかかるし、起動も遅い。

そこで、[気軽に Docker を使いたい人向けの軽量な Docker ホスト（VM）用 Linux OS][20]、BargeLinuxでPython開発環境を構築することにする。
(Python環境を作るだけで、Pythonのお話はこの記事には出てきません）

また、この記事のベースは[前回記事][10]なので、先にそちらを参照してください。

# BargeLinuxとは
BargeLinux はDockerホスト用に無駄なものを全て省いた超軽量LinuxOSで、以下のような特徴を持っています。
- 最軽量
- 高速ブート
- Docker のバージョンを切り替え可能
- glibc、bash、dumb-init を標準搭載
- パッケージ・インストーラ
- Vagrant 用 Box
- VirtualBox に最適化
- Raspberry Pi 3 のサポート

ラズパイのサポートは今のところあまり自分には関係ないですが、それ以外は理想的なOSです。
何も無さ過ぎて後で大変になるかもしれないけど、Dockerコンテナ上でいろいろ用意できるからそれも大丈夫だと割り切って使わせてもらいます。

こういうのを無償で提供している方、すごいです。

# 今回の構築環境
Vagrant＋VirtualBox上で、BargeLinuxを動作させて、そこでDockerを起動してPython開発環境を用意します。
こんな↓イメージです。
![BargeKankyo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477633/192b315e-efe6-f70d-4a48-ac018a4574c0.png)

# 用語の定義
前回も書きましたが、一応、用語の定義をもう一度書いておきます。

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

# Vagrant + VirtualBox のインストール
[前回の記事][30]を参照してください。

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

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

BargeLinuxのイメージをダウンロードします。（速い！！）

```
> vagrant box add ailispaw/barge
```

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

```
> vagrant init ailispaw/barge
```

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

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

BargeLinuxを起動しましょう。

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

恐らくこれで、ゲストOSが起動しているので、仮想環境にSSHで接続しましょう。

```
> vagrant ssh
Welcome to Barge 2.13.0, Docker version 1.10.3, build 20f81dd
```
Dockerのバージョンが表示されるのはBargeLinuxならでは。

# Dockerコンテナ動作確認
Dockerはインストール済みなので、試験的にtraining/webappコンテナを起動してみます。

```
$ sudo docker run -d -p 80:5000 training/webapp python app.py
Unable to find image 'training/webapp:latest' locally
latest: Pulling from training/webapp

e190868d63f8: Pull complete
909cd34c6fd7: Pull complete
0b9bfabab7c1: Pull complete
a3ed95caeb02: Pull complete
10bbbc0fc0ff: Pull complete
fca59b508e9f: Pull complete
e7ae2541b15b: Pull complete
9dd97ef58ce9: Pull complete
a4c1b0cb7af7: Pull complete
Digest: sha256:06e9c1983bd6d5db5fba376ccd63bfa529e8d02f23d5079b8f74a616308fb11d
Status: Downloaded newer image for training/webapp:latest
c03f4bcfebc23053ec02cfce63252401f6471f9f9d77b65ee8e07c488295b976
```
ホストOS（Windows7）からlocalhost:8080にアクセスしてもらえれば、以下のような結果を得られるはずです。
![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477633/af74877e-743e-0f1a-7428-949c1df05a8b.png)

念のため、コンテナを停止して、削除しておきましょう。
後で同じコンテナを起動すると、コンテナがたくさん出来てストレージを無駄にするので。

```
$ docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                  NAMES
2757d7084e0a        training/webapp     "python app.py"     8 minutes ago       Up 4 seconds        0.0.0.0:80->5000/tcp   reverent_euclid
$ docker stop 2757d7084e0a
2757d7084e0a
$ docker rm 2757d7084e0a
2757d7084e0a
```

# Dockerの更新
BargeLinuxの特徴に、「Docker のバージョンを切り替え可能」とあったので、Dockerを安定版の最新バージョンに更新してみます。
ちなみに起動時点のバージョンは以下の通り。

```
$ docker --version
Docker version 1.10.3, build 20f81dd
```

更新は簡単です。
バージョン番号を指定して、Dockerデーモンを再起動するだけ。

```
$ sudo /etc/init.d/docker restart v18.06.3-ce
docker[922]: Loading /etc/default/docker
WARNING: Possible Forward-Incompatibility of libnetwork
Once you upgrade Docker to v1.12 or newer, if you downgrade back,
you may need to initialize /var/lib/docker/network/files/local-kv.db.
Downloading v19.03.1 ...
docker[922]: Stopping Docker daemon
docker[922]: Setting ulimit 1048576
docker[922]: DOCKER_RAMDISK=
docker[922]: Docker version 19.03.1, build 74b1e89e8a
docker[922]: Starting Docker daemon -D -s overlay -g "/var/lib/docker" -H unix:// -H tcp://0.0.0.0:2375 --userland-proxy=false
$ docker --version
Docker version 18.06.3-ce, build d7080c1
```

動作確認用に、training/webappコンテナを動かしてみましょう。

```
$ sudo docker run -d -p 80:5000 training/webapp python app.py
```
![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477633/de011c5c-93f9-619c-d842-cfb6e20e58db.png) 
問題なく動作しています！

# Pythonコンテナを使う
[公式の認定Dockerイメージ一覧][50]から、Pythonのイメージをダウンロードします。

```
$ docker pull python
Using default tag: latest
latest: Pulling from library/python
Digest: sha256:4432d65bd7da4693bb9365c3369ed5c7f0cb472195a294c54d1b766751098f7b
Status: Image is up to date for python:latest
```

とりあえずPythonのソースを保存し、実行するディレクトリを作成します。
ここでは、「project_guest_dhost」ディレクトリを作成し、その中へ移動します。

```
$ mkdir project_guest_dhost
$ cd project_guest_dhost
```

では、コンテナを立ち上げましょう。

```
$ docker run -it -w /project_dguest -v $(pwd):/project_dguest python bash
```
プロンプトが、$ から # に変わったと思います。

-iは、Keep STDIN open even if not attached で、標準入力を開き続けます。
-tは、Allocate a pseudo-TTY で、疑似ttyを割りあてます。
標準入力を開き続け、そこを操作出来るようにします。
つまり、手元の環境で、docker内入力ができるようにします。

-wは、ワークディレクトリの指定です。
コンテナ内に作られるワークディレクトリなので、名前は何でも良いです。

-vは、dockerホストのワークディレクトリを、コンテナのワークディレクトリにマウントします。
Dockerホストのワークディレクトリは「/home/bargee/project_guest_dhost」ディレクトリです。
つまり、project_guest_dhostディレクトリは、pythonコンテナの/project_dguestディレクトリにマウントされています。

とりあえず、pythonのバージョンを確認してみます。

```
# python --version
Python 3.7.4
```

一旦、exitコマンドでDockerホスト側に戻って、Pythonソースを用意します。
ここでは、単純に「Hello Python World」と標準出力する、単純なソースを用意します。

```
# exit
$
```
```hello_python.py
print("Hello Python World")
```

project_guest_dhostフォルダに、hello_python.py を配置したら、再度新しいコンテナを起動します。
先ほど起動したコンテナは残っていますが、新しく作成したhello_python.pyファイルがマウントされていない為です。

```
$ docker run -it -w /project_guest_dhost -v $(pwd):/project_guest_dhost python bash
```

実行してみましょう。

```
# python hello_python.py
Hello Python World
```

コンテナを抜けて、SSHログインしているBargeLinuxも抜けます。

```
# exit
$ exit
>
```

上記のhello_python.pyのように、ゲストOSで作成したソース（pyファイル）を永続的に保存する為、ホストOSとゲストOSのディレクトリをマウントします。
ホストOSのディレクトリを用意します。

```
> mkdir project_host
```

vagrantfileの47行目に以下を追加して、ホストOSのproject_hostフォルダを、ゲストOSの /home/bargee/project_guest_dhostフォルダへマウントします。

```vagrantfile
47|  config.vm.synced_folder "project_host", "/home/bargee/project_guest_dhost", mount_options: ['dmode=777','fmode=777']

```

vagrant reloadで仮想環境（ゲストOS）を再起動します。

```
> vagrant reload
==> default: Attempting graceful shutdown of VM...
==> default: Checking if box 'ailispaw/barge' is up to date...
==> default: Clearing any previously set forwarded ports...
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 2375 (guest) => 2375 (host) (adapter 1)
    default: 80 (guest) => 8080 (host) (adapter 1)
    default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Running 'pre-boot' VM customizations...
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: bargee
    default: SSH auth method: private key
==> default: Machine booted and ready!
==> default: Mounting shared folders...
　　// ↓これが表示されればマウントOKです。
    default: /home/bargee/project_guest_dhost => C:/Users/hajime.iwase/tbc_workspace/test_barge_v2/project_host
==> default: Machine already provisioned. Run `vagrant provision` or use the `--provision`
==> default: flag to force provisioning. Provisioners marked to run always will still run.
> vagrant ssh
Welcome to Barge 2.13.0, Docker version 18.06.3-ce, build d7080c1
$
```

仮想環境を再起動したので、Dockerコンテナは全て消えてます。

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

もう一度、project_guest_dhostディレクトリに移動し、hello_python.py を作成します。

```
$ cd project_guest_dhost
$ vi hello_python.py
```

では、コンテナを起動して、実行してみましょう。

```
$ docker run -it -w /project_dcon -v $(pwd):/project_dcon python bash
# python hello_python.py
Hello Python World
```

ホストOSでソースを更新して、再実行してみましょう。

```hello_python.py
print("Hello Python World")
print("Add Line") # 追加
```
```
# python hello_python.py
Hello Python World
Add Line
```

これで、ホストOSでソースを更新して、コンテナ実行して手軽にPython開発を行えます。


# おわりに
やっていることは大したこと無いのに、記事を丁寧に書きすぎている気もしてきた。。。
次回からもう少し端折ろうかな。