コンテナとカーネルの関係
1. コンテナはカーネルを持たない
コンテナイメージに入っているのは、カーネル以外のすべて(ユーザー空間)です。カーネルは、コンテナを動かすホスト側のものを使います。
| 層 | 例 | どこから来るか |
|---|---|---|
| ベースの OS | bash、coreutils、glibc、apt、tzdata | debian:bookworm など |
| PHP 本体 | php、php-fpm、docker-php-ext-* スクリプト |
php:8.x の公式イメージ |
| 追加パッケージ | default-mysql-client、libzip-dev、libicu-dev |
Dockerfile の apt-get install |
| ビルドした拡張機能 | pdo_mysql.so、intl.so |
docker-php-ext-install |
| カーネル | ネットワーク、メモリ管理、プロセス管理 | ホスト側(イメージには含まれません) |
そのため、カーネルの脆弱性はイメージを更新しても直りません。ホスト側のカーネルを更新する必要があります。
2. 実行環境ごとのカーネル
| 実行環境 | 使われるカーネル | 更新するのは |
|---|---|---|
| AWS Fargate | AWS が用意した Linux カーネル | AWS(利用者は新しいタスクに入れ替えるだけ) |
| ECS on EC2 / Ubuntu サーバー | そのホストの Linux カーネル | 利用者(カーネルを更新して再起動) |
| Mac の Docker Desktop | Docker Desktop が動かす Linux 仮想マシンのカーネル(例: 6.10.14-linuxkit) |
Docker Desktop をアップデート |
Mac のカーネル(Darwin)は Linux ではないので、Linux コンテナを直接動かせません。
Docker Desktop が裏で軽量な Linux 仮想マシンを起動し、その中でコンテナを動かしています。
Mac(Darwin カーネル)
└─ Docker Desktop の Linux 仮想マシン(linuxkit カーネル、arm64)
└─ コンテナ(ユーザー空間)
次のコマンドで確認できます。
uname -srm # Mac のカーネル
docker info --format '' # コンテナが使うカーネル
3. Fargate は Debian でも Alpine でも動く
ベースのディストリビューションは関係ありません。
動くかどうかを決めるのは次の 2 点です。
- Linux 用のイメージであること
- CPU アーキテクチャがタスク定義と合っていること
アーキテクチャに注意
Apple Silicon の Mac で普通に docker build すると、arm64 用のイメージになります。
タスク定義が既定の x86_64 のままだと、exec format error で起動に失敗します。
| 動かしたい環境 | 対応 |
|---|---|
| x86_64 | docker build --platform linux/amd64 ... でビルドする |
| arm64(Graviton) | タスク定義に RuntimePlatform: { CpuArchitecture: ARM64, OperatingSystemFamily: LINUX } を指定する |
Mac でも --platform linux/amd64 を付ければ amd64 用のイメージを動かせます。
ただし命令を変換しながら実行するので遅く、まれに挙動が違うことがあります。最終確認は実環境で行うのが確実です。
4. Debian 版と Alpine 版の違い
| 観点 | Debian(php:8.5) |
Alpine(php:8.5-alpine) |
|---|---|---|
| イメージサイズ | 大きい | 小さい |
| Fargate での起動 | イメージ取得に時間がかかる | 速くなりやすい |
| C ライブラリ | glibc | musl |
| 互換性 | 高い | musl が原因の差が出ることがある(iconv の //TRANSLIT、一部の拡張機能や外部バイナリ、DNS の細かい挙動など) |
| パッケージ管理 | apt-get |
apk |
既存の構成が Debian 系なら、Debian 版を選ぶのが無難です。
5. docker-php-ext-* とパッケージ名
docker-php-ext-configure と docker-php-ext-install は、PHP 公式イメージが Debian 版にも Alpine 版にも入れている共通のスクリプトです。ただし、事前に入れるビルド用パッケージは名前が違います。
| 用途 | Debian(apt) | Alpine(apk) |
|---|---|---|
| zlib | zlib1g-dev |
zlib-dev |
| libzip | libzip-dev |
libzip-dev |
| ICU(intl 用) | libicu-dev |
icu-dev |
| MySQL クライアント | default-mysql-client |
mysql-client または mariadb-client |
-dev パッケージはビルド用のヘッダーです。実行時に必要なライブラリ本体(libzip4、libicu72 など)は依存関係として一緒に入ります。
6. ビルドした拡張機能は、そのイメージでしか動かない
intl.so などの拡張機能は、そのイメージの PHP、C ライブラリ、ICU のバージョンと CPU アーキテクチャに合わせてコンパイルされます。次の組み合わせでは動きません。
- Debian でビルドしたものを Alpine で使う(glibc と musl の違い)
- bookworm でビルドしたものを trixie で使う(ICU のバージョンの違い)
- PHP 8.3 用のものを PHP 8.5 で使う(PHP の内部 API の違い)
- amd64 でビルドしたものを arm64 で使う
Docker ではビルドと実行が同じイメージの中で行われるので、通常は問題になりません。PHP のバージョンを上げるときは、新しいイメージの中で拡張機能をビルドし直します。
7. -fpm イメージと待ち受けポート
php:8.x-fpm イメージは、何も指定しないと php-fpm を起動してポート 9000 で待ち受けます。ECS のタスク定義で Command を上書きすると、そのコマンドだけが実行されます。
| 起動方法 | 動くもの | 待ち受け |
|---|---|---|
Command の指定なし |
php-fpm | ポート 9000 |
Command: php bin/console ... |
そのコマンドだけ | なし |
ENTRYPOINT の docker-php-entrypoint は、指定されたコマンドをそのまま実行します。アプリ側の Dockerfile で ENTRYPOINT を変えている場合は、裏で別のプロセスが起動していないか確認が必要です。
コンテナ内で待ち受けているポートは、次のコマンドで確認できます。何も表示されなければ、待ち受けはありません。
for f in /proc/net/tcp /proc/net/tcp6; do
awk '$4=="0A"{split($2,a,":"); print a[2]}' "$f"
done | while read -r p; do echo "LISTEN port: $((0x$p))"; done