61SQLSTATE[HY000] [2002] Connection refused in Docker Container PHP/Apache - php

I have recently switched from XAMPP to Docker for PHP Development and have managed to get my project running. The project was running fine on XAMPP, but for whatever reason the database kept on getting corrupt, hence the switch to Docker. This question has probably been asked before, but i have not been able to find an answer for it so far.
I have a login page, from where i submit the data to a php script, which makes a connection with the database and in that part, it runs into an exception:
61SQLSTATE[HY000] [2002] Connection refused61SQLSTATE[HY000] [2002] Connection refused
Warning: Cannot modify header information - headers already sent by (output started at /var/www/inc/cDBConnection.inc.php:61)
I have a docker-compose.yml file:
version: "3.2"
services:
php:
build: './php/'
networks:
- backend
volumes:
- ./project/:/var/www/html/
- ./inc/:/var/www/inc/
apache:
build: './apache/'
depends_on:
- php
- mysql
networks:
- frontend
- backend
ports:
- "8080:80"
volumes:
- ./project/:/var/www/html/
mysql:
image: mysql:5.6.40
ports:
- "3306:3306"
volumes:
- ./db:/var/lib/mysql
networks:
- backend
environment:
- MYSQL_ROOT_PASSWORD=password
networks:
frontend:
backend:
A Dockerfile in the apache folder:
FROM httpd:2.4.33-alpine
RUN apk update; \
apk upgrade;
# Copy apache vhost file to proxy php requests to php-fpm container
COPY apache.conf /usr/local/apache2/conf/apache.conf
RUN echo "Include /usr/local/apache2/conf/apache.conf" \
>> /usr/local/apache2/conf/httpd.conf
A Dockerfile in the php folder:
FROM php:7.2.7-fpm-alpine3.7
RUN apk update; \
apk upgrade;
RUN docker-php-ext-install pdo pdo_mysql mysqli
the DBConnection.php:
$this->_config = $databaseConfig;
$dsn = "" .
$this->_config['driver'] .
":host=" . $this->_config['host'] .
";dbname=" . $this->_config['dbname'];
try {
$this->dbc = new PDO( $dsn, $this->_config[ 'username' ], $this->_config[ 'password' ] );
} catch( PDOException $e ) {
echo __LINE__.$e->getMessage(); // here i run into this exception
}
I assume i'm missing some extension in the dockerfile, but if i log in through a mysql query browser, i am able to log in as root user. For the project i have another user, which i created with:
CREATE USER 'sec_user'#'localhost' IDENTIFIED BY 'password';
GRANT SELECT, INSERT, UPDATE ON `project`.* TO 'sec_user'#'localhost';
when i tried to log in with this user, i got an error "access denied", so i followed checked with:
SELECT user, host FROM mysql.user;
UPDATE mysql.user SET host='%' WHERE user='sec_user';
FLUSH PRIVILEGES
and the login worked with the query browser but on the frontend I'm unable to get in. Does anyone know what the problem here is?

I found the solution to this issue. The credentials are passed on through the environment variables and connecting to localhost or 127.0.0.1 will not work.
the credentials should be in the dockerfile:
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=test_db
- MYSQL_USER=sec_user
- MYSQL_PASSWORD=password
these are then accessed in the DBConnection.php like this:
'host' => "mysql", //this is from the dockerfile, docker does the mapping for you
'port' => '3306',
'dbname' => $_ENV["MYSQL_DATABASE"],
'username' => $_ENV["MYSQL_USER"],
'password' => $_ENV["MYSQL_PASSWORD"]
and succesfully connected!

Related

Can't connect to Postgres database using PHP PDO and Docker

I am running a Docker app that is built on three images: php:7.4-fpm, nginx:stable-alpine and postgres:alpine.
I was previously attempting to use the image php:7.4-fpm-alpine, but apparently it does not come with the Postgres PDO driver, which was causing a could not find driver error. This post explains more about that, and how to fix it. I followed the steps in that post, including creating a Dockerfile for my PHP FPM service (though I did not create a PHP CLI service), and that remedied my driver issues. However, I am now getting the following error when I try to connect to my PSQL database using PDO:
SQLSTATE[08006] [7] could not connect to server: Connection refused Is the server running on host "localhost" (127.0.0.1) and accepting TCP/IP connections on port 6432?
I know my database is running (on port 6432) because I can access it from my terminal and from Positco, and have created tables after my Docker app was created. I also tried to connect to a database on port 5432 (through which my Postgres desktop app is running), but that did not work either. I also tried to restart my Postgres container, but that did not help.
Here is my PHP:
class Database {
private $connection;
private static $options = array(
PDO::ATTR_EMULATE_PREPARES => FALSE,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
public function __construct() {
try {
$dsn = 'pgsql:host=localhost;port=6432;dbname=db_my_test_app';
$username = 'root';
$password = 'secret';
$connection = new PDO($dsn, $username, $password, self::$options);
$this->connection = $connection;
return $connection;
} catch (PDOException $e) {
exit($e->getMessage());
}
}
}
$database = new Database();
...and my docker-compose.yml file:
version: '3'
networks:
my_test_app:
services:
# nginx
nginx-service:
image: nginx:stable-alpine
container_name: nginx-container
ports:
- "8080:80"
volumes:
- ./app:/var/www/project
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php-fpm-service
- postgres-service
networks:
- my_test_app
# php
php-fpm-service:
build:
context: .
dockerfile: ./php-fpm/Dockerfile
container_name: php-fpm-container
ports:
- "9000:9000"
working_dir: /var/www/project
volumes:
- ./app:/var/www/project
networks:
- my_test_app
# postgres
postgres-service:
image: postgres:alpine
container_name: postgres-container
ports:
- "6432:5432"
volumes:
- ./postgres:/var/lib/postgresql/data
restart: always
environment:
POSTGRES_USER: root
POSTGRES_PASSWORD: secret
POSTGRES_DB: db_my_test_app
networks:
- my_test_app
...and the PHP service Dockerfile (from the aforementioned site):
FROM php:7.4-fpm
RUN apt-get update && apt-get install -y libpq-dev
RUN docker-php-ext-install pdo pdo_pgsql pgsql
RUN ln -s /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini
RUN sed -i -e 's/;extension=pgsql/extension=pgsql/' /usr/local/etc/php/php.ini
RUN sed -i -e 's/;extension=pdo_pgsql/extension=pdo_pgsql/' /usr/local/etc/php/php.ini
You are configuring docker under the default network mode: bridge. In order for the php-fpm-service to be able to access the postgres-service you need to make the following modifications:
In the docker-compose.yml file you'll need to add depends_on to php-fpm-service
# php
php-fpm-service:
build:
context: .
dockerfile: ./php-fpm/Dockerfile
container_name: php-fpm-container
ports:
- "9000:9000"
working_dir: /var/www/project
volumes:
- ./app:/var/www/project
networks:
- my_test_app
depends_on:
- postgres-service
In your PHP config, you need modify localhost to postgres-service and using port 5432:
$dsn = 'pgsql:host=postgres-service;port=5432;dbname=db_my_test_app';

Docker Container MySQL and PHP "LOAD DATA LOCAL INFILE" Permission Woes

I've got a docker container setup running on a machine, which has:
A PHP Web Server Container
A MySQL 8.0 Container
A PHPMyAdmin Container
Here's roughly what my docker-compose.yml file has:
version: '3.3'
services:
front:
build:
context: ./front
dockerfile: Dockerfile
container_name: front-end
depends_on:
- db
ports:
- 8000:80
# phpmyadmin
phpmyadmin:
container_name: phpmyadmin
depends_on:
- db
image: phpmyadmin/phpmyadmin
restart: always
ports:
- "8080:80"
environment:
PMA_HOST: db
MYSQL_ROOT_PASSWORD: derp
db:
container_name: mysql8
image: mysql:8.0
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: dev_db
MYSQL_USER: user
MYSQL_PASSWORD: pass
ports:
- 6033:3306
And, for that Front part, here's the Dockerfile
FROM php:7.3.3-apache
RUN apt-get update && apt-get upgrade -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev
RUN docker-php-ext-install mysqli
RUN docker-php-ext-install pdo pdo_mysql
RUN docker-php-ext-configure gd --with-freetype-dir=/usr --with-jpeg-dir=/usr --with-png-dir=/usr
RUN docker-php-ext-install gd
RUN a2enmod rewrite
EXPOSE 80
It's nothing too fancy, right? Probably.
Anyway, I'm working on a feature that allows the upload of a .csv file, which will then get loaded into a MySQL table. I'm running into some interesting errors when I attempt to do this, and after extensive digging and research, I'm not finding a solid solution.
Basically, when I try to execute this query:
try {
$sql = "LOAD DATA LOCAL INFILE '" . $tmpName . "'
INTO TABLE psy_products_temp_sales
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '\"'
LINES TERMINATED BY '\r\n'
(#col1,#col2,#col3,#col4,#col5,#col6)
SET
product_temp_name = #col1,
product_temp_sku = #col2,
product_temp_posted_date = #col3,
product_temp_sales_period = #col4,
product_temp_qty_sold = #col5,
product_temp_total_earned = #col6;";
$sql = $pdo->prepare($sql);
$sql->execute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY);
} catch (Exception $e) {
$output .= "Error: " . $e;
}
My PDO Object is set up like this:
$dsn = "mysql:host=" . $host . ";dbname=" . $db . ";charset=" . $charset;
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::MYSQL_ATTR_LOCAL_INFILE => true,
PDO::ATTR_EMULATE_PREPARES => false
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
$log->error(
"Could not establish database connection",
["message" => $e->getMessage()]);
throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
Notice the PDO::MYSQL_ATTR_LOCAL_INFILE => true flag is set, and in my php.ini, mysqli.allow_local_infile is set to ON.
So when I attempt to run this, I don't get an error, but MySQL is not reading the uploaded .csv file and loading it into the table. I'm able to actually READ that temporary .csv file directly using fopen(), but MySQL refuses to read it. And these .csv files have tens of thousands of rows, so I'm not looping through each row and running a query. No way.
When I attempt to run this in PHPMyAdmin, I get this error:
LOAD DATA LOCAL INFILE is forbidden, check mysqli.allow_local_infile
Then, when I try running that query in the MYSQL container itself in the CLI, I get this error:
ERROR 2068 (HY000): LOAD DATA LOCAL INFILE file request rejected due to restrictions on access.
The only thing that makes sense here is that the mysql8 container is being denied access to the front container's /tmp directory?
If this is the case, how do I set this up to where permissions are granted? I'm not the most saavy with CLI or docker container cross communication, but there's got to be a way for this to work.
Sorry this got long-winded. Thanks in advance!

How to configure and run old php 5.4 web application in docker with mysql?

I have an old application based on php 5.4 and mysql. I had developed that in 2015. I want to run that application using docker as changing php version for individual application is not a feasible solution.
What I did is as follows:
Dockerfile
FROM php:5.4-apache
COPY 000-default.conf /etc/apache2/sites-available/000-default.conf
RUN a2enmod rewrite
COPY . /var/www/html/
RUN chown -R www-data:www-data /var/www/html
RUN docker-php-ext-install mysql
CMD ["/usr/sbin/apachectl", "-D", "FOREGROUND"]
docker-compose.yml
version: "3.7"
services:
webapp:
build:
context: ./
dockerfile: Dockerfile
ports:
- "8000:80"
volumes:
- .:/var/www/html
# first load the 'db' service
depends_on:
- db
links:
- db
db:
image: mysql:5.7
restart: always
ports:
- "13306:3306"
environment:
MYSQL_USER: root
MYSQL_PASSWORD: admin
MYSQL_ROOT_PASSWORD: admin
MYSQL_DATABASE: pizzabite
volumes:
- ./mysql:/var/lib/mysql
The problem here is I was accessing mysql using old mysql methods i.e mysql_connect() etc.
database.php
<?php
// Connecting to the database server
$servername = "localhost:13306";
$username = "root";
$password = "admin";
$port = "13306";
$dbname = "pizzabite";
$connect = mysql_connect($servername, $username, $password) or die("<br/>Check your server connection...");
// $connect = mysqli_connect($servername, $username, $password, $dbname,$port); // I do not want to use mysqli_* function
$selectedDB = mysql_select_db($dbname) or die(mysqli_error());
//include('date.php');
?>
This file is included everywhere using include() but when run using docker this file gives error:
Warning: mysql_connect(): No such file or directory in /var/www/html/database.php on line 10
Check your server connection...
When using 0.0.0.0:13306 it gives me this error:
Warning: mysql_connect(): Connection refused in /var/www/html/database.php on line 10
Check your server connection...
docker-compose ps command output:
Name Command State Ports
---------------------------------------------------------------------------------------------------
pizza_corner_db_1 docker-entrypoint.sh mysqld Up 0.0.0.0:13306->3306/tcp, 33060/tcp
pizza_corner_webapp_1 /usr/sbin/apachectl -D FOR ... Up 0.0.0.0:8000->80/tcp
You are trying to connect to localhost:13306, because your PC port 13306 is forwarded to the mysql container.
However, that code is executed from the php-apache container, so 'localhost' is the container, not your pc. There is no port 13306 available there.
You should connect to db:13306 because in your docker-compose the database container is called db.
Also, be sure to enable mysql in your php container:
RUN docker-php-ext-install mysql && docker-php-ext-enable mysql

Can't connect to between mysql container and php in docker

Trying to connect to mysql 8 (mysql:latest) from a php:latest image (without apache or nginx) and I'm getting this annoying error:
Fatal error: Uncaught PDOException: SQLSTATE[HY000] [2002] Connection refused in /src/conn.php:5
Stack trace:
#0 /src/conn.php(5): PDO->__construct('mysql:host=data...', 'root', '12345678')
#1 {main}
thrown in /src/conn.php on line 5
I've looked for +20 solutions here on stackoverflow but none of them was able fix my problem. I can connect without a problem using mysql workbench or DataGrid using the following credentials:
server: localhost user: root pass: 12345678
But any configuration I use on the php image I can't make them connect with each other.
My docker-compose file:
version: '3'
services:
composer:
container_name: composer
networks:
- backend
image: composer
volumes:
- .:/app
command: install
database:
container_name: mysql
networks:
- backend
image: mysql:latest
volumes:
- ./database/mysqldata:/var/lib/mysql
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_ROOT_PASSWORD: 12345678
MYSQL_DATABASE: testdb
ports:
- "3306:3306"
php:
build:
context: .
container_name: php
networks:
- backend
image: php:apache
links:
- database
env_file:
- .env
volumes:
- .:/
command:
php /src/conn.php
depends_on:
- composer
- database
networks:
backend:
My conn.php:
<?php
$db = new PDO('mysql:host=database;dbname=testdb', 'root', '12345678');
What I did until now to try to fix the problem:
Change conn.php host to 127.0.0.1
Change conn.php host to localhost
Tried to use mysqli (got also connection refused)
Tried another php images (with apache, nginx etc)
Tried to use mysql as a host
PS: I'm using docker for mac
After 5 hours of research I really don't know what else to do and as I'm not a docker expert, would appreciate any help to point me the direction of the fix.
Thank you!
In your case, you can't connect to mysql via localhost or 127.0.0.1. If you connect like this. It call to localhost inside php container. But there is no mysql install in your php container.
You must connetc via container name. Or docker inspect you mysql container and get the container IP. For example with your docker-compose
database:
container_name: mysql
Now your mysql database host is mysql - container name instead localhost
Was able to find the solution. Turns out I need to wait for mysql service to be available before I start the php script. So I used the wait-for-it solution and did this on docker-compose:
command: >
bash -c "chmod +x /docker/./wait-for-it.sh
&& /docker/./wait-for-it.sh database:3306 -- echo 'database is up'
&& php phpscript.php"
Thank you for the help

Docker MYSQL '[2002] Connection refused'

I was trying out Docker for the first time. Got a LEMP stack up and running, but I can't connect to the MYSQL Database. Not on my Symfony application, not on PHPMyAdmin. The applications are returning the following error code:
An exception occured in driver: SQLSTATE[HY000] [2002] Connection refused
This is my docker-compose.yml:
nginx:
image: tutum/nginx
ports:
- "80:80"
links:
- phpfpm
volumes:
- ./nginx/default:/etc/nginx/sites-available/default
- ./nginx/default:/etc/nginx/sites-enabled/default
- ./logs/nginx-error.log:/var/log/nginx/error.log
- ./logs/nginx-access.log:/var/log/nginx/access.log
phpfpm:
build: phpfpm/
ports:
- "9000:9000"
volumes:
- ./public:/usr/share/nginx/html
mysql:
image: mariadb
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: admin
phpmyadmin:
image: phpmyadmin/phpmyadmin
restart: always
links:
- mysql
ports:
- 8183:80
environment:
MYSQL_USERNAME: admin
MYSQL_ROOT_PASSWORD: admin
PMA_ARBITRARY: 1
Dockerfile PHPFPM:
FROM php:fpm
RUN docker-php-ext-enable opcache
RUN apt-get update \
&& apt-get install -y --no-install-recommends libpq-dev \
&& docker-php-ext-install mysqli pdo_pgsql pdo_mysql
GitHub URL: https://github.com/MolengraafFrank/DockerSymfony
Could someone help me out? Thank you for your time.
The '[2002] Connection refused' means you can reach the database server, but you don't have right access for the user (in your case admin). By default mariadb have a root user with the password given by MYSQL_ROOT_PASSWORD and this user can connect from any server (%).
If you want use an over login to your databases, you have to create it in the databases server with the right granting on databases from chosen locations.
The problem here is that you have named your database server as 'mysql' (service name in the docker-compose file). But by default phpmyadmin tries to connect to a database server named 'db'. Adding PMA_HOST: mysql under the environment section of the phpmyadmin service will resolve this problem.
I think that MYSQL_USERNAME and PMA_ARBITRARY are useless if you work with default configuration (connection with root to your databases server)
I had this challenge because I am running 3 different containers with different IP Addresses
db - 172.18.0.3 - container for MYSQL
app - 172.18.0.2 - container for Laravel app
so I fixed it by editing my Laravel .env file
DB_CONNECTION=mysql
DB_HOST=172.18.0.3
DB_PORT=3306
DB_DATABASE=database_name
DB_USERNAME=username
...
To get your containers Ip addresses. From your docker host
docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
UPDATED:
For latest docker versions and based on the services name, "mysql", in your docker-compose.yml
mysql:
image: mariadb
ports:
- 3306:3306
You can try this:
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=database_name
DB_USERNAME=username
DB_HOST is the name of MySQL service name defined in docker-compose.yml
I've managed to connect to the mysql instance using mysql command line tool, this is the command I used - mysql -u root -p -h 127.0.0.1, and the entering the admin password. Is that a sufficient solution for you?
In my case I was running mysql in a docker container whose port was mapped to the host mac (3306:3306). I tried connecting to this database from a phpmyadmin docker container using 127.0.0.1 . But it won't work because the localhost on the phpmyadmin docker container does not have the required mysql running.
To connect to the host from docker network
docker.for.mac.host.internal
Docker Networking Docker Compose Networking
For my instance, the issue was with port mapping somehow.
In my case it was 3307:3306, as soon as I changed it to 3307 on the right side as well, I could connect to the DB instance.
Adding DB_READ_HOST=db solved this problem for me
If you want to know why your connexion failed, you can use in your terminal php artisan tinker and then
like
DB::connection()->getPdo();
Unfortunately this will only give you a part of the error.
Quit tinker and then use this command php artisan db will give you more information like database type, host, port, ad user about the issue.
Like this one
ERROR 2003 (HY000): Can't connect to MySQL server on '127.0.0.1:3306' (61)
Symfony\Component\Process\Exception\ProcessFailedException
The command "'mysql' '--host=127.0.0.1' '--port=3306' '--user=root' '--default-character-set=utf8mb4' 'laravel'" failed.
Exit Code: 1(General error)
Working directory: /Users/Dev/Documents/www/laravel_docker/src/addressAPI
Output:
================
Error Output:
================
at vendor/symfony/process/Process.php:270
266▕ */
267▕ public function mustRun(callable $callback = null, array $env = []): self
268▕ {
269▕ if (0 !== $this->run($callback, $env)) {
➜ 270▕ throw new ProcessFailedException($this);
271▕ }
272▕
273▕ return $this;
274▕ }
+14 vendor frames
15 artisan:37
Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
This will not give you the answer on what is wrong, but at least you can understand why your config is wrong.
you need to link the phpfpm container to mysql.

Categories