![Obtendo um SQLSTATE[HY000] [2002] Conexão recusada no contêiner PHP Apache Docker usando mariadb, se conectado via CMD do Dockerfile (PHP CLI funciona)](https://rvso.com/image/781990/Obtendo%20um%20SQLSTATE%5BHY000%5D%20%5B2002%5D%20Conex%C3%A3o%20recusada%20no%20cont%C3%AAiner%20PHP%20Apache%20Docker%20usando%20mariadb%2C%20se%20conectado%20via%20CMD%20do%20Dockerfile%20(PHP%20CLI%20funciona).png)
Estou tentando executar um contêiner Docker baseado em:
- PHP 8.1
- Apache 2.4
- MariaDB (imagem oficial mais recente do docker)
Tudo começa sem nenhum problema; mas não consigo me conectar ao banco de dados do Docker Container via PDO.
Arquivo 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:
De acordo com a maioria das postagens e respostas de diferentes fóruns, tentei usar tanto localhost
quanto 127.0.0.1
o valor da variável de ambiente MARIADB_HOST
(e além disso, estou interessado em saber por que isso deveria funcionar?). De qualquer forma, não resolve o problema, o seguinte código php (conteúdo de src/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
]
);
Sempre resulta em:
SQLSTATE[HY000] [2002] Connection refused
.
ATUALIZAR
Dei um passo adiante ao substituir esta linha aqui:
MARIADB_HOST: "127.0.0.1"
com o nome do meu serviço de banco de dados; ser:
MARIADB_HOST: db
Descobri isso porque descobri ao mesmo tempo que só posso fazer login no painel do administrador se usar db
como host. Portanto, isso foi um palpite, e eu ainda adoraria entender por que isso funciona agora..?
No entanto, isso ainda não funciona totalmente. Só funciona se eu omitir a CMD
linha no dockerfile, construir o contêiner, migrar para seu terminal via docker exec -t -i php-apache /bin/bash
e executar o comando php src/init.php
de lá. Se eu tentar fazer isso através CMD
do formulário Dockerfile
(conforme detalhado acima), recebo o erro mencionado. O que ainda estou faltando? É claro que eu preferiria automatizar essa chamada init com o início da execução do contêiner Docker. Indo mais longe...
Responder1
Entendi de verdade agora. A conexão foi recusada porque as variáveis de ambiente só foram utilizadas se o script for executado via shell, e via Docker CMD
- como eu usei - não ocorreu nenhum processamento de shell. Nos documentos, também encontreiesse:
Ao contrário do formulário shell, o formulário exec não invoca um shell de comando. Isso significa que o processamento normal do shell não acontece. Por exemplo, CMD [ "echo", "$HOME" ] não fará substituição de variáveis em $HOME. Se você deseja processamento de shell, use o formulário de shell ou execute um shell diretamente, por exemplo: CMD [ "sh", "-c", "echo $HOME" ]. Ao usar o formulário exec e executar um shell diretamente, como no caso do formulário shell, é o shell que está fazendo a expansão da variável de ambiente, não o docker.
Quando usada nos formatos shell ou exec, a instrução CMD define o comando a ser executado ao executar a imagem.
Se você usar o formato shell do CMD, ele será executado em /bin/sh -c
Usando:
CMD [ "sh", "-c", "php src/init.php" ]
em vez de:
CMD [ "php", "src/init.php" ]
Fiz o trabalho!