こんにちは、サイオステクノロジー武井(Twitter:@noriyukitakei)です。今回は、第4回シリーズで、WSL2、Visual Studio Code、Docker、Windows Terminalなどの最新技術を用いて、Windows開発環境をグッとよくしましょうっていうお話をします。第4回目の今回は、Visual Studio CodeとDockerで開発環境の改善を実践してみます!!
- その1:まずは概要
- その2:WSL1&2のしくみ
- その3:WSL2、Windows Terminalで改善!!
- 今回はこちら → その4:Visual Studio Code、Dockerで改善!!
※ 本記事は技術評論社出版の「WEB+DB PRESS」Vol.117(詳細はこちら)に私が寄稿した「WSL 2、Docker、Visual Studio Code[最新]Windows開発環境」の記事をベースとしております。是非、WEB+DB PRESSの方も合わせてご覧ください!!
Windows開発環境の問題点のおさらい
本章では、今までご紹介したWSLやVisual Studio Codeに加え、さらにDockerを使うことによって、Windowsによる開発の利便性が加速する例を紹介します。
その前に、第1章〜第3章に渡って紹介してきました、Windowsの開発環境の問題点及びその改善方法をここでおさらいしておきます。
Windowsにおける開発においては「開発環境と実行基盤の差異」という問題に悩まされてきました。Windowsで開発したアプリケーションは、Linux上で本番稼働するというケースが多く、その違いによって、文字化けを始めとした想定外の事象が発生し、多くのエンジニア達を悩ませてきました。
その問題解決に大きく貢献したのがWSLです。従来の仮想環境とは異なり、数ステップでWindows上にLinuxを構築できるようになり、またWindowsとの親和性が高く、相互のファイルアクセスも簡単です。起動も高速で、使いたいときにすぐ使うことができます。
非常に有用なWSLですが、同様のアプローチでWindowsの開発における利便性を加速させるものとして「Docker」があります。本章では、このDockerの概要を説明するとともに、今まで紹介してきたWSLやVisual Studio Codeとのコラボにより、Windowsでの開発がどのように改善されるのかを記載致します。
Dockerによる開発スタイルの変化
まず、具体的な改善方法を説明する前に、Dockerとは何なのか、なぜ開発にDockerが必要なのかを説明します。
Dockerとは?
Dockerとは、コンテナ型の仮想環境を作成、配布、実行する仕組みです。では、コンテナとはなんなのかという疑問に至るわけですが、こちらは従来のVMWareなどの仮想環境と比較して説明致します。説明をわかりやすくするために、コンテナ型の仮想環境を「コンテナ」、従来型の仮想環境を「仮想化」と呼びます。
上図のホストOSは、仮想化ソフトウェアやコンテナを実行するPCのOSです。仮想化は御存知の通り、VMWareなどの仮想化ソフトウェアの上には、カーネルを内包したゲストOSが稼働し、さらにそのOS上でプロセスが稼働します。
対して、コンテナについては、仮想化ソフトウェアやゲストOSというものが存在しません。これは、Linuxカーネルの機能である「namespace」により、プロセス空間やネットワーク、ファイルシステムを分離し、さらにホストOSのカーネルを利用することになるので、コンテナ内にはカーネルを含む必要はありません。上図の「コンテナ」と記載のあるものが、namespaceによって区切られた空間であり、仮想化におけるゲストOSに相当します。このコンテナの中でUbuntuやCentOSといった様々なOSが稼働します。
つまり、コンテナの最大のメリットの一つは、カーネルを含まないことによる軽量化であり、軽量化を実現したことにより、可搬性が格段に向上しています。
そして、Dockerとは、コンテナの作成や削除、Dockerリポジトリ(Dockerコンテナのもととなるイメージを格納しているデータベース)からイメージを取得、アップロードしたりするツールになります。つまりコンテナの管理ツールです。
本特集では、Dockerの説明が主目的ではないため概要のみとしましたが、詳しくご存知になりたい方は、小生が執筆した以下の技術ブログをご覧頂けますと幸いです。
【連載】世界一わかりみが深いコンテナ & Docker入門 〜 その1:コンテナってなに? 〜
https://tech-lab.sios.jp/archives/18811
Dockerによる開発スタイル
先程、コンテナは可搬性が高いと説明しました。コンテナを稼働させるツールであるDockerが入っているPCやサーバーであれば、そのコンテナをどこでも動作させることができます。
つまり下図にあるような開発スタイルが実現可能になります。
図2 Dockerによる開発スタイル
-
開発リーダーはDockerfileとソースコードをGitリポジトリにpushします。
-
開発エンジニアは、GitリポジトリからDockerfileとソースコードをclone or pullします。
※開発エンジニアのPC上にあるGitで行われます -
開発エンジニアは、Dockerfileに従って、開発環境のコンテナを作成します。Dockerエンジンは、 Dockerfileの内容に従って、適宜DockerHubを参照します。
-
開発エンジニアは、修正したソースコードをGitHubにpush or pullします。
※これはDockerコンテナ内のGitから行われます。 -
開発リーダーは、GitHubにpushされたソースコードに基づき、Dockerイメージを作成、DockerリポジトリにPushします。
-
Kubernetesなどのコンテナオーケストレーターによって読み込まれて、本番環境が作成されます。
上記の流れでは、開発エンジニアのPC上に作成されたDockerコンテナと本番環境上に作成されたDockerコンテナは全く同じものです。
つまり、WSLのときと同様に「開発環境と実行基盤の差異」をなくすことができているのがわかります。
また、ここが重要なポイントなのですが、WSLとは違って、OSを含む環境ごと、GitリポジトリやDockerリポジトリを経由して、開発環境と本番環境との間でやり取りをしています。これにより以下の2つのメリットが生まれます。
-
開発エンジニアは、開発環境を構築する手間が省ける
Dockerイメージの中に既に開発に必要なものは入っているので、開発エンジニアが自ら開発環境を構築する必要はない。 -
開発環境と本番環境で全く同じ構成を実現できる。
開発環境で動作したコンテナをそのまま本番環境で動作させるので、開発環境と本番環境で動作するものは寸分違わず同じものとなる。
これは、先程説明した「コンテナの可搬性の高さ」によって実現できている開発フローです。例えば、これを従来の仮想化で実現した場合、カーネルを含むゲストOSごと開発環境と本番環境との間でやり取りをすることになるのですが、その容量の大きさから、時間はかかりますしネットワーク帯域は圧迫しますし、なかなかに実現が厳しくなります。
Dockerによる開発スタイルでは、コンテナのその可搬性の高さから、WSLと同じく開発環境と実行基盤の差異をなくすことはもちろん、開発エンジニアが開発環境を構築する手間さえも省くことができることがわかります。
WSL2とDockerは相性ぴったり!!
図2でご紹介した「Dockerによる開発スタイル」を実現するためには、もちろんDockerが必要です。今までWindowsでDockerを使うためには、Windows 10 Pro以上が必要でした。それは、従来のDocker Desktop for Windowsが以下のようなアーキテクチャになっていたためです。
Docker Desktop for Windowsは、Moby VMというLinuxの仮想マシンを起動し、その仮想マシン内のLinuxカーネルを使ってコンテナを起動します。Moby VMの起動には仮想化ハイパーバイザーであるHyper-Vが必要となり、Hyper-VはWindows 10 Pro以上が必要となります。
しかし、Docker Desktop WSL 2 backendの場合は、「図XX Docker Desktop WSL 2 backendの構成図」のとおり、Dockerコンテナ稼働に必要な仮想化ハイパーバイザー、Linux仮想マシン、LinuxカーネルはすべてWSL2をインストールすると自動的に作成されます。さらに、WSL2専用の軽量化Hyper-Vは、Windows 10 Homeにも利用できるように設計されてあるため、Docker Desktop WSL 2 backendと組み合わせることで、Windows 10 HomeでもDockerが利用できるのです。
つまり、WSL2を利用することで、Windowsにおける開発の門戸が広がるのです。
Visual Studio CodeとDockerは相性ぴったり!!
さらにVisual Studio CodeはDockerとの相性も抜群です。図2でご紹介した「Dockerによる開発スタイル」の③を実行するにはひと手間必要です。Dockerfileをもとにdocker buildコマンドを実行して、コンテナを作成、さらにホスト上のソースコードをコンテナにマウントするためのdockerコマンドを実行して、、、とかなり多くのコマンド操作を必要とします。これを開発エンジニア全員に行わせるのはかなりの工数を消費してしまいます。
Visual Studio CodeのRemote Development拡張機能を使うと、これらの作業をすべて自動化することができます。そのための設定ファイルであるdevcontainer.jsonもGitリポジトリに事前にPushしておき、開発エンジニアのみなさんにPullしてもらい、Remote Development拡張機能に読み込ませ、Docker周りの環境構築を自動化することができます。devcontainer.jsonの記載方法については、この後の実践でご説明します。
実践!!WindowsでのDockerによる開発!!
Dockerの概要や、WSL2とDockerを組み合わせた開発のメリットをご理解頂けたところで、早速実践に入りたいと思います。
今回の実践では、下図のような環境を構築します。
図3 Dockerによる開発環境の構成図
この実践では、先に紹介した「図2 Dockerによる開発スタイル」の①、②、③、④の部分に主にフォーカスを当てて行います。本来であれば⑤、⑥の部分も開発における必須事項なのですが、⑤、⑥は本番環境への反映であり、本記事の主旨である「Windowsによる開発」とは若干離れてしまうため、今回は割愛させて頂きます。
さらに、この環境では、幅広く多くの方が開発できるよう、Windows 10のHomeエディション上に構築するものとします。
今回の実践の進め方は、以下の通りとなります。
-
Docker Desktop for Windowsのインストール
Docker Desktop for Windowsのインストールを行います。 -
ソースコードおよびコンテナ関連設定ファイルの作成、GitへのPush
今回実践対象のソースコードおよびコンテナ関連の設定ファイルの作成、GitへのPushを行います。これは「図2 Dockerによる開発スタイル」の①に相当する部分です。 -
開発環境の構築
GitからPullしたソースコードおよびコンテナ関連設定ファイルと、Visual Studio CodeのRemote Development拡張機能を使うことにより、開発環境で使用するDockerコンテナを生成します。Dockerを用いた開発の場合も、WSLと同様にVisual Studio CodeのRemote Development拡張機能を使うことにより、コンテナ内のファイルを直接編集できるため、WSLのときと同様のメリットを享受できます。これは「図2 Dockerによる開発スタイル」の②、③に相当する部分です。 -
ソースコードの修正およびGitへのPush
ソースコードを修正して動作確認を実施し、問題ないことを確認した上で、GitへのPushを行います。これは「図2 Dockerによる開発スタイル」の④に相当する部分です。
以降の説明では、図3のWindows 10 Homeが稼働している環境を「ホストOS」、ホストOS上でコンテナとして稼働している環境を「コンテナ」と呼ぶことにします。
Docker Desktop for Windowsのインストール
何はともあれ、まずはDocker Desktop for Windowsのインストールです。第3章でも説明したように、Docker Desktop for Windowsは今まではHyper-Vを内包するProfessionalエディション以上が必要でした。しかし、WSL2ではWSL2向けのHyper-VがHomeエディションに内包されることとなり、Docker Desktop for Windowsは、このHyper-Vを使うことで、Dockerエンジンを動作することができます。
上記の理由より、まず最初にWSL2のインストールを実施します。WSL2は、第1章でインストールしたWSLを以降の手順でWSL2にアップグレードすることでインストールします。
Windowsの左下の検索ボックスに「powershell」と入力すると、メニューの中に「Windows PowerShell」が表示されます。それを右クリックして、「管理者として実行」をクリックして下さい。以下のコマンドを実行して、「操作は正常に完了しました。」と表示されれば成功です。
PS C:\Windows\system32> dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart 展開イメージのサービスと管理ツール バージョン: 10.0.19041.1 イメージのバージョン: 10.0.19041.207 機能を有効にしています [==========================100.0%==========================] 操作は正常に完了しました。
次に、同じPowerShellのウィンドウで以下のコマンドを実行します。「操作は正常に完了しました。」と表示されれば成功です。
PS C:\Windows\system32> dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart 展開イメージのサービスと管理ツール バージョン: 10.0.19041.1 イメージのバージョン: 10.0.19041.207 機能を有効にしています [==========================100.0%==========================] 操作は正常に完了しました。
Docker Desktop for Windowsを使うためには、WSL2のLinuxカーネルを更新する必要があります。以下のURLの「this link」をクリックし、Linux kernel update packageをダウンロードして実行します。ウィザード通りに進んでいけばインストールは完了します。
https://docs.microsoft.com/en-us/windows/wsl/wsl2-kernel
以下のリンクをクリックして、「Download Docker Desktop Edge X.X.X.X or a later release.」(X.X.X.Xはバージョン番号)をクリックし絵、Docker Desktop for Windowsをダウンロードして実行します。ウィザード通りに進んでいけばインストールは完了します。
https://docs.docker.com/docker-for-windows/wsl-tech-preview/#download
※ 以下のリリースノートにある通り、Windows 10のHomeエディションでDocker Desktop for Windowsを利用するためには、2.2.2.0以降のバージョンをダウンロードして下さい。
https://docs.docker.com/docker-for-windows/edge-release-notes/#docker-desktop-community-2220
ソースコードおよびコンテナ関連設定ファイルの作成、GitへのPush
ここでは、「図2 Dockerによる開発スタイル」の②の部分に相当する実践を行います。具体的な内容としては、Gitリポジトリ(GitHubなど)にPushするためのソースコードやコンテナ関連の設定ファイル(Dockerfile)を作成します。そのファイル群やディレクトリ構成は以下の通りとなります。
GitリポジトリのTop
├── .devcontainer
│ ├── devcontainer.json
│ └── Dockerfile
└── src
└── index.php
上記のファイルを作成し、GitリポジトリにPushします。
では、これより以降は、上記に記載のファイルの詳細を一つずつ説明していきます。
■ .devcontainer/devcontainer.json
Remote Development拡張機能を使うと、Visual Studio CodeからDockerコンテナに接続しDocker上のファイルを直接編集できるのはもちろんのこと、Dockerコンテナ自体の生成も拡張機能で行うことができます。devcontainer.jsonは、生成するコンテナファイルの詳細について記述し、その記述内容によって、コンテナのイメージやマウントの設定などが決定します。今回の実践における具体的な設定内容は以下のとおりです。
{ # 設定を一意に識別する任意の名称です。 "name": "Hello", # コンテナを作成するためのDockerfileのファイル名を指定します。 # Dockerfileの内容については後述します。 "dockerFile": "Dockerfile", # この設定によりホストOSの80宛の通信がコンテナの80に転送されます。 # ホストPCからブラウザで動作確認するために必要です。 "forwardPorts": [80], # デフォルトではVisual Studio Codeからのコンテナ起動時のコマンドは # while sleep 1000; do :; doneに上書きされてしまいますが、それを防止します。 "overrideCommand": false, # Gitリポジトリのsrcディレクトリを、Apacheのドキュメントルートである/var/www/htmlに # マウントします。 "mounts": [ "source=${localWorkspaceFolder}/src,target=/var/www/html,type=bind,consistency=cached" ] }
■ .devcontainer/Dockerfile
Visual Studio CodeのRemote Development拡張機能で生成されるコンテナ内で実施するコマンドを定義したDockerfileです。先に説明したとおり、.devcontainer/devcontainer.jsonで定義されています。
# PHPとApacheがインストールされたOfficialイメージをPullします。 FROM php:7.2.30-apache # 修正したソースコードをGitリポジトリにアップするために # コンテナ上にGitをインストールします。 RUN apt-get update && apt-get -y install git
上記のDockerfileでGitをインストールしていますが、Visual Studio CodeのRemote Development 拡張機能を利用すると、Visual Studio CodeのGitの機能はコンテナ側で動作します。そのため、コンテナ側にもGitのインストールが必要になります。
■ src/index.php
ブラウザにhogeと表示するだけの簡単なPHPスクリプトです。
開発環境の構築
開発リーダーがGitレポジトリにPushしたファイルを、開発エンジニアはホストOS上のGitでPullをして取得します。
これらのファイル(.devcontainerディレクトリ配下のファイル)とRemote Development拡張機能により、開発環境に必要なDockerコンテナを生成します。
Visual Studio Codeを起動して、左下の緑のボタンをクリックして下さい。
図4 開発環境の構築手順その1
以下のようなリストが表示されますので、「Remote-Containers: Open Folder in Container…」 をクリックします。そして先程PullしたGitディレクトリを選択します。
図5 開発環境の構築手順その2
Visual Studio Codeの右下の方に以下の画面が表示され、コンテナの生成が始まります。初回はDocker HubからイメージをPullしたりコンテナを生成したりしますので、時間がかかりますが、2回目以降は素早く起動できます。
図6 開発環境の構築手順その3
以下のような画面が表示されれば成功です。画面左部に表示されているのはコンテナの中のファイルです。このファイルを修正すると、コンテナの中のファイルが修正されます。
画面下部のTerminalはコンテナ内部のShellになります。ps axと入力してプロセスを見てみますと、たしかにコンテナ内部で起動しているプロセスのみが表示されている(PIDが1のプロセスがApacheの親プロセス)ことがわかります。
root@9af07dd07639:/workspaces/webapp# ps ax PID TTY STAT TIME COMMAND 1 ? Ss 0:00 apache2 -DFOREGROUND 18 ? S 0:00 apache2 -DFOREGROUND 19 ? S 0:00 apache2 -DFOREGROUND 20 ? S 0:00 apache2 -DFOREGROUND 21 ? S 0:00 apache2 -DFOREGROUND 22 ? S 0:00 apache2 -DFOREGROUND 23 ? Ss 0:00 /bin/sh ... 以下略 ...
ソースコードの修正およびGitへのPush
開発エンジニアは、ソースコードを修正して、コンテナ上にインストールしてあるGitによって、GitレポジトリにPushします。
index.phpを編集し、以下の様にfugaと表示するスクリプトに変更します。
「図8 GitへのCommit」の①をクリックして、Commitのコメントを入力し、②をクリックしてCommitします。
図8 GitへのCommit
先程GitにCommitしたファイルをPushします。「図9 GitへのPush」の赤い枠の部分をクリックするとPushは完了します。
図9 GitへのPush
ホストPCのブラウザからhttps://localhost/にアクセスすると、ブラウザ上に「fuga」と表示されるはずです。
開発の終了
その日の開発を終えて、Visual Studio Codeを終了します。すると同時にコンテナも終了しますが、コンテナからホストPC上のソースコードをマウントしていたので、コンテナ上でソースコードに加えた変更やGitの操作履歴は消えることはありません。
図10 開発の終了
これで、Visual Studio CodeとDockerを用いた開発の流れが体感頂けたかと思います。
まとめ
今回の特集を通じて、WSLやWindows Terminal、Visual Studio Code、Dockerといった最新の技術を駆使し、Windowsでの開発における課題を克服、WindowsとLinuxのいいとこ取りの最適な開発環境を構築できることがご理解頂けたかと思います。
本稿が、これからWindowsを使って開発を行うエンジニアの皆様のお役に立てれば幸いです。