経緯コンテナをrootとして実行することは重大なセキュリティリスクです。これを解決するため、ほとんどの公式Node.jsイメージにはnodeという名前の非ルートユーザーが組み込まれています。しかし、このユーザーに切り替えると、パーミッションエラーという厄介な壁にぶつかることがよくあります。これは、npm installの実行時や、Next.jsやViteなどのフレームワークが起動時に.cacheフォルダに書き込もうとした際によく発生します。
このエラーは通常、DockerfileにUSER nodeを追加した直後に発生します。ビルドまたは実行プロセスが、特定のメッセージとともにクラッシュします。
Error: EACCES: permission denied, mkdir '/app/node_modules/.cache'
根本的な原因問題は単純な所有権にあります。DockerがWORKDIRやCOPYなどのコマンドを実行する際、デフォルトではrootユーザー(UID 0)が使用されます。これらのコマンドによって/appフォルダが作成された場合、その所有者はrootになります。その後、nodeユーザー(通常はUID 1000)に切り替えると、そのユーザーにはrootが作成したファイルを変更する権限がありません。
主な発生要因は以下の通りです:
- デフォルトのCOPY: フラグなしで
COPY . .を実行すると、コンテナ内のすべてのファイルの所有者がrootになります。- ボリュームによる上書き: ローカルフォルダをnode_modulesにマウントすると、ホスト側のパーミッションが同期され、コンテナ内部のユーザーと一致しなくなることがあります。- ディレクトリの自動作成:WORKDIR命令は、デフォルトで存在しないパスをrootとして作成します。## ステップバイステップの修正方法### 1. Dockerfileで--chownフラグを使用する最も信頼できる修正方法は、コードをコピーする前にnodeユーザーがディレクトリを所有していることを確認することです。また、--chownフラグを使用して、コピープロセス中に所有権を変更するようDockerに指示する必要があります。
# 安定性のために特定のバージョンを使用
FROM node:18-alpine
# 正しいパーミッションでアプリディレクトリを事前に作成
RUN mkdir -p /home/node/app && chown -R node:node /home/node/app
WORKDIR /home/node/app
# 早めに非ルートユーザーに切り替える
USER node
# Dockerキャッシュを活用するため、先にパッケージファイルをコピー
COPY --chown=node:node package*.json ./
RUN npm install
# 残りのソースコードをコピー
COPY --chown=node:node . .
CMD ["npm", "start"]
2. Docker Composeでのボリュームの扱いローカル開発では、ホストマシン(Mac/Windows/Linux)とコンテナでユーザーIDが異なるため、パーミッションの問題が発生しやすくなります。ホストのnode_modulesがコンテナ側のバージョンを上書きするのを防ぐには、匿名ボリュームを使用します。これにより、コンテナ側のフォルダはDockerの内部エンジンによって管理されるようになります。
services:
web:
build: .
user: "node"
volumes:
- .:/home/node/app
- /home/node/app/node_modules # この匿名ボリュームが内部のパーミッションを保護する
environment:
- NODE_ENV=development
3. 実行中のコンテナに対するクイックフィックスすでに実行中のコンテナを修正する必要がある場合は、rootユーザーとしてdocker execを使用し、強制的に所有権を変更できます。これは一時的な応急処置ですが、急ぎの場合に有効です:
docker exec -u root -it <container_id> chown -R node:node /home/node/app/node_modules
修正の確認コンテナ内のディレクトリ所有権を確認して、変更が反映されたかチェックしましょう。次のコマンドを実行します:
docker exec -it <container_id> ls -la /home/node/app
出力結果で、node_modulesの行を確認してください。以下のようになっているはずです:
drwxr-xr-x 100 node node 4096 Oct 20 10:00 node_modules
もし列が依然としてroot rootと表示されている場合は、chownコマンドが漏れているか、ボリュームマウントによって上書きされています。
予防策とヒントLinuxのパーミッションは、特にPCとコンテナ間でUIDが一致しない場合に厄介な問題となります。パーミッションビットを可視化することで、ミスを防ぐことができます。
私はよくToolCraftのUnix Permissions Calculatorを使用して、chmodのロジックを確認しています。これは、チェックボックス(読み取り/書き込み/実行)を必要な数値コードに変換してくれるシンプルなブラウザツールです。ブラウザ上でローカルに動作するため、機密性の高い設定の確認にも安全です。
重要なポイント:
- 常に--chownを使用する: 非ルートユーザーを使用する場合、
--chown=node:nodeなしでCOPYを使用してはいけません。- 順序が重要:USERを切り替える前に、WORKDIRを作成しパーミッションを設定してください。- node_modulesを保護する: Composeでは匿名ボリュームを使用して、ホスト側のパーミッション競合を防ぎましょう。- 777を避ける: エラーを直すためにchmod 777を決して使わないでください。これは重大なセキュリティホールになります。chownを使用して、必要なユーザーにのみアクセス権を付与するようにしましょう。

