windows IIS を macOS で立ち上げる

# はじめに
- WindowsのWebサーバーであるIISは基本的にはWindowsOS上でしか動作しない
- docker imageも公式で用意されているが、`Docker for mac`やlinux版では動作しない
- そのためmac環境では通常だとIISを立ち上げることが難しい
- 本記事はそんな面倒な制約があるIISをmac上で動かす方法を記述する

# 環境

- macOS BigSur ver11.6.5
- windows server2019 を立てる

# 概要

- `ホストOS(macOX) -> ゲストOS(VirtualBox-windows server2019) -> ゲストOS上のゲストOS(IIS Docker container)`という通信経路
  - `localhost:8080 -> localhost:8080(VirtualBox) -> localhost:80(IIS)`
- windows 用 docker image である [IIS](https://hub.docker.com/_/microsoft-windows-servercore-iis) を vuitual box 上で起動して、ホスト PC からブラウザ経由でアクセスできるまで
- image tag は`windowsservercore-ltsc2019`

# 流れ

1. Vagrant と Virtual Box のインストール
1. Docker machine のインストール
1. Windows Server 2019 の Docker machine を構築する
1. VirtualBox で NAT 設定
1. IIS Docker image を run する
1. ブラウザから確認

## Vagrant と Virtual Box のインストール

- `brew install vagrant virtualbox --cask`
- virtualbox をインストールする時にセキュリティとプライバシーの設定に関する画面がでるので、許可しておく。
  ![設定画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641313/0f33b87d-474f-8ee7-a0df-833b8095b00e.png)

## Docker machine のインストール

- **重要** docker machine の最新版をインストールすること
  - `fatal error: MSpanList_Insert`のようなエラーが発生する可能性がある
- [docker machine git](https://github.com/docker/machine/releases/)

  ```bash
   curl -L https://github.com/docker/machine/releases/download/v0.16.2/docker-machine-`uname -s`-`uname -m` >/usr/local/bin/docker-machine && \
   chmod +x /usr/local/bin/docker-machine
  ```

## Windows Server 2019 の Docker machine を構築する

- [StefanScherer/windows-docker-machine](https://github.com/StefanScherer/windows-docker-machine)を利用する
- `2019-box`を使う

  ```bash
   git clone https://github.com/StefanScherer/windows-docker-machine
   cd windows-docker-machine
   vagrant up 2019-box
  ```

- Docker machine の確認

  - `vagrant up`コマンドが終わったあと、Docker machine ができているかの確認をする

  ```bash
      $ docker-machine ls

      NAME       ACTIVE   DRIVER    STATE     URL                        SWARM   DOCKER          ERRORS
      2019-box   -        generic   Running   tcp://192.168.99.90:2376           v18.03.1-ee-3
  ```

  - 自分は下記のように表示されたが、その後の作業に影響はなかったため、先に進んだ

    ```bash
      NAME       ACTIVE   DRIVER    STATE     URL                        SWARM   DOCKER    ERRORS
      2019-box   *        generic   Running   tcp://192.168.59.90:2376           Unknown   Unable to query docker version: 400 Bad Request: client version 1.15 is too old. Minimum supported API version is 1.24, please upgrade your client to a newer version
    ```

- Docker machine の利用

  - docker を virtual box で起動した windows 環境の Docker に切り替える
  
    ```bash
        $ eval $(docker-machine env 2019-box)
    ```

  - 切り替わっているかの確認

    - `windows docker machine`

      ```bash
          $ docker version
          Client:
           Cloud integration: 1.0.17
           Version:           20.10.8
           API version:       1.41
           Go version:        go1.16.6
           Git commit:        3967b7d
           Built:             Fri Jul 30 19:55:20 2021
           OS/Arch:           darwin/amd64
           Context:           default
           Experimental:      true

          Server: Docker Engine - Community
           Engine:
            Version:          20.10.6
            API version:      1.41 (minimum version 1.24)
            Go version:       go1.13.15
            Git commit:       8728dd2
            Built:            Fri Apr  9 22:45:40 2021
            OS/Arch:          windows/amd64
            Experimental:     false
      ```

    - `windows/amd64`になっていることが確認できる
      - コマンドを打ったターミナルでのみ切り替わっている状態

- Docker machine を戻す

  - macos 上の docker machine に戻したい時

       ```bash
            $ eval $(docker-machine env --unset)
       ```

  - 切り替わっているかの確認

    - `macos docker machine`

        ```bash
            Client:
             Cloud integration: 1.0.17
             Version:           20.10.8
             API version:       1.41
             Go version:        go1.16.6
             Git commit:        3967b7d
             Built:             Fri Jul 30 19:55:20 2021
             OS/Arch:           darwin/amd64
             Context:           default
             Experimental:      true

              Server: Docker Engine - Community
               Engine:
                Version:          20.10.8
                API version:      1.41 (minimum version 1.12)
                Go version:       go1.16.6
                Git commit:       75249d8
                Built:            Fri Jul 30 19:52:31 2021
                OS/Arch:          linux/amd64
                Experimental:     false
               containerd:
                Version:          1.4.9
                GitCommit:        e25210fe30a0a703442421b0f60afac609f950a3
               runc:
                Version:          1.0.1
                GitCommit:        v1.0.1-0-g4144b63
               docker-init:
                Version:          0.19.0
                GitCommit:        de40ad0
        ```

    - `linux/amd64`になっていることが確認できる
    
## VirtualBox で NAT 設定

- `2019-box`の NAT 設定を行い、ホスト OS と VirtualBox 間を通信できるようにしておく
- virtualbox のウィンドウを開く
  - brew で install したのでアプリは開ける状態になっている
    ![launchpad](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641313/a5a22bd3-b26d-9a4f-964c-74dffd98751e.png)

- マネージャーで`2019-box`が実行中であることが確認できる
  ![manager](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641313/49a5b3da-e6bb-2df7-b942-b7fc5ffb051e.png)

- 設定->ネットワーク->高度からポートフォワーディングのボタンをクリック
  ![network](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641313/8c15fc47-584e-00a3-4e42-c46d2c90cb87.png)

- `http tcp localhost 8080`の設定を追加する(他の設定はデフォルトで設定されていた)
  ![portfoward](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641313/aca9861c-4b97-2cd3-1772-1683d3d317e0.png)

## IIS Docker image を run する

- [Windows IIS](https://hub.docker.com/_/microsoft-windows-servercore-iis)イメージを run する
- タグは`windowsservercore-ltsc2019`

  - `windows docker machine`
    ```bash
        docker run --entrypoint powershell -it -p 8080:80 mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
    ```

## ブラウザから確認

- ブラウザから`http://localhost:8080`でアクセスすると、IIS の初期画面が表示される
  ![初期画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641313/b7b37092-48c9-0f40-8438-734d64defc4e.png)

# その他

- IIS のデフォルト画面の場所は`C:\inetpub\wwwroot\iisstart.htm`
- virtualbox をシャットダウン
  - `macos docker machine`
    ```bash
        vagrant halt
    ```
- IIS 上に資材のデプロイ
  - `windows docker machine`
    ```bash
      docker cp ./ [container name]:"C:\inetpub\wwwroot"
    ```

# トラブルシュート

## ブラウザから IIS にアクセスできない

- 各階層それぞれで IIS に繋がるか確認していく
  - IIS docker 上で Web サーバが立ち上がっているか
    - docker container の中に入る
      - `windows docker machine`
        ```bash
            docker exec -it powershell [container name]
        ```
    - リクエストを叩く
      ```powershell
          Invoke-WebRequest http://localhost:80 -UseBasicParsing
      ```
  - Virtual box 上で IIS docker container に繋がるか確認していく
    - virtual box のマネージャーを開き、表示をクリックして画面を立ち上げる
      ![画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641313/4dd55c3e-d959-ae4a-b35c-2df19afd8fc1.png)

      ```
          curl localhost:8080
      ```

## 参考文献

- [Docker Machine のインストール](http://docs.docker.jp/v1.12/machine/install-machine.html)
- [MSpanList_Insert ｜ docker-machine コマンドでのエラー](https://qiita.com/ryomoucmei/items/678810b034d1f29a7ad0)
- [VirtualBox 上のゲスト OS にホスト OS から NAT でアクセスする](https://www.karakaram.com/virtualbox-port-fowarding/)
- [Docker for Windows で IIS ウェブサイトの開発環境を作る手順（シリーズその２）](https://qiita.com/yoshiwatanabe/items/a903f7855e8f1f014018)
- [Azure Automation で Invoke-WebRequest したあと Parse してくれない件](https://www.syuheiuda.com/?p=4991#respond)