Docker Laravel root以外のユーザーで起動する on Ubuntu
Dockerを運用し始めてから約半年、この問題の対処方法を紹介します。 ずっと放置していたんですが、サービスをリリースすることになったためセキュリティの観点から対応しました。
「Nginx + Laravel ( + Mysql ) 」の組み合わせについての方法です。(Mysqlはあんま関係ないかも、mysqlはmysqlユーザーで開始すればOK)
ローカルから編集もできるし、docker上で実行エラーも起きないそんな方法です。
前提条件
こんな感じのプロジェクトディレクトリで運用してます。 Laravelやってる人はぴんとくるものがあると思います。 今回関係あるのは下図の★のところだけです。
project ├── Dockerfile ├── compose_by_env │ ├── docker-compose_cloud.yml │ ├── docker-compose_local.yml ├── docker │ ├── mysql │ │ ├── Dockerfile │ │ └── my.cnf │ ├── nginx │ ├── Dockerfile │ ├── default.conf │ ├── nginx.conf ├── docker-compose.yml -> ./compose_by_env/docker-compose_local.yml ├── logs ★ │ ├── access.log │ └── error.log └── src ★ ├── README.md ├── app ├── artisan ├── bootstrap ├── composer.json ├── composer.lock ├── config ├── database ├── package.json ├── phpunit.xml ├── public ├── resources ├── routes ├── server.php ├── storage ├── tests ├── vendor ├── webpack.mix.js └── yarn.lock
対処
結論から言いますが、いくつか方針とステップがあります。
1.ユーザー作成
ホスト側にdocker の nginx , laravel app内のwww-dataユーザーと同じUID, GIDでユーザーとグループを作成する
2.グループ追加 ホスト側で作成した上記ユーザーグループにホスト側でいつも使っている開発ユーザーを加える
3.Dockerファイル編集
docker の nginx , laravel appをwww-data で立ち上げるようにする(その他もろもろ)
4.所有権変更
workディレクトリ(上図だとsrcフォルダ)以下をnginx , laravel app(docker)上のwww-dataと同じUID:GIDでchownする
5.権限変更
workディレクトリ(上図だとsrcフォルダ)以下のファイル権限を770にする
こうすることでDocker上からはwww-dataユーザーで関係するファイルがすべてwww-data権限で構成されるため実行上のエラーは起きません。
またホスト側においても、開発ユーザーはwww-dataユーザーグループに加わっており770で権限管理されているためローカル編集することができます。
では詳しく見ていきましょう。
1.ユーザー作成、及び 2.グループ追加
nginx及びLaravel app のwww-dataユーザーのUIDは82です。
なので、ホスト上でそのUIDでユーザーを作成します。
私は一身上の都合でユーザー名はdocにしました。(www-dataのほうがわかりやすいかも)
sudo useradd --shell /bin/bash -u 82 -o -m doc sudo groupmod -g 82 doc sudo gpasswd -a $USER doc
3.DockerFile(その他もろもろ)
nginx
・DockerFile
FROM nginx:1.17-alpine WORKDIR / # 【重要】ディレクトリオーナーを変更 RUN touch /var/run/nginx.pid && \ chown -R 82:www-data /var/run/nginx.pid && \ chown -R 82:www-data /var/cache/nginx USER 82 RUN alias ll="ls -al"
USER www-data だと起動できないので、UIDで指定します。 もう一つ、nginxの場合root権限以外で80, 443番ポートを立ち上げることができないっぽいので、default.confで別ポートを指定します。
・default.conf
server { #listen 80; listen 8080; return 301 https://$host$request_uri; } server { #listen 443 ssl; listen 8443 ssl; ・・・以下略
あとnginx.confも今回編集したので貼っておきます。
#user nginx www-data; これをコメントアウト #worker_processes auto; これをコメントアウト worker_processes 1; #これ追加 error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } ・・・以下略
Laravel app
laravelのDockerFileも同様です。
FROM php:7.3-fpm-alpine LABEL maintainer "ucan" COPY ${PROJECT_PATH} /work RUN chown -R www-data:www-data /work RUN chmod +x /work/public USER 82 RUN alias ll="ls -al"
4.所有権変更 及び 5.権限変更
最後にホスト側でこれ。 私の場合logsというフォルダーにnginxログファイルを吐いているので、そこも変えています。
cd project sudo chown -R doc:doc src sudo chown -R doc:doc logs sudo chmod -R 770 src sudo chmod -R 770 logs
あとは
docker-compose build docker-compose up -d
でおけ。
docker セキュリティ
rootで実行するとよくないので、今回のやり方はその対策にもなっています。
残された課題
ローカルで新規にファイルを作成した場合、所有権がローカルユーザーとなるため、
sudo chown -R doc:doc src
のコマンドをどこかに保存して、新規作成のたびに実行するような仕組みをつくりましょう。 暫定と呼ぶ所以はこの問題が残されているからです。。