SQLSTATE[HY000] [2002] を取得すると、Dockerfile の CMD 経由で接続した場合、mariadb を使用した PHP Apache Docker コンテナで接続が拒否されます (PHP CLI は動作します)

SQLSTATE[HY000] [2002] を取得すると、Dockerfile の CMD 経由で接続した場合、mariadb を使用した PHP Apache Docker コンテナで接続が拒否されます (PHP CLI は動作します)

以下に基づいて Docker コンテナを実行しようとしています:

  • PHP8.1 について
  • アパッチ2.4
  • MariaDB (最新の公式 Docker イメージ)

すべて問題なく起動しますが、PDO 経由で Docker コンテナの DB に接続できません。

Dockerファイル:

FROM php:8.1-apache

WORKDIR /var/www/html/

RUN pecl install xdebug \
    && apt update \
    && apt install libzip-dev -y \
    && docker-php-ext-enable xdebug \
    && a2enmod rewrite \
    && docker-php-ext-install zip \
    && rm -rf /var/lib/apt/lists/* \
    && docker-php-ext-install pdo pdo_mysql

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
COPY composer.json .

RUN groupadd -r user && useradd -r -g user user
USER user
RUN composer install --no-dev

COPY . .

EXPOSE 80

CMD ["php","src/init.php"]

docker-compose.yml:

services:

  php:
    build: ./php
    depends_on:
      - db
      - adminer
    container_name: php-apache
    ports:
      - 80:80
    volumes:
      # setup xdebug to be able to use PHP step debugger, if needed
      - ./php/conf.d/xdebug.ini:/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
      - ./php/conf.d/error_reporting.ini:/usr/local/etc/php/conf.d/error_reporting.ini
      # apache config (server name)
      - ./apache/apache2.conf:/etc/apache2/apache2.conf
      # apache config (rewrite rule to reroute all requests to unknown resources through to REST controller)
      - ./apache/000-default.conf:/etc/apache2/sites-enabled/000-default.conf
      # Source code
      - ./php/src:/var/www/html/src
      # unbind local composer components
      - /php/vendor
      - /php/composer.lock
      - /php/composer.phar
    environment:
      MARIADB_HOST: "127.0.0.1"
      MARIADB_USER: root
      MARIADB_PASSWORD: top_very_secret
      MARIADB_DB: apidb

  adminer:
    image: adminer
    depends_on:
      - db
    restart: always
    ports:
      - 8080:8080

  db:
    image: mariadb
    container_name: db
    volumes:
      - maria-db-storage:/var/lib/mysql
    environment:
      MARIADB_ROOT_PASSWORD: top_very_secret
      MARIADB_DATABASE: apidb
    ports:
      - 3306:3306

volumes:
  maria-db-storage:

さまざまなフォーラムからの投稿や回答の大部分によると、私は と を環境変数の値としてlocalhost使用しようとしました (また、なぜそれが機能するはずなのかを知りたいです)。とにかく、次の PHP コード ( の内容) では問題は解決されません。127.0.0.1MARIADB_HOSTsrc/init.php

new PDO(
    "mysql:host={$_ENV['MARIADB_HOST']};dbname={$_ENV['MARIADB_DB']}",
    $_ENV['MARIADB_USER'],
    $_ENV['MARIADB_PASSWORD'],
    [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
    ]
);

常に次の結果になります:

SQLSTATE[HY000] [2002] Connection refused

アップデート

私はさらに一歩進んで、この行を次のように置き換えました。

MARIADB_HOST: "127.0.0.1"

データベース サービスの名前は次のようになります。

MARIADB_HOST: db

私がこれを知ったのは、ホストとして使用する場合にのみ管理者ダッシュボードにログインできることが同時にわかったからですdb。したがって、これはむしろ推測であり、なぜこれが現在機能するのかをまだ理解したいと思っています。

ただし、これはまだ完全には機能しません。dockerfileCMDの行を省略し、コンテナーをビルドし、 を介してそのターミナルに移行しdocker exec -t -i php-apache /bin/bash、そこからコマンドを実行する場合にのみ機能します。から(上記のように)php src/init.php実行しようとすると、前述のエラーが発生します。まだ何が足りないのでしょうか? もちろん、この init 呼び出しを Docker コンテナーの実行開始で自動化したいです。さらに掘り下げます...CMDDockerfile

答え1

今では本当に理解できました。環境変数はスクリプトがシェル経由で実行される場合にのみ使用され、Docker経由では(私が使用したように)シェル処理は行われなかったため、接続CMDが拒否されました。ドキュメントから、私はまたこれ:

シェル形式とは異なり、exec 形式はコマンド シェルを呼び出しません。つまり、通常のシェル処理は行われません。たとえば、CMD [ "echo", "$HOME" ] は $HOME で変数置換を行いません。シェル処理が必要な場合は、シェル形式を使用するか、シェルを直接実行します (例: CMD [ "sh", "-c", "echo $HOME" ])。exec 形式を使用してシェルを直接実行する場合、シェル形式の場合と同様に、環境変数の展開を行うのはシェルであり、docker ではありません。

シェルまたは exec 形式で使用する場合、CMD 命令はイメージの実行時に実行されるコマンドを設定します。

CMDのシェル形式を使用する場合は、/bin/sh -cで実行されます。

使用方法:

CMD [ "sh", "-c", "php src/init.php" ]

の代わりに:

CMD [ "php", "src/init.php" ]

仕事完了!

関連情報