SREチーム、およびPHPバージョンアップチームの金澤です。
先日、ランサーズをEC2での運用からFargateベースのDocker運用に移行できたためPHP7.3→8.1のバージョンアップに着手しています。
※本番環境のコンテナ化については「Lancers本番環境のコンテナ化が完了しました」を参照。
バージョンアップがやや遅れていましたが、バージョンアップ前にDockerベースでの運用体制確立を優先していました。
Dockerベースの運用になったおかげで、CircleCI + によるローリングデプロイが確立し、GitHubのマージボタンを押したタイミングで、Dockerfileも含めた更新リリースが可能になり、バージョンアップのようなサーバー設定の変更リリースも非常にやりやすくなりました。(EC2 + ansible時代は、サーバーの設定関係はオートスケーリングを含め細かく面倒を見る必要があるため大変でした)
今回は、PHP8.1バージョンアップに伴う、OS選択の苦労話を書きたいと思います。
Amazon Linux2で構築
先日、EC2からコンテナに移行したときのPHPバージョンは7.3でした。先にコンテナ運用していた他サービスでは、Alpineベースで構築していたのですが、ランサーズではAmazon Linux2で構築しました。
ランサーズでは、EC2時代からAmazon Linux2を使っており、ログの加工、および転送を行う際にawslogsを使っていたこともあり、互換性を重視した選択でした。
PHP7.3はAmazon Linux2のyumでインストール可能でしたが、PHP8.1ではサポートしていません。
https://repost.aws/questions/QUsfhDbww4SAy8i5Jmd4vcMg/amazon-linux-2-amazon-linux-extras-php-8-1-support
そのため、remiでインストールしました。
※参考資料としてDockerfileを以下のGitHubリポジトリにアップしておきました。https://github.com/LancersDevTeam/PHP_versionup/tree/master/PHP7.3toPHP8.1/docker.amazonlinux2/prd/app-admin
結果、本番環境のawslogsも問題なく動作しました。順調にPHP8.1への移行が完了しました。
(と、このときは思っていました)
M1 Macで開発環境が動かない問題
本番環境のPHP8.1化も終了し、開発メンバーにも開発環境をPHP8.1に移行してもらうようにお願いしていましたが、開発メンバーの1人から、開発環境がビルドできないとの報告がありました。
原因の切り分けをした結果、M1 MacでPHP8.1版のコンテナがビルドできないことが判明。
remiリポジトリ( http://rpms.remirepo.net/enterprise/ )を調査してみると、remi7には、x86_64のパッケージしかなかったため、remi8を調べてみましたが、remi8にはaarch64自体存在しませんでした。
x86_64
remi7:http://rpms.remirepo.net/enterprise/7/remi/x86_64/repoview/
remi8:http://rpms.remirepo.net/enterprise/8/remi/x86_64/repoview/
aarch64(remi7にphp8がない。remi8はそもそも存在しない)
remi7:http://rpms.remirepo.net/enterprise/7/remi/aarch64/repoview/
remi8:http://rpms.remirepo.net/enterprise/8/remi/aarch64/repoview/ (Not Found)
remi自体、個人で運営しているリポジトリで、aarch64でのビルド環境はなさそうで、将来的に対応されることを期待して待つという選択は難しいと判断しました。
https://forum.remirepo.net/viewtopic.php?id=4016
そのため、M1 Macにおける開発環境構築手段として別の方法を考えました。
- Docker Buildをやめる
- x86_64で構築済のコンテナをECRにアップロードし、それを取得して使ってもらう
- ※Docker for Macのエミュレーション機能で
- Amazon Linux2をやめる
- 他のLinux系コンテナで構築する
Docker for Macのエミュレーションに頼るのが一番簡単な解決方法なのですが、本番環境をAWSのGravitonプロセッサで動かす選択肢を捨ててしまいたくなく、Amazon Linux2での構築はあきらめ、別のコンテナOSで構築する決断をしました。
Alpine Linuxで構築
Docker HubのPHP Official ImageはAlpine Linuxベースで提供されています。
https://hub.docker.com/_/php
※このイメージをベースに構築したDockerfileを以下のGitHubリポジトリにアップしました。
https://github.com/LancersDevTeam/PHP_versionup/tree/master/PHP7.3toPHP8.1/docker.alpine/dev/app-admin
Alpineは軽量なDocker Imageですが、インストールするパッケージによっては、makeやgccをインストールしてビルドする必要があり、これを単純にビルドすると、コンテナイメージが簡単に肥大化してしまいます。
イメージが小さくなるようにビルド工夫をしても、結局はライブラリのインストール分だけイメージ容量が増えるので、Alpineが最適な選択になるためには、それなりに条件が必要だと感じました。
(個人的には、Goバイナリで運用する場合はイメージが小さく済むことが多く、最適な選択になりやすいと思いました)
awslogsのインストールが困難な問題
さて、このAlpine Linuxベースで構築したコンテナですが、今度は、awslogsのインストールが困難を極めました。
# pip install awslogs
でインストールされるawslogsは、今回必要なCloudWatch Logs(awslogsd)ではありませんでした。(こちらはツールの様子)
CloudWatch Logsをインストールするには、インストールスクリプト
https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py
を利用するのですが、これがAlpineに対応していないことが判明しました。
手数をかけてAlpineに対応するよりも、別のOSを選択したほうが良いと判断し、Alpine Linuxでの構築も断念しました。
Ubuntu Linuxで構築
Debian系のLinuxであれば、PHP8.1、awslogs共にインストールできることがわかり、最終的に、Ubuntu Linuxで構築しました。
※このイメージをベースに構築したDockerfileを以下のGitHubリポジトリにアップしました。
https://github.com/LancersDevTeam/PHP_versionup/tree/master/PHP7.3toPHP8.1/docker/prd/app-admin
インストールスクリプト
https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py
がサポートするPythonのバージョンはPython2.6~3.5ですが、Ubuntu 22.04 LTSコンテナにインストール済のPythonのバージョンは3.10のため、そのままではインストールできませんでした。
※本件はPython2.7を入れて解決させましたが、Python3.10でもビルドできるようにすればさらにコンテナイメージを減らすことができそうで、今後の課題にします。
※awslogsのインストールは @adachin0817 にも協力いただきました。
インストール手順の詳細内容を ADACHIN SERVER WIKI に記載しています。
現在、このUbuntuベースのコンテナでPHP8.1を運用できています。
さいごに
PHP8.1バージョンアップにようやく着手しましたが、インフラ面において、要件を全て満たすコンテナOSの選択という点で早々と苦労することになり、まずは、このネタだけでブログを書くことにしました。
次回からは、PHP8.1バージョンアップに伴う具体的なソース修正についても書いていきたいと思います。
本ブログ内容の詳細は、2022/8/27に開催されるPHPカンファレンス沖縄2022 で発表予定です。