環境
- WSL2 - Ubuntu20.04
- Docker 20.10.1
- ruby 3.1.2
- rails 6.1.5
問題
Volumeを使いローカルにデータを保管すると,フォルダがroot権限で作成される.
原因
DockerはWSL環境ではユーザーを指定していない限りコンテナがrootユーザーで実行される.
ちなみにMacOSではこの問題は起こらず,コンテナはローカルユーザーで実行されるらしい.
個人的にDockerの主なメリットにOS間の差異の吸収があるのに[それどうなの?」と感じる.
今後改善されていくのかな?知っている方はコメントお願いします.
対策
Docerfileのentrypointでユーザー作成と権限変更を行う
Dockerfile
FROM ruby:3.1.2
# yarnインストール用に追加
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
&& echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
&& apt-get update -qq \
&& apt-get install -y nodejs postgresql-client yarn
WORKDIR /app
COPY / /
RUN bundle install
# コンテナー起動時に毎回実行されるスクリプトを追加
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
entrypoint.sh
set -e
# Rails に対応したファイル server.pid が存在しているかもしれないので削除する。
rm -f /app/tmp/pids/server.pid
#ユーザーIDの追加,グループIDの変更
echo "Starting with UID : $USER_ID, GID: $GROUP_ID"
useradd -u $UID -o user
groupmod -g $GID user
#権限変更
chown -R user:user /app
chown -R user:user /Gemfile /Gemfile.lock
# コンテナーのプロセスを実行する。(Dockerfile 内の CMD に設定されているもの。)
exec "$@"
コンテナ内ではユーザーおよびグループはIDを参照するため,名前はローカルと違っても大丈夫です.
あとはDockerComposeで環境変数を渡します.
docker-compose.yml
version: '3'
services:
db:
image: mysql:8.0.29
environment:
MYSQL_ROOT_PASSWORD: password
volumes:
- ./db/mysql_data:/var/lib/mysql
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
env_file:
- web.env
volumes:
- .:/app
ports:
- "3000:3000"
depends_on:
- db
web.env
UID=<自分のユーザーID>
GID=<自分のグループID>
.envに直接IDを書き,コンテナに渡しています.
シェルスクリプトを起動させ,自動でローカルの変数を渡すこともできますが,個人開発ならこれで十分だと思います.