コンテナからマウントしたファイルなどをいじると、ホスト側ユーザーと所有者が異なってしまう問題があります。
これが結構煩わしいので、ホスト側ユーザーと同じUID、GIDでマウント先のファイルを扱う方法を考えてみました。
コンテナ起動時に、ホスト側と同じUID、GIDを持つユーザーを作成して、コマンドを実行する方針です。
実装
ディレクトリ構成
sample/
| Dockerfile
| entrypoint.sh
| run.sh
Dockerfile
FROM debian:bullseye-slim
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
entrypoint.sh
- 環境変数として受け取った
LOCAL_UID
LOCAL_GID
でグループとユーザーを作成します。 - マウント先の所有者を 1. で作成したユーザーとグループに chown します。 (一応)
chown -R $UNAME:$UNAME /opt/app
- 作成したユーザーで任意のコマンドを実行します。
exec su $UNAME -c '...'
entrypoint.sh
#!/bin/bash
# ホスト側の実行ユーザーと同一のUID, GIDを持つユーザーを作成
HOST_UID=${LOCAL_UID}
HOST_GID=${LOCAL_GID}
UNAME="app"
# グループIDを指定してグループを作成
# -g: グループIDを指定する
groupadd -g $HOST_GID $UNAME
# ユーザーIDを指定してグループを作成
# -u: ユーザーIDを指定
# -o: ユーザーIDが同じユーザーの作成を許す
# -m: ホームディレクトリを作成する
# -g: ユーザーが属するプライマリグループを指定する(グループID or グループ名)
# -s: ログインシェルを指定する
useradd -u $HOST_UID -o -m -g $HOST_GID -s /bin/bash $UNAME
export HOME=/home/$UNAME
# マウント先のを所有者作成したユーザーとグループに変更
chown -R $UNAME:$UNAME /opt/app
# 作成したユーザーで任意のコマンドを実行
exec su $UNAME -c 'id | tee /opt/app/id.txt'
run.sh
-
docker run
時に環境変数にユーザーIDとグループIDを設定します。
run.sh
#!/bin/bash
SCRIPT_DIR=$(cd $(dirname $0); pwd)
cd $SCRIPT_DIR
# イメージのビルド
IMAGE_TAG="exec_host_user:latest"
docker build -t $IMAGE_TAG .
# 現在の実行ユーザー・グループを環境変数に設定してコンテナを起動
LOCAL_UID=$(id -u)
LOCAL_GID=$(id -g)
docker run \
-e LOCAL_UID=$LOCAL_UID \
-e LOCAL_GID=$LOCAL_GID \
-v $SCRIPT_DIR/app:/opt/app \
$IMAGE_TAG
実行方法
bash run.sh
# コンテナで作成されたファイルを確認 (ファイルの所有者がコンテナ起動ユーザーになっている)
ls -alF app/id.txt