My開発メモ

UbuntuのDockerコンテナを作成し、そこにPHP8.3-ztsをインストールする

マルチスレッドなPHP(ThreadSafety=enable)を手に入れるには、PHPを自分でコンパイルするしかない、ということらしい。

zts(ThreadSafety=enable)なPHPをDockerHubで見つけたのだが、それをもとにコンテナを作って parallel をインストールしようとして、うまくいかなかった。

そんなこともあって、PHPを自力でコンパイルしてみた。
いろいろと試行錯誤したのだが、とりあえずここまでの手順をまとめておく。

ビルドの準備

PHPのソースコードは、
https://www.php.net/distributions/php-8.3.13.tar.gz
から入手した。

とりあえず、このソースコードを ./configure & make してみた。
すると、不足なものがあるとコンパイルが止まるので、それらを apt-get で
インストールした。

また、phpをビルドするのに libsodium が必要だったので、
(コンパイルが停止して、”not found libsodium” というメッセージが出た)
libsodiumのソースコードをここから入手した。
https://download.libsodium.org/libsodium/releases/LATEST.tar.gz

また、拡張モジュールとして parallel をインストールするため、以下からソースコードを入手した。

$git clone https://github.com/krakjoe/parallel.git

そして、以下のようにフォルダを作成した。

my-php8.3/
    +-- src/
    |     +-- php-8.3.13.tar.gz
    |     +-- LATEST.tar.gz
    |     +-- parallel/
    +-- Dockerfile
    +-- docker-compose.yml

Dockerfile は以下である。

Dockerfile
FROM ubuntu:24.04                                 #  (1)

RUN apt-get update --fix-missing
RUN apt-get -y install wget \
                       build-essential \
                       unzip \
                       vim \
                       less \
                       tzdata \
                       apache2 \
                       apache2-dev \
                       bison \
                       re2c \
                       pkg-config \
                       libxml2-dev \
                       libsqlite3-dev \
                       curl \
                       libcurl4-openssl-dev \
                       libonig5 \
                       libonig-dev \
                       libreadline.dev \
                       libargon2-1 \
                       libargon2-dev \
                       libssl-dev \
                       libz-dev                   # (2) 

ADD ./src/php-8.3.13.tar.gz /usr/local/src/       # (3)
ADD ./src/LATEST.tar.gz /usr/local/src            # (4)
WORKDIR /usr/local/src/libsodium-stable           # (5)
RUN ./configure
RUN make && make install

WORKDIR /usr/local/src/php-8.3.13
RUN ./configure --build=x86_64-linux-gnu \
  --prefix=/usr \
  --libdir=/usr/lib/php \
  --libexecdir=/usr/lib/php \
  --datadir=/usr/share/php/8.3 \
  --mandir=/usr/share/man \
  --with-config-file-path=/etc/php/8.3/cli \
  --with-config-file-scan-dir=/etc/php/8.3/cli/conf.d \
  --enable-option-checking=fatal \
  --with-mhash \
  --with-pic \
  --enable-mbstring \
  --enable-mysqlnd \
  --with-password-argon2 \
  --with-sodium=shared \
  --enable-pdo \
  --with-pdo-mysql \
  --with-pdo-sqlite=/usr \
  --with-sqlite3=/usr \
  --with-curl \
  --with-iconv \
  --with-openssl \
  --with-readline \
  --with-zlib \
  --enable-phpdbg \
  --enable-phpdbg-readline \
  --with-pear \
  --with-libdir=lib/x86_64-linux-gnu \
  --enable-embed \
  --enable-sockets \
  --disable-cgi \
  --enable-zts \
  --disable-zend-signals \
  build_alias=x86_64-linux-gnu                    # (6)

RUN make -j4                                      # (7)
RUN make install

RUN apt-get -y install php-curl \
                  php-dev \
                  libapache2-mod-php \
                  php-pear \
                  php-mbstring                    # (8)

COPY ./src/parallel /usr/local/src/parallel       # (9)
WORKDIR /usr/local/src/parallel                   # (10)
RUN phpize                                        # (11)
RUN ./configure --enable-parallel
RUN make && make test
RUN make install

RUN echo "extension=parallel.so" >> /etc/php/8.3/mods-available/parallel.ini  # (12)
RUN ln -s /etc/php/8.3/mods-available/parallel.ini \     # (13)
          /etc/php/8.3/cli/conf.d/30-parallel.ini
RUN ln -s /etc/php/8.3/mods-available/parallel.ini \
          /etc/php/8.3/apache2/conf.d/30-parallel.ini
          

RUN a2enmod rewrite
RUN service apache2 start                        # (14)

RUN apt-get clean
RUN echo "alias ll='ls -lF'" >> /root/.bashrc    # (15)

WORKDIR /var/www/html                            # (16)
  1. コンテナの基盤として Ubuntu を選んだのは、慣れているからである。
  2. PHPをビルドするのに必要なものを、あらかじめインストールしておいた。
  3. ADDコマンドを使うと、圧縮ファイル(PHP8.3)をコピーし、解凍してくれる。
  4. libsodium の最新版アーカイブをコピー、解凍する。
  5. LATEST.tar.gz を解凍すると libsodium-stable というフォルダができる。その中に移動してビルドするために WORKDIR を /usr/local/src/libsodium-stable とした。
  6. configureオプション。これは、 php:8.3-zts を参考にした。
    ここで、–enable-zts とするのが、今回の目的である。
  7. ビルドする。-j4 というオプションは、cpuのコア数である。この指定によって、cpuのコアを有効に使用してコンパイルできるらしい。cpuのコア数は、
    $ grep “cpu cores” /proc/cpuinfo
    で確認できる。
    ( http://phpinternalsbook-ja.com/build_system/building_php.html )
  8. これらは、phpをインストールした後でインストールする必要があると判断したので、ここでインストールしている。
  9. gitでクローンした parallelフォルダをここにコピーした。
  10. parallelをビルドするために、WORKDIR指定した。
  11. phpsizeを実行することで、PHPを再ビルドすることなしに、拡張モジュールをインストールできるということである。
  12. php.ini に extension=parallel.so を記入するのであるが、php8.3のシステムでは、/etc/php/8.3/mods-available/ に parallel.ini を作成し、その内容を extension=parallel.so とする。
  13. そして、シンボリックリンクを /etc/php/8.3/cli/conf.d/ と /etc/php/8.3/apache/conf.d/ に作成するという方法をとっている。もっとも、mods-available/ に parallel.ini があれば、phpenmod parallel というコマンドでシンボリックリンクを作成してくれるんだろう。
  14. ここで apache2 をスタートさせているのだが、残念ながら、スタートできていないようである。このコンテナを動作させたのち、このコンテナに接続して、service apache2 status とすると、not running となっていたのである。
  15. ‘ll’ (エル・エル) というエイリアスが便利なので、それが使えるように .bashrc に書き込んでいる。
  16. こうしておくと、作成されたコンテナに接続すると、このフォルダにいることになる。

この Dockerfile は次のコマンドでコンテナにできる。

$ docker build --no-cache -t seiichin/my-php:8.3-zts .

このコンテナを動作させる。

$ docker run -itd --rm --name my-ubuntu seiichin/my-php:8.3-zts

このコンテナに接続する。

$ docker exec -it my-ubuntu /bin/bash

このコンテナを DockerHub にプッシュするには、次のコマンドを使う。

$ docker push seiichin/my-php:8.3-zts

拡張モジュールの読込み指定による Warning

この時点で dockerコンテナに接続して、phpのモジュールを確認する。

$ docker exec -it my-ubuntu /bin/bash
root@dege345wdw34:/var/www/html# php -m

すると、

PHP Warning: PHP Startup: Unable to load dynamic library 'pdo.so' (tried: /usr/lib/php/extensions/no-debug-zts-20230831/pdo.so (/usr/lib/php/extensions/no-debug-zts-20230831/pdo.so: cannot open shared object file: No such file or directory), /usr/lib/php/extensions/no-debug-zts-20230831/pdo.so.so (/usr/lib/php/extensions/no-debug-zts-20230831/pdo.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0

という Warning が20以上出る。

その後に、インストールされたモジュールの一覧が表示される。

[PHP Modules]
Core
...
PDO
...

モジュールは /usr/lib/php/20230831 にインストールされているのだが、
/etc/php/8.3/mods-available/ の中に、たとえば pdo.ini が存在しており、
そのファイルの中に “extension=pdo.so” と記述されているので、それと
衝突しているのである。
mods-available に記述すると、/usr/lib/php/extensions/no-debug-zts-20230831/
の中に pdo.so を探しにいく。

これを無効化するために、以下のコマンドを実行する。

# phpdismod pdo

以下、Warning の表示されているモジュールの読込みは、同じ方法で無効化する必要がある。

configureオプションの指定のときに、いい方法があるのかもしれない。
あるいは、configureオプションでモジュールの指定をせずに、PHPのインストール後に、
モジュールの組込をするべきなのかもしれない。

PHPのインストール後にモジュールの組込をする方法は以下である。

(pdoモジュールの組込の場合)
# cd /usr/local/src/php-8.3.13/ext/pdo
# phpize
# configure
# make
# make install

docker-compose を使う

docker-compose.yml
version: '3'

services:
  web:
    image: seiichin/my-php:8.3-zts
    volumes:
      - ./html:/var/www/html
    container_name: my-ubuntu
    restart: always
    ports:
      - 8002:80
    environment:
      TZ: Asia/Tokyo
    stdin_open: true
    tty: true

これで、以下により、コンテナを動作させることができる。

$ docker-compose up -d
$ docker-compose ps
  Name       Command    State                  Ports                
--------------------------------------------------------------------
my-ubuntu   /bin/bash   Up      0.0.0.0:8002->80/tcp,:::8002->80/tcp

今回は、覚書として、ここまでとしておく。

カテゴリー: Docker, memo, php

タグ: parallel, php8.3, ThreadSafety, zts, マルチスレッド, モジュール

カウント: 181