Dockerでソースコードをコンテナに入れる（マウントする）には？【Windows10Home】

## はじめに

初めてDockerを扱う際、多くの素晴らしい記事やチュートリアルのおかげで、イメージやコンテナの起動、削除をすぐに実施することができました。
しかし、恥ずかしながら「コンテナは起動したけど__結局どうやってソースコードをコンテナの中に反映すればよいの__」という状態になり、すぐに理解できず苦しんでしまいました。
また、WindowsHome独特の問題にも躓きましたので備忘録も兼ねて、私と同じような悩みをもつ初心者の方を対象に、今回はその解決策についてご紹介したいと思います。

以降の運用方法は、比較的小規模の開発を想定しています。（私自身、大規模なWebシステムで用いるというよりは、自前の機械学習環境の保存や共有に用いています。）


## 環境

- Windows10 Home 64bit
- Docker
    - Client 19.03.1
    - Server 19.03.5

WindowsHomeへのDockerインストールは下記の記事を参考にさせていただきました。
- [windows 10 home で docker を導入するメモ](https://qiita.com/idani/items/fb7681d79eeb48c05144)


## 設定ファイルの準備

実現したいことは、__指定したディレクトリ配下の変更がコンテナにも反映される状態を作成したい__ということです。これは、コンテナのボリューム（メモリ領域）と、ホストPC（Dockerを起動しているPC）のメモリ領域を共有（マウント）させることで実現できます。
Dockerfileとdocker-compose.ymlという二種類のファイルを用意する必要があります。例として下図のようなファイル構成を想定します。

```:ファイル構成
|-Dockerfile
|-docker-compose.yml
|-hello.py
```

### Dockerfileの例

Dockerファイルは独自のDockerImageを作成するためのファイルです。ここではTensorFlowのイメージを用いることを想定して下記のように記述します。

```docker:Dockerfile
FROM tensorflow/tensorflow
WORKDIR /usr/src/app
COPY . .
```

簡単に各コマンドを紹介します。

|コマンド|概要|
|-----|-----|
|FROM|DockerHubからダウンロードするイメージを指定します。|
|WORKDIR|イメージ内の作業ディレクトリを指定します。|
|COPY|HOST（今回の場合はWindowsHome）からコンテナにファイルをコピーします。一つ目の引数がホスト側のディレクトリ、二番目の引数がコンテナ側の作業ディレクトリ（直前に指定した/usr/src/app）を表しています。|


### docker-compose.ymlの例

続いてdocker-compose.ymlです。DockerComposeは複数のコンテナを並列して動作させる場合に使用するサービスですが、コンテナが単独の場合でもVolumeの設定を記述しておけるので便利です。

```yml:docker-compose.yml
version: '3'
services:
    app:
        build: .
        container_name: py-container
        volumes:
            - .:/usr/src/app
        tty: true
```

簡単に各コマンドを紹介します。

|コマンド|概要|
|-----|-----|
|build|使用するDockerfileの保存ディレクトリを指定しています。|
|container_name|コンテナ名を指定しています。|
|volume|対応させるメモリ領域を指定します。一つ目の引数がホスト側のディレクトリ、二番目の引数がコンテナ側のディレクトリ（/usr/src/app）を表しています。|
|tty|コンテナが起動した後に標準入力を受け付けられるようにしています。|


### pythonファイル

サンプルとして以下を用意しました。

```py:hello.py
def greeting():
    print("Hello World")

if __name__ == "__main__":
    greeting()
```

### Windows Homeの際に注意すべきこと

WindowsHomeでDockerを起動する際は、Virtual Boxを介して起動していることに相当しています。そのため、マウントできるメモリ領域もVirtual Boxの設定に依存します。デフォルトではUserフォルダ配下がマウントできるようになっていますので、__コンテナにマウントさせたいファイルはUserフォルダ配下に保存する__ようにするとよいです。なお、他のディレクトリをマウントさせる場合は、Virtual Boxの設定を変更する必要があります。

## dockerの実行

Windows Homeの場合は、デスクトップにできている「Docker Quickstart Terminal」のショートカットから起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447885/f0704557-cbe3-cd01-68aa-f2482256977e.png)

ターミナル上ではLinuxライクな操作が可能です。以下の3ステップでコンテナを起動します。

1. 作成した一連のファイルが保存されているディレクトリに移動します。(前節でも記載した通り、「C:\\Users」配下であることを確認してください。)

2. まず、下記のコマンドで、docker-compose.ymlの情報をもとにコンテナを作成し、バックグランドで起動させます。

```
docker-compose up -d
```

3. 次に、下記のコマンドでコンテナ内に入ります。（正確にはコンテナが標準入力を受けつけられる状態にします。）

```
docker exec -it <コンテナ名> bash 
```
<コンテナ名>には今回の場合、ymlファイルで記載したpy-containerが入ります。

コンテナ内のファイルを確認するために「ls」コマンドを実行すると、確かにファイルが認識されていることが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447885/1699db3b-5bac-13e5-d7b9-6ca9a9160bc7.png)

コンテナを起動したままで、ホスト側のhello.pyで出力される文字列を「Changed Hello World」変更すると、下図のようにその変更が正しく認識されていることを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447885/a7499bf8-0535-c105-2d44-5a53299170c7.png)

以上で、ホスト側のソースコードの変更がコンテナ内に反映される状態を実現できました。


## まとめ

今回は、コンテナを作成した後ソースコードやその変更をコンテナ内に反映させる方法を紹介しました。
- Dockerfileとdocker-compose.ymlを用意すること。
- 特別な設定をしない限り、WindowsHomeの場合は、マウントするホスト側のディレクトリはC:\\Users配下にする必要があること。

を紹介しました。より効率的な方法などありましたら、教えていただけますと幸いです。

## 参考文献

- [windows 10 home で docker を導入するメモ](https://qiita.com/idani/items/fb7681d79eeb48c05144)
- [Docker for WindowsでWindowsの任意のフォルダをコンテナにマウントする](https://roundwide.com/ja/mount-windows-folder-to-docker-container/)
- [Docker公式サイト](https://docs.docker.com/reference/)