メインコンテンツまでスキップ

Docker 環境構築 【 Windows 編 】

Dockerとは何か

仮想化技術には、ハイパーバイザー型とコンテナ型があります。
Docker とはコンテナ型の仮想化プラットフォームです。
VirtualBox などのハイパーバイザー型の仮想化プラットフォームでは、ホストマシン上にゲスト OS を構築し、そこでアプリケーションを実行します。
それに対し Docker は、ホストマシンのカーネルを利用しプロセスやユーザなどを隔離することで、あたかも別のマシンが動いているかのように動かします。
そのため、Docker は OS を構築しない分、ハイパーバイザー型より軽量かつ高速に動くとされています。

しかし実際に使ってみると「重すぎて使えない」という声が多く聞かれます。
また、このような声は WindowsPC ユーザーによく聞かれます。
これはコンテナで仮想化した LINUX OS とホストマシンの Windows OS の違いが原因で、環境構築手順が複雑になってしまっており、正しく扱うことができていないからです。
一方 Mac OS は LINUX ベースで作られているため、OS の差分が少なく簡単な設定で始めることができます。
本記事では、複雑になってしまっている Windows での Docker 環境構築 / 操作手順について解説していきます。

図1. ハイパーバイザー型(VirtualBox) とコンテナ型(Docker) の違い ハイパーバイザー型とコンテナ型の違い

Docker の(快適)動作要件

Docker を快適に動作させるには以下をインストールしてください。
本記事では Docker の設定をメインに解説するため、インストール手順は割愛します。
参考記事をもとにインストールを完了させてください。

WSL2 とは

動作要件に WSL2 とありますが、この仕組みを理解しておかなければ Docker を快適に利用することはできません。
WSL2 は Windows Subsystem for Linux 2 なので、文字通り Windows 上で動作する Linux の実行環境です。
Docker を動作させるだけであればこの仕組みは必要ありませんが、快適に利用するには必須です。
というのも WindowsOS に配置されたアプリケーションは同期時に LinuxOS に適応させる必要があります。
そのため、Windows 上にアプリケーションを配置してしまうと、ファイルを読み込む度に変換処理が入って重くなってしまうのです。
WSL2 は Windows 上にあらかじめ Linux 環境を用意することで OS の違いを解消し、読み込み速度を高速化する役割を担っています。

図2. WSL2の役割 WSL2の役割

WSL2 を正しく使おう

WSL2 をインストールしたら、エクスプローラーのサイドバーに「Linux」が表示されます。
これが前述した Windows 上で動作する Linux の実行環境です。
中身を見てみると Linux > Ubuntu > mnt > c に ホストOS (Windows) の C ドライブがマウントされています。
よくある間違いはこれを使ってしまうことです。
この場所を使ってしまうとアプリケーションの同期時に変換しなければならず、処理が格段に遅くなってしまいます。
これを回避するため、マウントしていないディレクトリにプロジェクトを配置しましょう。
まず Linux > Ubuntu > home > [WSL2インストール時に設定したユーザー名] のディレクトリがあるので、ここに任意のディレクトリを作成してください。
(画像では dev ディレクトリを作成しています)
あとは作成したディレクトリ内に Docker で動かしたいプロジェクトを配置するだけです。

図3. Linuxのディレクトリ構成 Linuxのディレクトリ構成

dockerの環境構築

dockerの環境構築は docker-compose.yml をルートディレクトリに配置し以下のコマンドを実行するだけです。

docker compose up -d --build

DockerFileを作成する方法と、併用する方法もありますので、興味のある方は調べてみてください。
docker-compose.yml の記述例を以下に3パターン上げておきます。
どういう設定かコメントを書いていますので、環境に合わせてカスタマイズして使用してください。

Node.js + PostgreSQL
docker-compose.yml
services:
node:
image: node:20-alpine
ports:
- 3000:3000 # ホストOSのポート:コンテナのポート
working_dir: /app # コンテナのルートディレクトリのパス
volumes: # 同期設定
- ./:/app # Linuxのパス:コンテナのパス
networks:
- app # 同じネットワークに置くことで接続可能となる
depends_on:
- postgres # postgresが先に起動する必要がある
command: sh -c "yarn install && yarn run dev" # コンテナが起動したときに実行
postgres:
image: postgres:15-alpine
ports:
- 5432:5432
volumes:
- 'db:/var/lib/postgresql/data'
- ./.docker/postgres/init:/docker-entrypoint-initdb.d # docker-entrypoint-initdb.dにSQLを置くことでimage起動時に実行してくれる
networks:
- app
environment: # 起動時に作成
POSTGRES_USER: ${POSTGRES_USER} # `${}`で.envから値を参照
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_HOST_AUTH_METHOD: trust
networks:
app:
driver: bridge # デフォルトネットワークドライバ
volumes:
db:
driver: local # デフォルトボリュームドライバ
Spring Boot (Maven) + MySQL
docker-compose.yml
services:
java-maven:
image: openjdk:17
ports:
- 8080:8080
volumes:
- ./:/app
networks:
- app
working_dir: /app
depends_on:
- mysql
command: sh -c "./mvnw spring-boot:run"
mysql:
image: mysql:8.0
ports:
- 3306:3306
volumes:
- 'db:/var/lib/mysql'
- ./.docker/mysql/init:/docker-entrypoint-initdb.d
networks:
- app
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_ROOT_HOST: '%'
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_ALLOW_EMPTY_PASSWORD: 1
networks:
app:
driver: bridge
volumes:
db:
driver: local
PHP (NginX) + MySQL
docker-compose.yml
services:
nginx:
image: nginx:stable-alpine
ports:
- "8080:80"
volumes:
- ./:/var/www/html
- ./.docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
networks:
- app
php-nginx:
image: php:8.3-fpm
volumes:
- ./:/var/www/html
- ./.docker/php/php.ini:/usr/local/etc/php/php.ini
networks:
- app
depends_on:
- mysql
mysql:
image: mysql:8.0
ports:
- 3306:3306
volumes:
- 'db:/var/lib/mysql'
- ./.docker/mysql/init:/docker-entrypoint-initdb.d
networks:
- app
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_ROOT_HOST: '%'
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_ALLOW_EMPTY_PASSWORD: 1
networks:
app:
driver: bridge
volumes:
db:
driver: local

VScode を正しく使おう

気を付けなければならないのはプロジェクトの配置だけではありません。
VScode も正しく使わなければなりません。
まずはコンテナを起動した時点でアプリケーションがどのような状態になっているか再認識しておきましょう。
図の通りアプリケーションが同期され Linux と Docker のコンテナに存在する状態です。
アプリケーションの実行は コンテナで行っているので、ファイルの作成やコマンド実行などは Docker 側の権限で行わなければなりません。
そのため VScode でアプリケーションを開く際には、コンテナに接続して操作する必要があります。

図4. プロジェクトの配置 プロジェクトの配置

ここからは VScode からコンテナに接続する手順を説明していきます。
まず VScode を開き、左下の水色のアイコンをクリックします。
中央上部に接続先の候補が出てきますので「実行中のコンテナーにアタッチ...」をクリックしてください。

図5. vscodeでコンテナを参照 vscodeでコンテナを参照

立ち上がっているコンテナ一覧が表示されますので、アプリケーションサーバーをクリックしてください。
新しいウィンドウが開いてローディングが終われば接続完了です。
サイドバーからエクスプローラを開いてアプリケーションの同期先ディレクトリを選択すればディレクトリ内のファイル操作が可能となります。

図6. コンテナにアタッチ コンテナにアタッチ

最後に拡張機能について説明しておきます。
拡張機能は環境ごとにインストールすることになります。
そのためローカルPCで使用している拡張機能を別途インストールする必要があります。
ただし、1から検索してインストールする必要はありません。
拡張機能の一覧から「LOCAL - インストール済み」の欄を表示しましょう。
ここにローカルPCにインストールしている拡張機能の一覧が表示されますので、必要なものだけボタンをクリックしてインストールしてください。

図7. 拡張機能のインストール 拡張機能のインストール