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

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';

Related

Trying to access a database in docker containers and php

So I have the following docker-compose file and Dockerfile for php which I am using. These files are in a folder called cca4 and my php files are in a subdirectory of this called src. I am trying to access my mysql database that I am creating however I cannot select anything from it or insert anything. No matter what I do the queries will not work. Any idea on what is wrong? When I go into phpmyadmin I can see that my database is there however it is just not updating or being selected from. I am using nginx as the web server and php-fpm to communicate. I am doing this all from a Linux VM on GCP (Google Cloud Platform) so could be an issue with that maybe too. My php just cannot seem to pick up that there are any tables in the db or rows even after inserting them into phpmyadmin
version: '3.3'
services:
db:
image: mysql:latest
volumes:
- database:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: MyDBRoot123
MYSQL_DATABASE: assignment_four_data
MYSQL_USER: php
MYSQL_PASSWORD: php
container_name: db
networks:
- mynet
myphp:
build:
context: .
dockerfile: Dockerfile
depends_on:
- db
expose:
- 9000
restart: always
volumes:
- $PWD/src:/var/www/html
container_name: myphp
networks:
- mynet
mynginx:
depends_on:
- myphp
image: nginx:latest
ports:
- "8080:80"
restart: always
volumes:
- $PWD/src:/var/www/html
- $PWD/src/nginx.ini:/etc/nginx/conf.d/default.conf
container_name: mynginx
networks:
- mynet
phpMyAdmin:
depends_on:
- db
image: phpmyadmin:latest
restart: always
environment:
PMA_HOST: mysql
ports:
- "8082:80"
container_name: phpMyAdmin
networks:
- mynet
volumes:
database: {}
networks:
mynet:
driver: bridge
Here is the dockerfile.
FROM php:7.4-fpm
RUN pecl install igbinary \
&& pecl install redis \
&& docker-php-ext-install mysqli \
&& docker-php-ext-enable redis \
&& echo "extension=redis.so" > /usr/local/etc/php/conf.d/redis.ini
my php code.
<?php
$servername = "db";
$username = "php";
$password = "php";
$databse = "assignment_four_data";
// Create connection
$conn = mysqli_connect($servername, $username, $password, $database);
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
$sql = 'SELECT * FROM Users';
$result = $mysqli_query($conn, $sql);
if (!$result) {
printf("false");
}
printf("Selected returned %d rows. \n", mysqli_num_rows($result));
?>
The error I keep receiving in my db.php file
Warning: mysqli_num_rows() expects parameter 1 to be mysqli_result, bool given in /var/www/html/db.php on line 18
Selected returned 0 rows
Is this a docker problem or a mysqli problem? My database is definitely there in phpmyadmin but I just can't get my db.php to communicate with it. Since the mysqli_query is returning false then my query obviously isn't able to work correctly with the mysql database. Even after creating tables and inserting values in phpmyadmin it still cannot detect anything.

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

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

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!

docker mysql connection refused while connecting from PHP script

Basically I want to run the LAMP stack in an Docker container.
All services are so far running but as soon I try to connect to an mysql from within an PHP script I get following error:
Warning: mysqli::__construct(): (HY000/2002): Connection refused
docker-compose.yml
version: '3.2'
services:
php:
build: ./php/
networks:
- backend
volumes:
- './public/:/var/www/html'
apache:
build: ./apache/
depends_on:
- php
- mysql
networks:
- frontend
- backend
ports:
- '8080:80'
volumes:
- './public/:/var/www/html'
mysql:
image: 'mysql:5.6.40'
ports:
- "3306:3306"
networks:
- backend
environment:
- MYSQL_DATABASES=test
- MYSQL_ROOT_PASSWORD=root
- MYSQL_HOST=127.0.0.1
- MYSQL_PORT=3306
- MYSQL_USER=user
- MYSQL_PASSWORD=password
- MYSQL_MY_DATABASE=test
networks:
frontend: null
backend: null
Dockerfile for PHP:
FROM php:7.2.7-fpm-alpine3.7
RUN apk update; \
apk upgrade;
RUN docker-php-ext-install mysqli
I had tested it with the following approach:
docker exec -ti <mysql_docker> bash
and used the same crendatial for entering the mysql mode:
mysql -uroot -h127.0.0.1 -P3306 -p
and there is not problem with it.
So what may cause the above connection refused?

How can I connect php-apache and MySQL using Docker?

I have a Wordpress site on live server and I want to create a LAMP stack locally with Docker to test things.
I pull the images of php:7.0-apache and mysql:5.7, the same versions on live.
I create a MySQL container:
docker run -d --name achi-mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
I create a php & apache container and link it with MySQL:
docker run -d --name achi-php-apache --link achi-mysql:mysql -p 8080:80 -v /home/achi/workspace/web/wordpress-template/:/var/www/html php:7.0-apache
I get the following error on localhost:8080:
Fatal error: Uncaught Error: Call to undefined function mysql_connect() in /var/www/html/wp-includes/wp-db.php:1564 [...]
Do I link these two containers the wrong way?
Your problem is not the connection between your containers. The problem is your PHP / Apache container which doesn't support mysqli (or PDO MySQL). WordPress can't find another function to connect with a MySQL database or your MySQL container. Instead WordPress is using a deprecated and removed (since PHP 7.0) mysql_ function per default. You need to install at least mysqli on your PHP container (explained below).
I also recommend to use a docker-compose file to install and run all containers with one command.
To create the containers you want, you can use the following docker-compose.yml file:
version: "3"
services:
achi-php-apache:
build:
context: ./
container_name: achi-php-apache
ports:
- "8080:80"
volumes:
- /home/achi/workspace/web/wordpress-template:/var/www/html:rw
depends_on:
- achi-mysql
networks:
- wp-net
achi-mysql:
image: mysql:5.7
container_name: achi-mysql
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: wp-dbname
volumes:
- wp-mysql-data:/var/lib/mysql
networks:
- wp-net
networks:
wp-net:
driver: bridge
volumes:
wp-mysql-data:
You need the following Dockerfile on the same directory as the docker-compose.yml file:
FROM php:7.0-apache
RUN docker-php-ext-install -j$(nproc) mysqli
This Dockerfile installs the missing mysqli extension so WordPress can use it.
You can also use PDO MySQL instead of mysqli. In this case you can use the following Dockerfile:
FROM php:7.0-apache
RUN docker-php-ext-install -j$(nproc) pdo
RUN docker-php-ext-install -j$(nproc) pdo_mysql
Now you can execute the command docker-compose up inside the folder where the docker-compose.yml file is located. After creating the container and running you should be able to access the WordPress site (<ip-or-hostname>:8080).
On the wp-config.php file you need to use the following constants:
define('DB_NAME', 'wp-dbname');
define('DB_USER', 'root');
define('DB_PASSWORD', '123456');
define('DB_HOST', 'achi-mysql');
You can also use the official WordPress image to install WordPress. In this case you can use the following docker-compose.yml file:
version: "3"
services:
achi-php-apache:
image: wordpress:4.9.4-php7.0-apache
container_name: achi-php-apache
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: achi-mysql
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: 123456
WORDPRESS_DB_NAME: wp-dbname
volumes:
- /home/achi/workspace/web/wordpress-template:/var/www/html:rw
depends_on:
- achi-mysql
networks:
- wp-net
achi-mysql:
image: mysql:5.7
container_name: achi-mysql
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: wp-dbname
volumes:
- wp-mysql-data:/var/lib/mysql
networks:
- wp-net
networks:
wp-net:
driver: bridge
volumes:
wp-mysql-data:
The simplest way is to use docker-compose to link all your docker instances together rather than linking through the docker command. Here is a sample docker-compose.yml file that should do what you want:
version: '2'
services:
achi-php-apache:
image: php:7.0-apache
ports:
- "8080:80"
volumes:
- /home/achi/workspace/web/wordpress-template/:/var/www/html
links:
- achi-mysql
achi-mysql:
image: mysql:5.7
volumes:
- /var/lib/mysql
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_USER: someuser
MYSQL_PASSWORD: somepassword
MYSQL_DATABASE: somedefaultdatabase

Categories