![Abrufen eines SQLSTATE[HY000] [2002] Verbindung im PHP Apache Docker-Container unter Verwendung von MariaDB abgelehnt, wenn Verbindung über die CMD von Dockerfile hergestellt wird (PHP CLI funktioniert)](https://rvso.com/image/781990/Abrufen%20eines%20SQLSTATE%5BHY000%5D%20%5B2002%5D%20Verbindung%20im%20PHP%20Apache%20Docker-Container%20unter%20Verwendung%20von%20MariaDB%20abgelehnt%2C%20wenn%20Verbindung%20%C3%BCber%20die%20CMD%20von%20Dockerfile%20hergestellt%20wird%20(PHP%20CLI%20funktioniert).png)
Ich versuche, einen Docker-Container auszuführen, basierend auf:
- PHP 8.1
- Apache 2.4
- MariaDB (neuestes offizielles Docker-Image)
Es startet alles ohne Probleme, aber ich kann keine Verbindung über PDO mit der Datenbank des Docker-Containers herstellen.
Docker-Datei:
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:
Den meisten Beiträgen und Antworten aus verschiedenen Foren zufolge habe ich versucht, sowohl localhost
als auch 127.0.0.1
als Wert der Umgebungsvariable zu verwenden MARIADB_HOST
(und außerdem interessiert es mich, warum das funktionieren soll?). Der folgende PHP-Code (Inhalt von src/init.php
) löst das Problem jedenfalls nicht:
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
]
);
Das Ergebnis ist immer:
SQLSTATE[HY000] [2002] Connection refused
.
AKTUALISIEREN
Ich bin noch einen Schritt weiter gegangen, indem ich diese Zeile hier ersetzt habe:
MARIADB_HOST: "127.0.0.1"
mit dem Namen meines Datenbankdienstes; nämlich:
MARIADB_HOST: db
Ich habe das herausgefunden, weil ich gleichzeitig herausgefunden habe, dass ich mich nur dann beim Admin-Dashboard anmelden kann, wenn ich es db
als Host verwende. Das war also eher eine Vermutung und ich würde immer noch gerne verstehen, warum das jetzt funktioniert..?
Dies funktioniert jedoch noch nicht vollständig. Es funktioniert nur, wenn ich die CMD
Zeile im Dockerfile weglasse, den Container baue, über in sein Terminal migriere docker exec -t -i php-apache /bin/bash
und den Befehl von dort aus ausführe . Wenn ich versuche, dies über das php src/init.php
zu tun (wie oben beschrieben), erhalte ich den erwähnten Fehler. Was übersehe ich noch? Ich würde diesen Init-Aufruf natürlich lieber mit dem laufenden Start des Docker-Containers automatisieren. Ich bohre weiter...CMD
Dockerfile
Antwort1
Jetzt habe ich es wirklich verstanden. Die Verbindung wurde abgelehnt, weil die Umgebungsvariablen nur verwendet wurden, wenn das Skript über die Shell ausgeführt wird, und über Docker CMD
- wie ich es verwendet habe - erfolgte keine Shell-Verarbeitung. In den Dokumenten habe ich auch gefundenDas:
Anders als die Shell-Form ruft die Exec-Form keine Befehlsshell auf. Das bedeutet, dass keine normale Shell-Verarbeitung stattfindet. Beispielsweise führt CMD [ "echo", "$HOME" ] keine Variablensubstitution für $HOME durch. Wenn Sie eine Shell-Verarbeitung wünschen, verwenden Sie entweder die Shell-Form oder führen Sie eine Shell direkt aus, beispielsweise: CMD [ "sh", "-c", "echo $HOME" ]. Wenn Sie die Exec-Form verwenden und eine Shell direkt ausführen, wie im Fall der Shell-Form, führt die Shell die Umgebungsvariablenerweiterung durch, nicht Docker.
Bei Verwendung in den Shell- oder Exec-Formaten legt der CMD-Befehl den Befehl fest, der beim Ausführen des Images ausgeführt werden soll.
Wenn Sie die Shell-Form der CMD verwenden, wird diese in /bin/sh -c ausgeführt.
Verwendung:
CMD [ "sh", "-c", "php src/init.php" ]
anstatt:
CMD [ "php", "src/init.php" ]
Hat seinen Zweck erfüllt!