LoginSignup
3
1

More than 1 year has passed since last update.

PHP8のコンテナでdocker stopしてるのにSIGTERMが送られていない事象について

Posted at

概要

PHP8のDockerコンテナに対して
docker stop

docker-compose stop
をしてもSIGTERMが送られず
phpスクリプトに記載のシグナル制御がうまく動かなかった。

原因

利用したDocker ImageにてSTOPSIGNALによりデフォルトのSIGTERMから別のシグナルに変更されていたため。

詳細

Docker Image

docker-compose

docker-compose.yml
version: '2.0'
services:
  app:
    container_name: php8
    image: phpdockerio/php80-fpm
    volumes:
      - ./:/var/www/html/
    command: php /var/www/html/test.php

test.php

test.php
<?php
pcntl_async_signals(true);
pcntl_signal(SIGTERM, 'hoge');

while(true){
    echo("call\n");
    sleep(2);
}

function hoge($signo){
    echo("hoge call\n");
    echo("{$signo}\n");
    exit;
}

うまくいかない実行

docker-compose up
Starting php8 ... done
Attaching to php8
php8   | call
php8   | call
php8   | call
php8   | call
・・・

無限ループ中に別ターミナルからdockerを停止。

docker-compose stop
Stopping php8 ... done
$ docker-compose up
Starting php8 ... done
Attaching to php8
php8   | call
php8   | call
php8   | call
php8   | call
php8 exited with code 137

すぐに終了せずに10秒後にSIGKILLが送られて強制終了。
SIGTERMをキャッチしてくれない。

うまくいく実行

コンテナを起動しておく。
別ターミナルでそのコンテナに入る。

docker exec -it php8 bash
# プロセス一覧からtest.phpをシグナルを15でkillする例
ps aux | grep test.php | grep -v grep | awk '{print $2}' | xargs kill -15

これを送ると

$ docker-compose up
Starting php8 ... done
Attaching to php8
php8   | call
php8   | hoge call
php8   | 15
php8 exited with code 0

SIGTERM(signo=15)を受け取って即時に終了する。

試したこと

全てのシグナルをキャッチしてみる。

test.php
<?php
pcntl_async_signals(true);
for($i=1;$i<65;$i++){
    // このあたりは上書き不可のシグナル
    if($i===9)continue;
    if($i===19)continue;
    if($i===32)continue;
    if($i===33)continue;
    pcntl_signal($i, 'hoge');
}

while(true){
    echo("call\n");
    sleep(2);
}

function hoge($signo){
    echo("hoge call\n");
    echo("{$signo}\n");
    exit;
}

実行してみたところ

$ docker-compose up
Starting php8 ... done
Attaching to php8
php8   | call
php8   | hoge call
php8   | 3
php8 exited with code 0

signo=3を受け取って終了した。
signo=3はSIGQUIT
https://www.php.net/manual/ja/pcntl.constants.php

考察

なんでdocker stopでSIGQUITを送ってるんだ?
デフォルトだとSIGTERMって書いてあるんだけど…。
https://matsuand.github.io/docs.docker.jp.onthefly/engine/reference/commandline/stop/

コンテナー内部の主となるプロセスは、シグナルSIGTERMを受信します。 そして一定時間後にSIGKILLを受信します。

ここで気になる記載が

初回に受信するシグナルは、コンテナーの Dockerfile 内においてSTOPSIGNAL命令を使って変更できます。

ほう、ってことはSTOPSIGNALで上書きしてる可能性あるか?

使ってるimageのDockerfileを確認しに行く。

https://hub.docker.com/r/phpdockerio/php80-fpm/tags
https://hub.docker.com/layers/phpdockerio/php80-fpm/latest/images/sha256-5fc31be3e13612fa4a694f64937c267053cd187369f8ec28e335f4bc63abfe5a?context=explore

STOPSIGNAL SIGQUIT

シグナル上書きしてるぅ!
状況を理解した。

まとめ

適当に使わず、使ってるImageはよく確認しよう。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1