WSLに置いたdevcontainer.jsonからJetBrains devcontainerを起動する

弊社ではPHPによる開発で使用するIDEはPhpStormが標準となっています。

PhpStormも今どきの流行かdevcontainer対応されており、されているからには使いたいと思うのですが、欲しい機能が無かったり期待した通り動かなかったりということが稀によくあるため、使う側が気を使って工夫してあげる必要があります。

今回はその中の1つ
「WSL上に配置したファイル(プロジェクト)からのdevcontainer起動が正常に行えない」
という問題の回避方法が分かったので共有しておこうという趣旨です。

公式に対して報告されている不具合としてはこれにあたると思われます。
https://youtrack.jetbrains.com/issue/IJPL-65925

そろそろ直りそうな気配もあり、直ったらこの記事も不要になるのですが、それならそれで喜ばしいということで。
(現時点の最新バージョン2025.1では直っていない)

結論から書きますと「devcontainer.jsonでworkspaceMountを指定する」となります。

以下は結論に至る経緯です。

Jetbrains devcontainerでは以下の2通りの方法でdevcontainerを作ることが出来ます。

  • ローカルプロジェクトから作成
    • ホスト機に置かれたファイル(devcontainer.json)を使って起動。
  • VCSプロジェクトから作成
    • VCS(Git)に置かれたファイル(devcontainer.json)を使って起動。
      • 実際の動作としては、使うファイルだけテンポラリディレクトリにcloneされてそこから起動される
    • 起動時にDocker volumeが作成され、そこにIDEが開く対象としてGit cloneされる

ただ、現状「VCSプロジェクトから作成」が以下のような点により使いにくいです。

  • Git cloneした内容がホスト機から直接見られない
    • HTMLやMicrosfot officeのドキュメントを入れてたりすると見られない
  • Git cloneした内容が複数のコンテナで共有できない
    • 専用のランダムな名前のDocker volumeが作成されるので、予めcompose.ymlで指定しておくということが出来ない
    • 静的なファイルだけWebサーバのコンテナで配布するとか、Javascriptは別コンテナのnodeで動かすといったことが出来ない
  • Dockerで使用する設定ファイルをBind mountしにくい
    • devcontainerが使用するファイルだけテンポラリディレクトリにcloneされるのでローカルで一時的に変更を試すといったことが出来ない

であれば「ローカルプロジェクトから作成」を使おうという話になりますが、この時「ローカルプロジェクト」がWSLに置いてあると正常に動作しないという問題にあたるわけです。(Windowsに置いてあれば問題なく動作するが、Dockerのディスクアクセス速度の都合でWSL上に置きたい)

状況を確認するために、以下のファイルを使用します。

\\wsl.localhost\Ubuntu\home\kurosawa\devtest.devcontainer\devtestdevcontainer.json

\\wsl.localhost\Ubuntu\home\kurosawa\devtest.devcontainer\compose.yml

このdevcontainer.jsonを使いdevcontainerを起動すると、IDEからディレクトリの中身(\\wsl.localhost\Ubuntu\home\kurosawa\devtest)が見えません。

Docker inspectでMountsを確認すると以下のようになっています。

Docker単体であればWSLに置いても特に問題なくマウント出来たはずなので確認します。

compose.ymlにvolumesを追加。

docker composeを使って直接起動します。

問題なくディレクトリ(\\wsl.localhost\Ubuntu\home\kurosawa\devtest)の中身が確認出来ます。

Docker inspectでMountsを確認すると以下のようになっています。

これらを見るに以下のような状況と思われます。

  • Dockerはスラッシュ区切りのパスがうまく認識できない
  • Dockerはバックスラッシュ区切りのパスは正常に認識できる
  • devcontainerから起動するとスラッシュ区切りのパスでマウントされる

compose.ymlを上記のまま、devcontainerから起動すればよいのでは?と思いましたが、スラッシュ区切りのパスでマウントされてしまいます。

それならばとcompose.ymlでバックスラッシュ区切りのフルパスを指定してみますが、相対パスで指定した場合と同じでスラッシュ区切りのパスでマウントされます。

では、バックスラッシュ区切りのパスにするにはどうしたらいいかというと、devcontainer.jsonのworkspaceMountで指定します。

compose.ymlのvolumesは不要なので削除します。(書いてもdevcontainer.jsonの設定で上書きされる)

workspaceMountで指定すると、バックスラッシュのパスでマウントされます。

workspaceMountは相対パスで指定しても大丈夫です。
devcontainer.jsonを共有することを考えるとこちらの方がよいでしょう。
マウント先のパスを変更することも出来ます。

devcontainerは指定したcompose.ymlをそのまま使うわけではなく、devcontainerの動作用に改変して使用します。

挙動からの推測になりますがその改変処理時に、compose.ymlのvolumesに書いたパスはdevcontainerが一旦解釈して、結果スラッシュ区切りのパスになりdevcontainer.jsonのworkspaceMountはdevcontainerが解釈せずそのまま使われる。ということなのだと思います。

PHP phar拡張モジュールの素敵な仕様

久しぶりにやってくれたPHP。
気づかず同じところに引っかかる人が出ると思ったので書いておきます。

今回PHPで.tar.gz圧縮/解凍を実装することになりまして、
phar拡張モジュールが対応しているということなので、素直にこれで実装したところ動作確認中にエラーが発生しました。

再現のための最小コードがこちらになります。

PharDataは内部でファイルパスをキーとして静的な領域にデータをキャッシュする実装になっているようで、上記のように同じファイルパスだと、複数PharDataを作成しても同じデータを指すことになり、2回目のcompressを実行しようとしたタイミングで「それはもう有るよエラー」ということです。

逆に以下のようなコードで1つのファイルを複数のPharDataで操作出来ます(意味は無い)

この現象については報告されていたのですが、ソースとかディスカッションを見るに
意図して実装されており、良い悪いは別として仕様な気がします。

https://bugs.php.net/bug.php?id=75101

1処理中に同じファイルパスで複数回ファイルを作り直すみたいなのはレアケースだと思うので遭遇する確率は低いと思いますが、記憶の片隅に留めておくとよいと思います。

WordPressのデフォルトアバターが表示されない(404エラーになる)問題

WordPressでデフォルトのアバターを表示させると、以下のようなGravatarのURLを生成します。

https://secure.gravatar.com/avatar/?s=60&d=mm&r=g

このURLが2023年8月9日現在404エラーとなっています。

次のようにパラメータの順番を変更すると正常に表示されます。

https://secure.gravatar.com/avatar/?s=60&r=g&d=mm

さすがにこれが仕様ということは無いと思うので、何かしら不具合が発生していると思われます。

Gravatarにお知らせしたいのですが、不具合を報告したり、お問い合わせするようなフォームが見つけられなかったので諦めました。

Gravatarの中の人ー!見てたら直してくれー!

Workaroundとしては、WordPressが生成するURLのパラメータを並べ替えることが考えられます。

以下のようにURLの生成箇所に用意されているフィルターでパラメータを並べ替えればよいでしょう。

Gravatarが修正されるまでの一時的な物なのでプラグイン化するほどではないかなと思います。

お使いのテーマのfunctions.phpに入れればよいのではないでしょうか。

httpd 2.4.33のmod_sslでLibreSSL 2.7以上を使うときのパッチ

httpdのバージョンが上がったらそのうち対応されて直ると思いますが
それまでは使えると思うのでメモっておきます。

具体的には次のようなエラーがでた場合の対処です。

LibreSSLのopenssl/dh.hでDH_set0_pqgが宣言されているのに
mod_sslのssl_engine_init.cでDH_set0_pqgがstaticで実装されていて合っていないというエラーです。

このDH_set0_pqgという関数はOpenSSL1.1未満では実装されていないため、
mod_sslはOpenSSLが1.1未満の場合に自前の実装を使うようになっています。

プリプロセッサ的にはMODSSL_USE_OPENSSL_PRE_1_1_APIがONになっていれば
mod_ssl側でDH_set0_pqgを実装する形です。

このMODSSL_USE_OPENSSL_PRE_1_1_APIはLibreSSLを使うとONになるようになっているため
DH_set0_pqgが実装されたLibreSSL 2.7以降と合わせると不整合という状態になってしまいます。
(LibreSSLは基本的にOpenSSL 1.0.1ベースだが、LibreSSL 2.7でOpenSSL 1.0.2や1.1.0の機能がいくらか追加された)

対処としてはmod_ssl側の実装を削除してしまうだけです。

mod_sslとLibreSSLでは微妙に実装内容が違うのですが、きっとLibreSSL側の実装の方が信用できる。
mod_sslの方が信用できるよ派の人はssl_engine_init.c内のDH_set0_pqgを適当にリネームでもすればよいと思います。

あと私はApacheよりNginx派です。