LoginSignup
4
2

More than 3 years have passed since last update.

dockerのmount volumeのpermissionをfixuidでなんとかする

Posted at

fixuidというコマンドを使う方法を知ったので共有します。

問題

docker/docker-composeでhostからvolumeをマウントして、そこへファイルを吐き出すと、rootで吐き出されてしまう。
あるいは、コンテナ内で作ったユーザーに対応するユーザーがhost側にいない
あるいは、host側のユーザーのUID/GIDを指定してdocker runしても、今度は当該ユーザーがコンテナ内にいない。

問題の根源

docker buildした時とdocker runする時で同じシステムとは限らない
なので、userのid、groupのidが異なってしまう。

対処

概ねこのような感じです

make_env.sh
#!/bin/sh

# 適切な.envを作成できればこれを使わなくてもよい
touch .env
echo "UID=$(id -u $USER)" >> .env
echo "GID=$(id -g $USER)" >> .env
echo "UNAME=$USER" >> .env
...
RUN useradd hoge # ユーザー名は各自かっこいいのつけて
RUN USER=hoge && \
    GROUP=hoge && \
    curl -SsL https://github.com/boxboat/fixuid/releases/download/v0.5/fixuid-0.5-linux-amd64.tar.gz | tar -C /usr/local/bin -xzf - && \
    chmod 4755 /usr/local/bin/fixuid && \
    mkdir -p /etc/fixuid && \
    printf "user: $USER\ngroup: $GROUP\n" > /etc/fixuid/config.yml
# ここまでrootユーザー
# ここからhogeユーザー
USER hoge:hoge

ENTRYPOINT[ "fixuid" ]
# 他にもENTRYPOINTを使っている何かが有ればunshift的につければいい
# ENTRYPOINT[ "fixuid", "docker-php-entrypoint" ] 等
docker-compose.yml
hoge:
  image: php:latest
  user: "${UID}:${GID}" # <= .envから読みこまれる
  volumes:
    - ....

使い方

# 各自、使う人が初回に叩いて.envを生成する
./make_env.sh

# あとは普通に使える
docker-compose up -d

原理

  • Dockerfileのベストプラクティスに則ってbuild時にuserを作っておく。この時点では、UID/GIDはランタイムと一致する保証はない。
  • LinuxのユーザーのUID/GIDは書き換えることが出来る。fixuidはそれを実施した上で、渡したコマンドを実行してくれる
    • 4xxxパーミッションが付いた実行ファイルは、その実行ファイルのownerの権限で動作する。fixuidはコレを利用してsudoなしでuid変更を実現する
    • 他にも$HOMEの書き換えなどやってくれる様子
  • docker run時に、host側ユーザーのuid/gidを外部から与えることで、ファイルシステムに記録されるuid/gidをhost-guestで一致させる
    • 与える手段としては.envを使う。docker-composeは.envを読んでくれる
    • uid/gidはidコマンドで取得
  • uid/gidが一致しているので、hostからもguestからもちゃんと読める!

参考:

4
2
2

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
4
2