ログの回転を伴うソケットでのnginxとphpのドッキング

Habréに関する記事では、「 docker way」(TM)について説明されていました。
コンテナごとに1つのプロセス
各コンテナには1つの懸念事項のみを含める必要があります



アプリケーションを複数のコンテナに分離すると、水平方向のスケーリングとコンテナの再利用がはるかに簡単になります。 たとえば、Webアプリケーションスタックは、Webアプリケーション、データベース、およびメモリ内キャッシュを分離した方法で管理するために、それぞれ独自のイメージを持つ3つの個別のコンテナで構成されます。



「コンテナごとに1つのプロセス」があるはずだと聞いたことがあるかもしれません。 このマントラには善意がありますが、コンテナごとにオペレーティングシステムプロセスが1つしかないことは必ずしも真実ではありません。 コンテナがinitプロセスで生成できるようになったという事実に加えて、一部のプログラムは独自の追加プロセスを生成する場合があります。 たとえば、Celeryは複数のワーカープロセスを生成できますが、Apacheはリクエストごとにプロセスを作成する場合があります。 多くの場合、「コンテナごとに1つのプロセス」が良い経験則ですが、それは難しくて速い規則ではありません。 コンテナをできるだけ清潔でモジュール式に保つために、最善の判断をしてください。



コンテナーが相互に依存している場合、Dockerコンテナーネットワークを使用して、これらのコンテナーが通信できることを確認できます。
nginxのドッキング時にこの原則に従うと、2つの結果が生じます。 UNIXソケットを介した異なるプロセスでのnginxとphp-fpmの相互作用の構成は、見かけよりも少し複雑です。 そして、通常のインストール中に箱から出てくるログ回転は、原則として実行することはできません。 別のプロセスを必要とするシグナルUSR1 nginxを送信する必要があります。



議論の結果、USR1 nginx信号を送信する代わりに、logrotate構成にcopytruncateオプションを追加できることが判明しました。 これは、コンテナが複数のプロセスを開始する必要がないことを意味します。 ただし、cronによるログローテーションの起動を設定するすべての手順は、コンテナー内だけでなく、コンテナーが動作するホスト上でも実行する必要があります。 1つのコンテナーでWebサーバーとログのローテーションを開始する場合、ホストで個別にローテーションを構成する必要はなくなりました。





上記のリンクはソリューションです。 しかし、初めて動作しなかったため、理由を探す必要がありました。 したがって、参考文献に加えて、実験の結果を提示します。 DDoS攻撃に対する保護方法を理解するために、nginxサーバー(Luaスクリプトエンジンを備えたTaobaoのnginxアセンブリ)の代わりにopenrestyが起動されます。 このサーバーには、nginxとは異なるファイルのディレクトリがあります。 しかし、他のすべてはまったく同じです。



最初に、プロジェクトのルートディレクトリにdocker-compose.ymlファイルを作成します。



version: "3" services: app: build: context: ./docker/php # dockerfile: docker/php/Dockerfile args: UID: "3000" working_dir: /app nginx: build: context: ./docker/nginx # dockerfile: docker/nginx/Dockerfile args: UID: "3000" ports: - 8000:80
      
      





コンテナ作成スクリプトはdocker / php / Dockerfileおよびdocker / nginx / Dockerfileファイルに保存されると想定しています。 Dockerfileという名前はデフォルト名であるため、構成で明示的に設定する必要はありません。



docker / php / Dockerfileファイルを作成します。



 FROM php:7-fpm ARG UID RUN addgroup --gid $UID --system app \ && adduser --uid $UID --system --disabled-login --disabled-password --gid $UID app
      
      





php:7-fpmイメージが読み込まれ、ユーザーはUIDパラメーター(docker-compose.yml UID:3000)で指定された識別子とappグループのappという名前で作成されます。 これは、openrestyが起動されるコンテナーからソケットを読み取る権限を設定するために必要です。



nginxまたはopenrestyでログローテーションを取得するには、Webサーバーの再起動時にコンテナーがシャットダウンしないこと、およびcronが同じコンテナーで実行されていることが必要です。 つまり、単一プロセスのコンテナではありませんが、そうでない場合は失敗します。 スーパーバイザーを介して複数のプロセスを開始することをお勧めします。



docker / nginx / Dockerfileファイルを作成します。



 FROM openresty/openresty:xenial RUN apt-get update && apt-get install -y supervisor cron logrotate COPY ./supervisord.conf /etc/supervisor/conf.d/supervisord.conf COPY ./logrotate.conf /etc/logrotate.conf COPY ./cron.d /etc/cron.d/nginx ARG UID RUN mkdir -p /var/log/supervisor \ && chmod 644 /etc/logrotate.conf && chown root:root /etc/logrotate.conf \ && chmod 644 /etc/cron.d/nginx && chown root:root /etc/cron.d/nginx \ && addgroup --gid $UID --system app \ && adduser --uid $UID --system --disabled-login --disabled-password --gid $UID app ENTRYPOINT ["/usr/bin/supervisord"]
      
      





まず、必要なプログラムがすべてインストールされます。 次に、構成ファイルが./docker/nginx/ディレクトリーからコンテナーの内部ファイルシステムにコピーされます。 さらに、これらのファイルの一部には644のアクセス許可が割り当てられています(そうでない場合、システムはログをローテーションしません)。 また、ユーザーとアプリグループは同じ識別子(UID:3000)で作成されます。



また、いくつかの構成ファイルを作成する必要があります。



ファイルdocker / php / zz-docker.conf(名前zz-docker.confはphp:7-fpmイメージ構成に存在します。これはどこにも記述されておらず、変更できます。残念ながら、現時点ではイメージの詳細な説明はなく、後で調べる必要がありますリポジトリからのダウンロード):



 [global] daemonize = no [www] ;listen = [::]:9000 # Don't need this listen = /sock/docker.sock listen.owner = app listen.group = app listen.mode = 0660
      
      





listen = /sock/docker.sock



は、nginx構成と同じになります。



メインのnginx構成ファイルを書き換える必要があります。 openrestyでは、必要なパラメーターは含まれていません。これは、ログ、プロセス識別子、ユーザー(アプリ)、および仮想サーバー構成のディレクトリ(/conf.d)の場所です。



 user app; error_log /var/log/nginx/error.log debug; pid /var/run/nginx.pid; http { access_log /var/log/nginx/access.log; include mime.types; default_type application/octet-stream; server { listen 80; server_name localhost; location / { root html; } } include /usr/local/openresty/nginx/conf/conf.d/*; }
      
      





server.conf構成で仮想サーバーを作成します。



 server { listen 80; server_name local; root /usr/share/nginx/html; disable_symlinks off; client_max_body_size 50M; location ~ (/assets|/favicon.ico) { try_files /build$uri $uri =404; } location / { try_files $uri /app.php$is_args$args; } location ~ \.php$ { fastcgi_pass unix:/sock/docker.sock; try_files $fastcgi_script_name =500; fastcgi_split_path_info ^(.+\.php)(/.*)$; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } }
      
      





ポートを介しunix:/sock/docker.sock



プロキシにunix:/sock/docker.sock



はなく、 unix:/sock/docker.sock



ソケットunix:/sock/docker.sock



を介してunix:/sock/docker.sock







次に、logrotate.confファイルを作成します。



 /var/log/nginx/*.log { size=1k missingok rotate 8 notifempty sharedscripts postrotate [ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid` endscript }
      
      







そして、cronの仕事:



 SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin MAILTO="" # mh dom mon dow user command * * * * * root logrotate -v /etc/logrotate.conf #
      
      







ファイルサイズサイズ= 1k、1分ごとにローテーションを実行(* * * * *)。実稼働サーバーではなく、最小限の時間コストでログのローテーションを観察できるようにするため。 logrotateコマンドは、ログをアーカイブファイルにコピーします。 ただし、nginxが再起動されるまで、新しい空のログファイルの実際の作成は行われません。 nginxが再びログを開くために、素晴らしいコマンドkill -USR1 `cat /var/run/nginx.pid`







最後に、スーパーバイザーの構成:



 [supervisord] nodaemon=true logfile=/dev/null [program:nginx] command=/usr/local/openresty/bin/openresty -g 'daemon off;' [program:cron] command=cron -f
      
      





これらのすべての構成ファイルがどこにあるかは問題ではありません。 すべてのパスは、DockerfileのCOPYステートメント、およびdocker-compose.ymlのボリューム値で指定されます。 次に、辛抱強く、docker-compose.ymlに必要なすべてのパスを書き留める必要があります。



 version: "3" services: app: build: context: ./docker/php args: UID: "3000" working_dir: /app volumes: - ./:/app - ./html:/usr/share/nginx/html - ./docker/php/zz-docker.conf:/usr/local/etc/php-fpm.d/zz-docker.conf - ./docker/sock:/sock expose: - 9000 links: - mysql nginx: build: context: ./docker/nginx args: UID: "3000" ports: - 8000:80 volumes: - ./:/app/ - ./html/:/usr/share/nginx/html/ - ./docker/nginx/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf - ./docker/nginx/conf.d/:/usr/local/openresty/nginx/conf/conf.d/ - ./docker/nginx/log/:/var/log/nginx/ - ./lua/:/usr/share/nginx/lua/ - ./docker/sock/:/sock/ links: - app depends_on: - app
      
      





これで、Luaスクリプトを追加できます( Habrに関する記事を参照 )。



apapacy@gmail.com

2018年1月27日



All Articles