## 要点 Docker Compose の `compose.yaml` でサービス名を付ける際は、HTTP での接続先となるコンテナのサービス名には `app` や `dev` といったトップレベルドメイン(TLD)として実在する文字列を使わないほうが安全です。 ### 具体的な対策 HTTP で接続するサービス(コンテナ)には、ハイフン(`-`)を用いて複数の単語を組み合わせた名前をつけるのが、簡単な解決策です。 - **避けるべきサービス名の例**:`app`, `dev` - **推奨されるサービス名の例**:`rails-app`, `web-server` ### なぜエラーになるのか Docker Compose のネットワーク内では、サービス名で名前解決をして他コンテナへアクセスできます。そのため、Selenium コンテナ内のブラウザから `http://app/` のようにアクセスする設定にすることがあります。 しかしブラウザは、その `app` を Docker 内部の名前としてではなく、通常のホスト名として扱います。 `app` や `dev` は実在の TLD であり、しかも HSTS(HTTP Strict Transport Security)を強制する対象なので、ブラウザは `http://app/` を `https://app/` に書き換えます。 接続先が HTTPS 非対応なら、結果として `ERR_SSL_PROTOCOL_ERROR` や `Are you trying to open an SSL connection to a non-SSL Puma?` のようなエラーになります。 一方、`rails-app` のように、TLD と一致しない名前にすれば、HSTS 強制の対象から外れ、HTTPS に書き換えられないため、エラーを防ぐことができます。 ## 背景:何が起きているか Docker の `compose.yaml` の `services` で定義したサービス名は、Docker ネットワーク内で他コンテナへアクセスする際のホスト名として使えます。ここでのホスト名とは、`http://example.com/` の `example.com` に当たります。 サービス名にドット(`.`)が含まれていない場合、単一ラベルのホスト名となり、ブラウザはその名前を TLD として扱います。例えば、`app` というサービス名は、`app` という TLD のみからなるホスト名として認識されます。 TLD のみのホスト名のうち、`app` や `dev` は HSTS 強制の対象となっており、HSTS プレロードリストなどの仕組みにより、HTTPS 接続が強制されます。そのため、`http://app/` という HTTP での接続になるよう設定しても、ブラウザは強制的に `https://app/` という HTTPS での接続へと書き換えて接続しようとします。 結果、`app` や `dev` のような HSTS が強制される名前を持つサービス(コンテナ)に対して、Selenium コンテナ内のブラウザは、HTTP で接続するよう設定されていても、HTTPS で接続してしまいます。 さらに、接続される側のコンテナが HTTPS に対応していない場合、接続がエラーとなります。 このように、E2E テストやシステムテストでは「ブラウザがどう解釈するか」は無視できない事項です。 コンテナ間疎通の都合だけで名前を決めるのではなく、ブラウザが特殊な扱いをする名前ではないか、という観点も持っておくとトラブルを減らせます。 ## 注意点 - TLD、及び、HSTS が強制されるホスト名は追加が続いています。そのため、将来のトラブルを防ぐ観点では、現状でトラブルになる名前だけでなく、今後トラブルになりそうな名前全般を避けたほうが無難だと考えられます。 - HSTS はホスト名ベースで効き、ポート番号では回避できません。つまり `http://app:3000/` のような URL でもエラーになり得ます。 - ホスト名にドットを含めることは、本件の SSL エラーの確実な回避策とはなりません。なぜなら、HSTS 強制の対象となっているホスト名としては、TLD のみのホスト名だけではなく、`facebook.com` や `www.amazon.com` といったドットを含むホスト名も多数存在するためです。 ## 接続エラーに遭遇した状況 `compose.yaml` において、`selenium/standalone-chromium` イメージの Selenium コンテナからサービス名が `app` のコンテナへ HTTP で接続する設定をしたところ、以下のエラーが発生しました。 ``` 2026-03-25 05:37:53 +0000 HTTP parse error, malformed request: # [Screenshot Image]: /x/tmp/screenshots/failures_test_should_destroy_Article.png E Error: ArticlesTest#test_should_destroy_Article: Selenium::WebDriver::Error::UnknownError: unknown error: net::ERR_SSL_PROTOCOL_ERROR (Session info: chrome=145.0.7632.109) test/system/articles_test.rb:38:in 'block in ' ``` なお、サービス名を `app` から `rails-app` に変更したところ、無事意図したとおりに動くようになりました。 HSTS 強制の対象となる TLD(`app`)との一致を回避した結果、ブラウザが HTTPS へ強制的に書き換えなくなったためと考えられます。 ## 参考資料 - .devドメインと.appドメインがHTTPSを強制する仕組み: https://qiita.com/tomoyk/items/187aa6723e80e1bba675 - Google Chrome implementing HSTS breaks dockerized application testing: https://medium.com/@alex.skrypnyk/google-chrome-implementing-hsts-breaks-dockerized-application-testing-55120e6d67bc