Help us understand the problem. What is going on with this article?

Docker+Nginx+PHP-FPMでユーザーをroot以外に設定する

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としています。

./docker/php/Dockerfile
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のusergroupディレクティブは無効になりますし、かといってrootにするわけにもいきませんし、ハマりました。

Dockerfile、php-fpmの設定を修正する

調べていく中で、少し古い内容ですが、下記が参考になりました。
https://github.com/phpbrew/phpbrew/issues/459

root以外のユーザーでphp-fpmを立ち上げたい場合、php-fpm用のグループを設定することで実行ができるようになるとのことです。

そこで、www.confでグループを設定し、そのグループに権限を与えます。

下記がwww.confの設定です。

/usr/local/etc/php-fpm.d/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に関係するファイルにも権限を付与します。

./docker/php/Dockerfile
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周りの設定で詰まっていたら試してみてください。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした