0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DockerコンテナでchmodするとディレクトリがRead-Onlyになる問題と対処法

Posted at

はじめに

Docker/DevContainerの構成を試行錯誤している際に、特定のディレクトリが突然read-only(読み取り専用)になってしまう問題に遭遇しました。この記事では、その原因と対処方法について解説します。

対象とする環境

  • macOS 15.7.2
  • Docker Desktop for Mac 4.51.0
  • DevContainer (Visual Studio Code) 0.431.1

対象とする読者

  • Docker/DevContainer初心者
  • macOS環境でDockerを使用している方
  • Dockerのファイルシステムの仕組みを詳しく知らない方

発生する問題

症状 : ディレクトリが読み取り専用になる

DevContainerの構成を試行錯誤していたところ、ホストOSからマウントされた特定のディレクトリが、コンテナー内でのみread-onlyになる現象が発生しました。ホストOS側では従来通り読み書きが可能な状態でした。

原因の調査

調査の結果、以下のような手順で問題が発生することがわかりました。

  1. Dockerfileやdevcontainer.jsonのpostStartCommandなどでchmodコマンドを実行
  2. パーミッションは正常に変更される
  3. 設定したパーミッション変更コマンドを削除する
  4. しかし、削除したにもかかわらずパーミッションが永続化している

拡張属性の確認

macOSではxattrコマンドでファイルやディレクトリの拡張属性を確認できます。

xattr -l .devcontainer

このコマンドを実行すると、以下のような拡張属性が見つかりました:

com.docker.grpcfuse.ownership: {"UID":-1,"GID":-1,"mode":555}

原因 : Docker Desktop のファイル共有メカニズムと拡張属性

Docker Desktop for Macは、ホストとコンテナー間のファイル共有に複数の方式を提供しています。現在のデフォルトはVirtioFSですが、gRPC FUSEやosxfs(レガシー)も選択可能です。コンテナー内からchmodコマンドでパーミッションを変更すると、Dockerはその変更を拡張属性として永続化します

この拡張属性com.docker.grpcfuse.ownershipは、gRPC FUSEで導入されたメカニズムですが、VirtioFSでも同じ属性名が使用されています(おそらく後方互換性のため)。この拡張属性が設定されると、コンテナー内でのみディレクトリのパーミッションがその属性値で上書きされてしまいます。上記の例では"mode":555(読み取り+実行のみ)が設定されているため、書き込みができなくなっています。

検証実験

この原因を確認するため、以下の3つのテストケースで検証実験を行いました。

dockerコマンドの-vオプションについて

-vオプションで、ホストのディレクトリをコンテナー内にマウントします。

-v <ホストのパス>:<コンテナー内のパス>[:<オプション>]
  • . : ホストの現在のディレクトリ
  • : : ホストのパスとコンテナー内のパスの区切り文字
  • ro : read-only(読み取り専用)オプション

例: -v .:/workspace:ro は「現在のディレクトリを/workspaceに読み取り専用でマウント」という意味です。

テスト1 : 通常のバインドマウント

docker run -v .:/workspace <image>
# コンテナー内の/workspace/.devcontainerを確認

結果 : .devcontainerディレクトリに拡張属性は付与されない(問題なし)

テスト2 : 読み取り専用マウント

docker run -v ./.devcontainer:/workspace/.devcontainer:ro <image>
# .devcontainerディレクトリを読み取り専用でマウント

結果 : 読み取り専用マウントでも.devcontainerディレクトリに拡張属性は付与されない(問題なし)

テスト3 : コンテナー内での chmod 実行

通常のバインドマウント後、コンテナー内で.devcontainerディレクトリに対してchmodを実行:

chmod 755 /workspace/.devcontainer

結果 : com.docker.grpcfuse.ownership 拡張属性が追加される(問題発生)

この検証により、読み取り専用マウント設定が原因ではなく、コンテナー内でのchmod実行が原因であることが明確になりました。

技術的背景 : Docker Desktop のファイル共有メカニズム

Docker Desktop for Macは、LinuxカーネルをベースとしたVM上でDockerを動作させています。ホストのmacOSとVM内のLinux間でファイルを共有するために、以下の3つの方式から選択できます。

  • VirtioFS(デフォルト、Docker Desktop 4.6以降)
    • 高速なファイル共有を実現
    • macOS 12.5以降で利用可能
  • gRPC FUSE
    • VirtioFS以前の実装
    • 拡張属性メカニズムを導入
  • osxfs(レガシー)
    • 初期の実装

拡張属性メカニズム

com.docker.grpcfuse.ownership拡張属性は、gRPC FUSEで導入されたメカニズムです。この仕組みによって:

  • ホストOSのファイルシステムにおける所有権情報を破壊せずに、コンテナー内の所有権を永続化できる
  • パーミッション変更などの操作は拡張属性として記録される

実験結果から確認できたこと :

  • VirtioFS使用時でもcom.docker.grpcfuse.ownership拡張属性が作成される
  • 属性名に"grpcfuse"が含まれているが、VirtioFSでも同じ拡張属性が使用されている

これは、VirtioFSがgRPC FUSEの後継として開発された際に、実装の共通性や後方互換性のために同じ拡張属性メカニズムを採用したものと推測されます。

つまり、コンテナー内でのchmod操作の結果が、使用しているファイル共有方式にかかわらず、ホスト側のファイルシステムに拡張属性として残り続けることになります。

解決方法

拡張属性の削除

macOS上で以下のコマンドを実行し、問題の拡張属性を削除します:

# 拡張属性の確認
xattr -l .devcontainer

# 拡張属性の削除
xattr -d com.docker.grpcfuse.ownership .devcontainer

確認方法

削除後、再び拡張属性を確認します:

xattr -l .devcontainer

何も表示されなければ、拡張属性が正常に削除されています。

この問題から理解できること

1. 拡張属性の永続化メカニズム

コンテナー内でマウントされたディレクトリに対してchmodを実行すると、拡張属性が永続化されることを理解しておきましょう。コンテナー内のパーミッションが意図せず変更されている場合は、xattrコマンドで拡張属性を確認してください。

2. devcontainer.jsonで読み取り専用マウントを指定

特定のディレクトリを、mountsオプションで読み取り専用にできます

{
  "mounts": [
    "source=${localWorkspaceFolder}/.devcontainer,target=/workspace/.devcontainer,type=bind,readonly"
  ]
}

読み取り専用マウントにすることで、chmodを使わずにread-onlyを実現でき、拡張属性を変更せずに済みます。

まとめ

  • Docker Desktop for Macでは、コンテナー内でのchmod実行結果が拡張属性として永続化される
  • 拡張属性com.docker.grpcfuse.ownershipがコンテナー内でのみディレクトリのパーミッションを上書きする
  • 解決方法はxattr -dコマンドで拡張属性を削除すること
  • パーミッションが意図せず変更されている場合はxattrコマンドで拡張属性を確認する
  • 読み取り専用マウントを使用することで拡張属性の永続化を防げる

macOS + Docker環境で開発する際は、この挙動を理解しておくことが重要です。

参考リンク


以上、ありがとうございました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?