はじめに
この記事では、Windows Server の Hyper-V 上に Rocky Linux の仮想マシンを立て、Docker Compose でアプリケーションを動かすまでの手順を整理します。
構成は次のとおりです。
- ホスト: Windows Server(Hyper-V 有効)
- ゲスト: Rocky Linux
- アプリケーション: Apache + Payara(Java AP サーバー)+ MySQL を Docker Compose で動かす
クラウドを使わずオンプレミスで Docker 環境を構築したい場面や、既存の Windows Server を活かして Linux 環境を用意したい場面で参考にしてください。
なぜこの構成を選んだか
背景
もともとアプリケーションは Apache・GlassFish・MySQL をホスト OS に直接インストールして動かしていました。この構成には次のような問題がありました。
- ミドルウェアが保守期限切れとなり、新規環境の構築時に問題が顕在化した
- ホスト直インストールのため、ブランチごとに異なるスキーマ状態を管理できず、開発効率が落ちていた
- オンプレミス(Windows Server)とクラウド(AWS EC2)の両環境で稼働する必要があり、構成の再現性が課題だった
これらを解消するため、Apache + Payara + MySQL の3層構成を Docker Compose でコンテナ化しました。Windows Server 環境では Hyper-V 上の Rocky Linux をホストとする構成を採用しました。
なぜ Hyper-V か
Windows Server が既にある環境では、追加コストなしで Hyper-V を使えます。VMware や VirtualBox を新たに導入するより管理が一元化できます。
なぜ Rocky Linux か
CentOS 8 のサポート終了に伴い、RHEL 互換で無償かつ長期サポートがある Rocky Linux を選びました。既存の CentOS 向けの手順やパッケージがそのまま使えます。
なぜ Docker Compose か
オフライン環境へのデプロイが docker save / docker load で完結します。複数コンテナの依存関係を docker-compose.yml 一枚で管理でき、環境の再現性と引き継ぎのしやすさが向上します。Kubernetes は運用の複雑さがこの規模の用途に対してオーバースペックと判断しました。
Docker 化により、開発環境ではブランチごとの DB 状態を即座に切り替えられるようになり、検証効率も改善しました。
Hyper-V で仮想マシンを作成する
Hyper-V マネージャーから新規仮想マシンを作成します。設定は次のとおりです。
| 項目 | 設定値 |
|---|---|
| 世代 | 第2世代 |
| メモリ | 4096MB(動的メモリ: 無効) |
| ネットワーク | 外部ネットワーク |
| 仮想ハードディスク | 60GB〜120GB |
| インストールオプション | Rocky Linux の ISO を指定 |
第2世代を選ぶと UEFI ブートになります。Rocky Linux の ISO がそのまま起動しない場合は、まず Hyper-V のセキュアブートテンプレートを Microsoft UEFI Certificate Authority に変更する方法を試します。それでも起動できない場合は、セキュアブートを無効にします。
仮想マシンの設定 → セキュリティ
- まず「証明機関」を `Microsoft UEFI Certificate Authority` に変更
- それでも起動しなければ「セキュアブートを有効にする」のチェックを外す
Rocky Linux をインストールする
ISO から起動後、インストール概要画面で次の項目を設定します。
パーティション設定
サーバー用途では手動パーティションが推奨です。次の構成が一つの目安です。
| マウントポイント | サイズ | 備考 |
|---|---|---|
/boot/efi |
600MiB | UEFI 用 |
/boot |
1GiB | |
swap |
4GiB | メモリ量に合わせる |
/ |
残り(目安 52GB) | |
/home |
2GiB | サーバー用途のため最小限 |
デバイスタイプは LVM、ファイルシステムは xfs(デフォルト)で問題ありません。
ユーザー設定
root パスワードと一般ユーザーを設定します。一般ユーザーには「管理者にする」チェックを入れておくと、sudo が使えます。
インストール完了後に再起動し、次のコマンドで確認します。
sudo whoami
# 出力: root
cat /etc/rocky-release
# 出力: Rocky Linux release 10.x
Docker と Docker Compose をインストールする
セットアップスクリプトを使うと一括で設定できます。
#!/usr/bin/env bash
set -euo pipefail
TARGET_USER="${TARGET_USER:-rocky}"
COMPOSE_VERSION="${COMPOSE_VERSION:-v2.27.0}"
# Docker CE のリポジトリ追加とインストール
sudo dnf -y install yum-utils
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf -y install docker-ce docker-ce-cli containerd.io
# Docker を起動・自動起動設定
sudo systemctl enable --now docker
# 一般ユーザーを docker グループに追加(sudo なしで docker を使えるようにする)
sudo usermod -aG docker "${TARGET_USER}"
# アプリケーション用ディレクトリを作成
sudo mkdir -p /opt/myapp /srv/myapp
sudo chown -R "${TARGET_USER}:${TARGET_USER}" /opt/myapp /srv/myapp
# MySQL コンテナ用のデータディレクトリ(uid/gid 999 で動く)
sudo mkdir -p /opt/myapp/data/mysql
sudo chown -R 999:999 /opt/myapp/data/mysql
sudo chmod -R 770 /opt/myapp/data/mysql
# Docker Compose v2 をインストール
sudo mkdir -p /usr/local/lib/docker/cli-plugins
sudo curl -L "https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" \
-o /usr/local/lib/docker/cli-plugins/docker-compose
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
スクリプト実行後は一度ログアウトして再ログインしてください。docker グループへの追加は再ログインで反映されます。
# 確認
docker --version
docker compose version
静的 IP を設定する
Hyper-V 上の仮想マシンは DHCP で IP が変わることがあります。サーバーとして運用する場合は静的 IP を設定しておくと安定します。
# 現在のネットワーク設定を確認
ip a
# 接続名を確認
nmcli connection show
# nmcli で静的 IP を設定する例
sudo nmcli connection modify "System eth0" \
ipv4.method manual \
ipv4.addresses 192.168.1.50/24 \
ipv4.gateway 192.168.1.1 \
ipv4.dns "8.8.8.8 1.1.1.1"
sudo nmcli connection up "System eth0"
eth0 や System eth0 という名前は環境によって異なります。nmcli connection show や nmcli device status で実際の接続名を確認して置き換えてください。
設定前に確認しておくべきことがあります。
- DHCP の割り当て範囲を確認し、その範囲外のアドレスを使う
- 使いたい IP に
pingして応答がないことを確認する -
arp -aでその IP に MAC アドレスが紐づいていないことを確認する
固定 IP を設定した後に SSH が切れることがあります。Hyper-V のコンソールから ip a で設定を確認するのが安全です。
Docker Compose でサービスを起動する
Apache + Java AP サーバー + MySQL の3コンテナ構成の例です。
# docker-compose.yml
services:
mysql:
image: mysql:8.0
container_name: mysql_app
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- ./mysql-init:/docker-entrypoint-initdb.d
- /opt/myapp/data/mysql:/var/lib/mysql
- ./mysql/conf.d:/etc/mysql/conf.d
networks:
- appnet
restart: unless-stopped
web:
build: "./apache"
container_name: web_app
depends_on:
- mysql
ports:
- "80:80"
networks:
- appnet
volumes:
- ${WEB_DIR:-../web}:/var/www/html/app
logging:
driver: json-file
options:
max-size: 1m
max-file: "3"
restart: unless-stopped
app:
build: "./payara"
container_name: payara_app
ports:
- "8080:8080"
networks:
- appnet
depends_on:
- mysql
volumes:
- ${DOCS_DIR:-./payara/documents}:/var/lib/glassfish/documents
- ${LOG_DIR:-/opt/myapp/logs}:/opt/payara/appserver/glassfish/domains/domain1/logs
logging:
driver: json-file
options:
max-size: 1m
max-file: "3"
restart: unless-stopped
networks:
appnet:
driver: bridge
.env ファイルで環境ごとのパスを切り替えられます。
# .env(Linux 環境の例)
WEB_DIR=/opt/myapp/web
DOCS_DIR=/srv/myapp/documents
LOG_DIR=/opt/myapp/logs/payara
起動と確認は次のとおりです。
cd /opt/myapp/compose
docker compose up -d
# ログ確認
docker compose logs -f
# コンテナ起動状態確認
docker ps
ネットワークの名前解決
仮想マシンに静的 IP を設定した後、URL でアクセスできるようにするには名前解決が必要です。
方法1: hosts ファイルを編集する(手元の PC のみ)
Windows の場合は C:\Windows\System32\drivers\etc\hosts を管理者権限で編集します。
192.168.1.50 myapp-dev.local
この方法はその PC からのみ有効です。複数の端末からアクセスする場合は DNS への登録が必要です。
hosts ファイルを変更した後に反映されない場合は次を試してください。
ipconfig /flushdns
方法2: 社内 DNS サーバーに A レコードを登録する(推奨)
myapp-dev.local → 192.168.1.50
クライアント側の設定が不要になり、ネットワーク内のどの端末からも URL でアクセスできます。
Docker イメージをオフラインで配布する
外部ネットワークにアクセスできないオンプレ環境では、Docker Hub からイメージを取得できないことがあります。その場合は事前にビルドしたイメージを tar ファイルとして書き出して持ち込む方法があります。
# ビルドしたイメージを tar に書き出す
docker save myapp-web:latest | gzip > myapp-web.tar.gz
# 別のマシンでインポートする
docker load < myapp-web.tar.gz
この方法で配布すれば、Docker Hub などの外部リポジトリへのアクセスやサーバーのポート開放は不要です。
注意点
Docker イメージビルド時のネットワーク
固定 IP の設定後に docker compose build を実行すると、apt-get や dnf が名前解決できず失敗することがあります。ビルド中のパッケージ取得はコンテナ内から行われますが、名前解決にはホスト OS の DNS 設定が使われます。固定 IP に設定した DNS サーバーに到達できていない場合、コンテナ内からも名前解決が失敗するのが原因です。
対処方法は次のとおりです。
- 固定 IP を設定する前(DHCP のまま)に
docker compose buildを済ませる - または到達可能な DNS サーバーを固定 IP の設定に含める
MySQL データディレクトリのオーナー
bind mount を使う場合、コンテナ内のユーザーとホスト OS のユーザーは別物ですが、UID/GID の数値で権限を判定します。MySQL 8.0 の公式イメージは mysqld をコンテナ内の mysql ユーザー(現在の mysql:8.0 では uid/gid: 999)で動かすため、そのユーザーがホスト側ディレクトリに書き込めないと起動時に失敗します。
sudo chown -R 999:999 /opt/myapp/data/mysql
sudo chmod -R 770 /opt/myapp/data/mysql
この 999:999 は手元の mysql:8.0 に合わせた実務上の設定です。常にこの数値が絶対というより、その環境の mysql ユーザーが書ける状態にすることが本質です。
この問題の背景と named volume との使い分けについては「MySQL公式Dockerイメージでbind mountが権限エラーになる理由と対処」で詳しく整理しています。
まとめ
Hyper-V 上の Rocky Linux で Docker Compose を動かす手順を整理しました。
- Hyper-V で仮想マシンを作成し、Secure Boot はまず
Microsoft UEFI Certificate Authorityを試し、必要なら無効化する - Rocky Linux に Docker と Docker Compose をインストールする
- 静的 IP を設定してサーバーとして安定させる
- Docker Compose で複数コンテナを構成する
- 名前解決は DNS への A レコード登録が複数端末対応の観点から推奨
クラウドを使わずオンプレで Docker 環境を整えたい場合の参考にしてください。