【OSSでWiki構築】第3回(環境構築編 トラブルシューティング)
はじめに
「【OSSでWiki構築】第2回(環境構築編)」に記載された手順に至るまでに遭遇した、様々なエラーとその解決策をまとめたものです。
エラーは失敗ではなく、システムへの理解を深めるための最高のヒントです。各エラーから得られた学びを共有します。
問題1: Docker Hubの認証エラー
発生した事象
docker compose up -d を初めて実行した際、イメージのダウンロードに失敗し、以下のエラーが表示された。
Error response from daemon: authentication required - email must be verified before using account
原因の分析
このエラーは、「Docker Hubのアカウント認証が完了していない」ことを意味します。Docker Desktopの利用にはDocker Hubへのログインが必要ですが、その際に登録したメールアドレスの本人確認が完了していないと、Docker Hub(Dockerイメージの公式保管庫)からイメージをダウンロードする権限が得られません。
解決策
- Docker Hubから送られてきている「Verify your email address」という件名のメールを探し、認証リンクをクリックする。
- もしメールが見つからない場合は、Docker Hub公式サイトにログインし、画面の案内に従ってメールアドレスの認証を完了させる。
学んだこと
Docker Desktopは、イメージをダウンロードするために認証済みのDocker Hubアカウントを必要とします。インストール直後は、まずメール認証を完了させることが重要です。
問題2: ポートの競合エラー
発生した事象
コンテナを起動しようとした際、以下のエラーでoutlineコンテナの起動に失敗した。
listen tcp 0.0.0.0:3000: bind: address already in use
原因の分析
PCのポート(ネットワークのドア)は、一つのアプリケーションしか使用できません。このエラーは、Outlineが使おうとした3000番ポートが、すでに他のアプリケーションによって使用されていたために発生しました。
解決策
- 以下のコマンドで、どのアプリケーションがポートを使用しているか特定する。
lsof -i :3000 - 特定したアプリケーションを停止する。
- (もし停止できない場合)
docker-compose.ymlのportsとURLの設定を、3000から3001など、空いている別のポート番号に変更する。
学んだこと
ポートは排他的なリソースです。address already in useエラーが出た際は、lsofコマンドで競合しているプロセスを特定するのが定石です。
問題3: アプリケーションの必須設定(環境変数)の不足
発生した事象
コンテナは起動するものの、すぐに停止してしまう。ログを確認すると、以下のエラーが出力されていた。
ケースA: RedisのURLが未設定
REDIS_URL should not be empty
ケースB: データベースのSSL接続エラー
The database does not support SSL connections. Set the `PGSSLMODE` environment variable to `disable`
原因の分析
- ケースA: 最近のOutlineのバージョンでは、キャッシュ用のデータベースとしてRedisが必須になっていましたが、当初の
docker-compose.ymlにその設定が含まれていませんでした。 - ケースB: Outlineはデフォルトで安全なSSL(暗号化)通信でデータベースに接続しようとしますが、ローカルで立てたPostgreSQLはSSLに対応していませんでした。
解決策
docker-compose.ymlのoutlineサービスのenvironmentセクションに、不足している環境変数を追記する。
- ケースA:
redisサービスをdocker-compose.ymlに追加し、REDIS_URL: 'redis://redis:6379'をoutlineの環境変数に追加した。 - ケースB:
PGSSLMODE: 'disable'をoutlineの環境変数に追加し、SSLを使わないように指示した。
学んだこと
エラーログは解決策の宝庫です。 特にアプリケーション固有のエラーは、ログに原因や、時には解決策(今回の場合Set the 'PGSSLMODE' ...)が直接書かれていることがよくあります。エラーが出たら、まずはログを丁寧に読むことが解決への一番の近道です。
問題4: ブラウザでの接続拒否と強制HTTPS化
発生した事象
- 全てのコンテナが
(healthy)状態で正常に起動しているにも関わらず、ブラウザでhttp://localhost:3000にアクセスできない (ERR_CONNECTION_REFUSED)。 - URLが自動的に
https://localhostに書き換わってしまう。 - 別のブラウザや、
http://127.0.0.1:3000でアクセスしても解決しない。
原因の分析
これは、Outlineアプリ自身が送ってくるHSTS (HTTP Strict Transport Security) ヘッダーが根本原因でした。
- 一度でもアクセスを試みると、Outlineがブラウザに対し「今後
localhostへのアクセスは、絶対にHTTPSを使いなさい」という強力な指示を送ります。 - ブラウザはその指示を忠実に記憶し、以降の
http://localhostへのアクセスをすべて強制的にhttps://localhostにリダイレクトしてしまいます。 - しかし、こちらの環境にはHTTPSで応答する準備がなかったため、接続エラーとなっていました。
この指示はブラウザの深いレベルで記憶されるため、通常のキャッシュクリアでは解決しませんでした。curl -v http://localhost:3000コマンドで通信内容を直接確認したところ、Strict-Transport-SecurityヘッダーとLocation: <https://localhost/というリダイレクト指示が返ってきており、これが決定的な証拠となりました。>
解決策
この複合的な問題を解決するため、以下の段階的な対策を実施しました。
localhostの回避: HSTSの記憶が染みついたlocalhostを避けるため、hostsファイルを編集し、127.0.0.1にoutline.testという新しい名前を付けました。- ローカルHTTPS環境の構築: OutlineがHTTPSを強く要求するため、リバースプロキシであるCaddyを導入し、ローカルでHTTPS通信を可能にしました。
- Caddyの設定: Caddyが外部の認証局に証明書を申請しに行ってしまうエラーを解決するため、
Caddyfileにtls internalを追記し、自家製の証明書を使うように指示しました。
補足:なぜ localhost ではなく outline.test を使ったのか?
このトラブルシューティングの過程で、 outline.test というカスタムドメインを導入しました。これは、localhost という名前に HSTS の記憶が染みついているという仮説に基づき、それを回避するための診断的なステップでした。
しかし、最終的な学びとして、Caddy によるローカル HTTPS 環境さえ用意すれば、HSTS が要求する https:// の条件を満たすことができると分かりました。
※事実、次回の「認証基盤編」では、Google の制約によって localhost を使う必要が出てきましたが、Caddyのおかげで https://localhost として問題なく動作させることができました。
つまり、Caddy を導入するという前提に立てば、localhost のままでもローカル HTTPS 環境を構築し、この問題を解決することは可能だったと言えます。outline.test への移行は、問題を切り分けるための有効な「回り道」でした。