dockerは本当に便利で、何でもdockerで開発をしています。
でもちょっと不満があるとすれば、コンテナの中のユーザと、ホスト側で実行したユーザのUID/GIDが異なるため、
コンテナ内のユーザがvolumeマウントして生成するファイルが、ホスト側のユーザパーミッションで書き換えられない
というのが不満でした。
どう解決するのか
この環境はプロダクション環境で使うのではなく、あくまで開発環境で使用することを想定しています。
nodeのオフィシャルイメージだと最初からnodeユーザが登録されているので、
コンテナ内で何かしら動かす際にnodeユーザで実行することを想定しています。
悩んだ挙げ句、とりあえず落ち着いたのは以下。
ホストユーザのUID、GIDを環境変数としてコンテナに渡す
.envファイルを作成し、以下のような情報を記述。
記述する際にはシェルスクリプトを準備して作成。
#!/bin/bash
set -eu
cat <<EOT > .env
LOCALUID=`id -u`
LOCALGID=`id -g`
EOT
生成されたファイルは以下な感じ。
LOCALUID=1003
LOCALGID=1003
entrypointでUID/GID を変更する
nodeのオフィシャルイメージだと最初からnodeユーザが登録されている。
コンテナ内で何かしら動かす際にnodeユーザで実行する。
#!/bin/bash
set -eu
# 一時的なグループを作成
groupadd -g 11111 tmpgrp
# nodeユーザを一時的なグループに一旦所属させる
usermod -g tmpgrp node
# もともと所属していたnodeグループを削除
groupdel node
# ホストユーザのGIDと同じGIDでnode グループを作成
groupadd -g $LOCALGID node
# nodeユーザのGID をホストユーザのGIDに設定
usermod -g $LOCALGID node
# nodeユーザのUID をホストユーザのUIDに設定
usermod -g $LOCALUID node
# 一時的に作ったグループを削除
groupdel tmpgrp
su node
exec "$@"
結果
以下のようなdocker-compose.yamlを作成して実験。
version: "3"
services:
node:
image: node:lts-buster-slim
volumes:
- ./app:/app
- ./entrypoint.sh:/entrypoint.sh:ro
entrypoint: /entrypoint.sh
env_file:
- ./.env
無事ホストユーザと同じUID/GIDに変更されていることが確認。
$docker-compose run --rm node bash
node@e9aa2121a23f:/$ id
uid=1003(node) gid=1003(node) groups=1003(node)
node@e9aa2121a23f:/$
一人で自マシン上で開発しているのならUID/GIDが1000でコンテナ内のUID/GIDも1000で同じだから気にしなくても
良いかなと思うのですが、会社内で共有PC上で開発していると、UID/GIDの1000じゃなくなるのでちょっと困っていました。
これをベースイメージとして社内で使えば、root権限を与えなくてもコンテナが生成したファイルやディレクトリを
ホストユーザが編集・削除できるようになりそうです。