Docker Composeでnginxとphp-fpmの環境を作るときの設定で少しハマりました。
実行ユーザーをrootのままにすればdocker-composeですんなり設定できるかもしれませんが、今後の運用も考えてセキュリティ面でroot以外に設定したほうが良いと思い、そのように設定を進めました。
php-fpmとDockerfileの設定を見直すことで実行ユーザーの設定ができましたのでその経緯を書いていきます。
今回想定している環境は下記になります。
- docker 18.09.2
- docker-compose 1.23.2
- image php:7.2-fpm
- image nginx:1.15
TL; DR
php-fpmのwww.confでuser, groupを削除しlisten.groupのみ設定。そしてDockerfileでphp-fpmのファイルにグループ権限付与することでroot以外のユーザーで実行できる。
Dockerfileの実行ユーザーはroot以外にする
NginxとMySQLはオフィシャルのイメージをビルドするだけで済みましたが、
PHPは設定する部分や必要な拡張子などが多かったのでDockerfileを個別に作りました。
ベストなDockerfileを書きたかったのでDockleを用いてチェックしたところ、
WARN - CIS-DI-0001: Create a user for the container
* Last user should not be root
という警告が。
こちらにも載っていました。
https://github.com/goodwithtech/dockle/blob/master/CHECKPOINT.md#cis-di-0001-create-a-user-for-the-container
セキュリティ的にも、Dockerfileでコンテナを実行するユーザーはroot以外の方が良いです。
それにdocker-compose exec
をroot権限で実行できてしまうのは危険ですからね。
そこでphp-fpmのDockerfileにユーザーを追加してみます。
php-fpmのDockerfileに追記
php-fpm用のユーザーを追加します。今回はwww-user
としています。
FROM php:7.2-fpm
# Install extensions
RUN apt-get update \
&& apt-get install -y libicu-dev zip unzip curl zlib1g-dev libpng-dev vim procps git \
&& docker-php-ext-install intl opcache \
&& docker-php-ext-enable intl opcache \
&& docker-php-ext-install pdo pdo_mysql mysqli\
&& docker-php-ext-install mbstring \
&& docker-php-ext-install gd \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
+ RUN useradd -ms /bin/bash www-user \
+ && echo "www-user:piyohoge" | chpasswd
+ USER www-user
これで再度ビルドしてみます。
% docker-compose down
% export $(cat .env | xargs)
% docker-compose build --no-cache
Creating network "myservice_app-network" with the default driver
Building php
Step 1/17 : FROM php:7.2-fpm
...
...
Successfully built 8d4ff435a5d2
Successfully tagged myservice_php:latest
% docker-compose up -d
creating network "myservice_mynetwork" with the default driver
Creating myservice_php_1 ... done
Creating myservice_db_1 ... done
Creating myservice_web_1 ... done
上手くいったような気がします。
しかし、
php-fpmのパーミッション周りでエラーが
ログを見てみるとエラーになっていました。
% docker-compose logs php
Attaching to myservice_php_1
php_1 | NOTICE: [pool www] 'user' directive is ignored when FPM is not running as root
php_1 | NOTICE: [pool www] 'user' directive is ignored when FPM is not running as root
php_1 | NOTICE: [pool www] 'group' directive is ignored when FPM is not running as root
php_1 | NOTICE: [pool www] 'group' directive is ignored when FPM is not running as root
php_1 | ERROR: unable to bind listening socket for address '/var/run/php-fpm.sock': Permission denied (13)
php_1 | ERROR: unable to bind listening socket for address '/var/run/php-fpm.sock': Permission denied (13)
php_1 | ERROR: FPM initialization failed
php_1 | ERROR: FPM initialization failed
myservice_php_1がExitに。
エラー内容を見てみると、php-fpmの実行ユーザーが上手く設定されていないようです。
rootじゃないとphp-fpmのuser
、group
ディレクティブは無効になりますし、かといってrootにするわけにもいきませんし、ハマりました。
Dockerfile、php-fpmの設定を修正する
調べていく中で、少し古い内容ですが、下記が参考になりました。
https://github.com/phpbrew/phpbrew/issues/459
root以外のユーザーでphp-fpmを立ち上げたい場合、php-fpm用のグループを設定することで実行ができるようになるとのことです。
そこで、www.conf
でグループを設定し、そのグループに権限を与えます。
下記がwww.conf
の設定です。
[global]
daemonize = no
; Start a new pool named 'www'.
; the variable $pool can be used in any directive and will be replaced by the
; pool name ('www' here)
[www]
- user = nginx
- group = nginx
listen = /var/run/php-fpm.sock
- listen.owner = nginx
listen.group = nginx
+ listen.mode = 0660
Dockerfileの方でもグループへの権限を付与します。
php-fpmの実行ユーザーwww-user
を先ほど設定したグループに追加します。
ただ、上記で使用しているusermod
はグループを全て上書きしてしまい危険なので別の書き方にします。
php-fpmに関係するファイルにも権限を付与します。
FROM php:7.2-fpm
# Install extensions
RUN apt-get update \
&& apt-get install -y libicu-dev zip unzip curl zlib1g-dev libpng-dev vim procps git \
&& docker-php-ext-install intl opcache \
&& docker-php-ext-enable intl opcache \
&& docker-php-ext-install pdo pdo_mysql mysqli\
&& docker-php-ext-install mbstring \
&& docker-php-ext-install gd \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
+ RUN chown -R www-user:nginx /var/www/ \
+ && chown -R www-user:nginx /var/run/ \
+ && chown -R www-user:nginx /var/log/
- RUN useradd -ms /bin/bash www-user \
+ RUN useradd -ms /bin/bash -g nginx www-user \
&& echo "www-user:piyohoge" | chpasswd
USER www-user
docker volume rm
でボリュームを削除して再ビルド。
% docker-compose build --no-cache && docker-compose up -d
...
% docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------------------------
myservice_db_1 docker-entrypoint.sh mysqld Up 0.0.0.0:3306->3306/tcp
myservice_php_1 docker-php-entrypoint php-fpm Up 9000/tcp, 9001/tcp
myservice_web_1 /bin/sh -c nginx -g daemon ... Up 0.0.0.0:443->443/tcp, 0.0.0.0:8080->80/tcp
これで上手く立ち上がりました。
初歩的なところかもしれませんが、もしphp-fpm周りの設定で詰まっていたら試してみてください。