Tagbangers Blog

Laravel Container環境内packageの脆弱性をCloud NativeのPrincipleを用いて解決

Introduction

PHPのApplication(Laravel)をContainerで動かす際に一般的にはDockerfileを用いると思うが、
dependenciesの脆弱性やpackageのUpdateなので開発者が手動で治す必要が出てくるケースがあります。

Containerで動かすImageは常に最新のpackageを保つ必要があるが、開発者が一つ一つ更新するのはかなり手間がかかるしCloudNativeの観点から見るとあまり好ましくないです。


そこでApplicationをcommandでpackしてimageを作れば毎回最新のimageを使用することができ、開発者のimageの脆弱性に対するconcernを取り除けると考えLaravel のApplicationのImage生成にpackを使用することに利用可能であったため記事にしました。


Prerequisite Background

PHPの実行環境としてメジャーなものであれば以下のstackが挙げられる。

Apache + PHP

  • Apacheのprocess内の一部分として、php scriptの実行環境が提供されている。

Nginx + PHP

  • Nginxのprocessとは別にruntimeのwebserverをphp-fpmが持つ。

  • NginxとPHPがtcp、またはsocket接続。

Nginx / Apacheの選定基準については以下を参照してください。

参考:   Nginx / Apache 


Main Contents

buildpackをLaravel Projectで使用できればimageの管理を簡略化でき、

buildpackがlaravel (php) project下でimage作成に使用。


今回は以下のProviderのbuildpackを使用し検証。

Provider Name

Provider Refs

Provider Official

Heroku

heroku/buildpacks:18

Heroku Official



今回使用するstack 

Nginx + PHP


設計

$ docker run -d -p 80:8080 <image-name>


と実行するとlaravelのWelcome Pageがlocalhostでaccessできるものに決定。


Introduce

Step 1: Pre Installation

Imageの作製に必要なものをinstallします。以下のものを用意してくだない。

1. Docker For Desktop 

2. Pack Command

installはこちら => buildpack.io

3. Laravel

以上となります。

Step2: Installation

作業Directoryで

$ composer create-project  laravel/laravel --prefer-dist sample_buildpack_laravel
$ cd sample_buildpack_laravel
$ composer install

を実行。


Step3: Pre Build

Image作製前にImageのconfig情報を設定する必要があります。
おもにDockerの起動時に実行されるcommandを設定する Procfile

Image内のNginxの設定を司る nginx_app.conf

Image内のphpのconfigを設定する .user.ini (php.iniと同じ働きとみなしても構いません)
また.user.iniはoptionなのでなくても構いません。

1. Procfileと起動shellの作製

Procfile

web: ./entry.sh


entry.sh

#!/bin/bash
echo $ENV_SECRETS | tr ' ' '\n' > .env;
php artisan cache:clear;
php artisan config:clear;
php artisan view:clear;
$(composer config bin-dir)/heroku-php-nginx -C nginx_app.conf public/;


環境変数はimageに依存してはならないのでdocker起動時に$ENV_SECRETSにまとめて渡すようにします。
.envをそのまま使いたい場合はecho $ENV_SECRETS | tr ' ' '\n' > .env;をcomment outしてください。


2. nginx_app_confの設定

nginx_app.conf

listen 8080 default_server;
location / {
    root /app/public;
    index index.php index.html;
}
location @rewriteapp {
    rewrite ^(.*)$ /index.php$1 last;
}

image作成時にnginxの設定をしたい場合はこちらに記入します。port を指定しなければ毎回randomに使われるので今回はport 8080を利用しました。port 80を使いたいところですが今回のimageで使用する軽量コンテナ内で内部的にすでにつかわれているので80を避けました。詳しくはこちら


3. .user.iniの設定 (Option)
.user.iniを設定したい場合は普段、.php.iniに記述しているものを書きましょう。

 .user.ini

post_max_size = 20M
max_input_vars=100000
upload_max_filesize = 5M


Step4: Build

実際にimageをbuildしてみましょう。

$ pack build <image-name>:<tag> --buildpack heroku/php --buildpack heroku/nodejs --builder heroku/buildpacks:18

frontにwebpackを使用していない場合は --buildpack heroku/nodejs を入れなくても大丈夫です。


Step5: Run

$ docker run -d -e ENV_SECRETES='DB_CONNECTION=mysql DB_HOST=127.0.0.1' -p 80:8080 --name <container-name> <image-name>:<tag> 


localhostにaccessできれば完成です。お疲れさまでした。
ENV_SECRETSはか各自、好きなものを指定してください。


Conclusion

このように、pack commandを使うだけでdockerfileを書かなくてもpackageを最新に保つことができる。
packをci/cdに組み込めばかなり簡単にArtifactを抽出できる。 ためしてしてはどうでしょうか!

参考: Application Repositoryはこちら


Appendix

Listenしているportを作製されたimageのcontainerの中身を少し見てみました。


しっかりとnginxがbindされています。

ここまで、読んでいただきありがとうございました。