よくある技術的質問 (FAQ)
プロジェクト開発中に生じた疑問とその回答をまとめています。
Docker / インフラストラクチャ
Q. なぜ docker コマンド実行に sudo が必要なのですか?
通常、Linux上で docker コマンドは Docker デーモン(root権限で動作)のソケット /var/run/docker.sock と通信します。このソケットは root ユーザーまたは docker グループのみが書き込み権限を持っています。
macOS (Docker Desktop) との違い:
- macOS: Docker Desktop アプリケーションが裏側でVMを管理し、ユーザー権限でそのVMと通信できるようにソケットやコンテキストを自動設定してくれているため、
sudoは不要でした。 - Debian (Linux Guest OS): サーバーとしての標準的な構成であるため、明示的に権限設定が必要です。デフォルトでは一般ユーザーは Docker デーモンにアクセスできません。
- macOS: Docker Desktop アプリケーションが裏側でVMを管理し、ユーザー権限でそのVMと通信できるようにソケットやコンテキストを自動設定してくれているため、
「permission denied」エラーの解決策:
- 一時的な対処: すべての
docker(またはmake)コマンドにsudoを付ける。bashsudo make down - 恒久的な対処: ユーザーを
dockerグループに追加する。bashsudo usermod -aG docker $USER # その後、一度ログアウトして再ログインするか、再起動することで反映されます
※
newgrp dockerコマンドは一時的に現在のシェルでのみグループを有効にするものなので、新しいターミナルを開いたりmakeコマンド内部でシェルが切り替わる際などに権限が適用されないことがあります。確実な方法は「再ログイン」です。- 一時的な対処: すべての
Q. 「ホストOSのカーネルを共有する」とは具体的にどういうことですか?
「カーネルを共有する」 とは、コンテナ内のアプリケーションプロセスが、ハイパーバイザー(ハードウェア仮想化層)を通さずに、ホストOSのカーネル(Linuxカーネル)の機能を直接呼び出す(システムコールを行う) ことを指します。
システムコールの直接実行:
- コンテナ内のプロセス(例:
nginx)がファイルを読み書きする際、ゲストOS内のカーネルに対して直接openやwriteといった命令(システムコール)を送ります。 - 仮想マシン(VM)の場合、ゲストOSのカーネルがシステムコールを受け取り、それをハイパーバイザーがさらにホストOSの命令に変換するという「翻訳」プロセスが発生するため、オーバーヘッドが生じます。
- コンテナ内のプロセス(例:
隔離技術 (Namespaces) とリソース制限 (Cgroups):
- カーネルは共有していますが、Namespaces (名前空間) という機能により、各プロセスに対し「自分専用のPID番号、ファイルシステム、ネットワークインターフェース」があるかのように見せています。これにより隔離を実現しています。
- Cgroups (Control Groups) により、CPUやメモリの使用量を制限しています。
- つまり、コンテナは「壁(Namespaces)と手錠(Cgroups)をかけられた、ホスト上のただのプロセス」と言い換えられます。
注意点 (Docker Infrastructure環境における「ホスト」):
- 一般的な文脈での「ホスト」は物理マシンを指しますが、本プロジェクト(Mac/Windows上のVirtualBox等)の場合、Dockerコンテナにとっての「ホストOS」は Debian 12(VM) です。
- Mac/Windowsのカーネルを直接共有しているわけではありません(OSが異なるため)。Mac/Win上の仮想化ソフトウェアが Debian VM を動かし、その Debian カーネルを Docker コンテナが共有しています。
- Reference: Docker Overview (Architecture) | Docker Docs
- Reference: Linux Namespaces | man7.org
- Reference: Containers vs. Virtual Machines | Red Hat
Q. 校舎環境(ホストOS)でのドメイン動作確認はどうすればよいですか?
校舎のiMac等ではホストOSの /etc/hosts を編集する管理者権限(sudo)がない場合があります。 その場合の確認方法は以下の通りです:
VM内での確認(推奨): ゲストOS(Linux VM)内では
sudoが使えるため、VM内の/etc/hostsに127.0.0.1 local.devを記述し、VM内のcurlやCLIブラウザで確認します。これが最も確実な評価方法です。curlの--resolveオプション(ホストOS): ホストOSから確認する場合、hostsファイルを書き換えずにドメイン解決を強制できます。bashcurl -k -I --resolve local.dev:443:127.0.0.1 https://local.dev※ ポート転送設定などによりIPが異なる場合は
127.0.0.1を適切なIPに変更してください。
Q. Docker ネットワークにはどのような種類があり、なぜ今回は Bridge ネットワークなのか?
Docker には以下の主要なネットワークドライバがあります。
- Bridge (デフォルト): コンテナとホストを隔離し、コンテナ同士も隔離しますが、明示的に接続したコンテナ間通信は許可します(User-defined bridge)。内部DNSによるサービス名解決が可能です。
- Host: コンテナがホストのネットワークスタックを直接共有します。ポート変換が不要になりますが (Port 80 は Host Port 80)、コンテナの隔離性が失われます。
- None: ネットワークインターフェースを持ちません。
- Overlay: 複数の Docker デーモン(Swarm 等)にまたがるネットワークを作成します。
- Macvlan: コンテナに物理ネットワーク上の MAC アドレスを割り当てます。レガシーアプリ向けです。
今回の採用理由: Docker Infrastructure では各サービスの独立性を保ちながら、wordpress というホスト名で通信する必要があるため、User-defined Bridge Network (networks: inception) が最適です。Hostドライバを使用すると、ポートの競合(ホストで既に80番を使っている場合など)やセキュリティリスクが発生しやすくなります。
- Reference: Docker Network Drivers | Docker Docs
Q. Docker ボリュームで driver_opts を使用している理由は?
Docker におけるデータ永続化には主に3つの方法があります。
- Volumes (Named Volumes):
docker volume createで作成し、Docker が管理する領域 (/var/lib/docker/volumes/...) にデータを保存します。管理が容易ですが、保存場所を意識しにくいです。 - Bind Mounts: ホスト側の任意のディレクトリ (
/home/user/data) をコンテナにマウントします。type: bindや-v /path:/pathで指定します。シンプルですが、Docker CLI から 'volume' オブジェクトとして管理・一覧化されません。 - Volumes with Bind Options (driver_opts): 今回採用している方法です。Docker 上の「ボリューム」として定義しつつ、実際の保存先は
driver_optsのdeviceオプションでホストの特定パス (/home/user/data/wordpress) を指定します。
今回の採用理由: 課題要件で「Docker Volume を使用すること」と「/home/login/data 以下に保存すること」の両方が求められているため、Bind Mount の実体を持つ Named Volume というハイブリッドなアプローチ(o: bind)を採用しています。これにより docker volume ls で確認できつつ、指定パスにデータが保存されます。
- Deep Dive: Docker Volume 戦略: ハイブリッドアプローチ - 図解と詳細な背景はこちら。
- Reference: Use bind mounts | Docker Docs
- Reference: Volume Create Options | Docker Docs
Q. なぜ healthcheck 機能を使用していないのですか?
docker-compose.yml には healthcheck セクションを追加することで、コンテナが単に起動中 (Running) なだけでなく、正常に応答できる状態 (Healthy) かどうかを監視できます。depends_on: condition: service_healthy と組み合わせることで、完全な起動順序制御が可能です。
今回コンポーズファイルに記述していない理由:
- 必須要件の範囲と学習コスト: Docker Infrastructure の課題範囲では、各コンテナ内のスクリプトやアプリケーション自身のリトライ機能(WordPress が DB 接続できるまでリトライするなど)で十分動作するためです。
- 複雑性: 適切なヘルスチェックコマンド(
curlやmysqladmin ping)をコンテナ内に用意し、適切なタイムアウト設定を行う必要があり、設定ファイルが肥大化します。 - 現状の代替手段:
depends_onで「起動順序(start順)」だけは保証されており、アプリケーションレベルでの待機で現状問題がないため、設定を省略しています。
ただし、本番環境運用(Production)や、より堅牢な設計を目指す場合は導入が推奨されます。
ネットワーク / HTTP
Q. curl -k -I https://localhost:443 の結果はどう見ればよいですか?
HTTP/1.1 200 OK
Server: nginx/1.18.0
...
Link: <https://local.dev/index.php?rest_route=/>; rel="https://api.w.org/"- HTTP/1.1 200 OK: リクエスト成功。Webサーバーから正常な応答が返りました。
- Server: nginx/1.18.0: Nginxがリクエストを受け付け、応答していることを示します(Nginxコンテナの動作証明)。
- Link: ... api.w.org ...: WordPressのREST APIのリンクが含まれています。これは、NginxがリクエストをWordPressコンテナに転送し、WordPressが生成したHTMLヘッダーが返ってきていることを証明しています(Nginx -> WordPress 連携の成功)。