I am trying to run a site using multiple container configuration - one for apache, second for mysql and third for myadmin. Everything starts fine, setup runs smooth but when I try to run a PHP application I get mysqli::__construct(): (HY000/2002): Connection refused in system/libraries/drivers/Database/Mysqli.php [54] error.
It seems that there's something wrong with the connection settings but I checked the site through PHP MyAdmin running on separate container and copied the db host IP from there just to be sure. How can I/should I connect from PHP container to MySQL db?
Here's my docker-compose.yml file:
version: '3'
services:
web:
build:
context: ./etc/php
args:
- APP_HOST=${APP_HOST}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_PORT=${MYSQL_PORT}
- MYSQL_DATABASE=${MYSQL_DATABASE}
ports:
- ${APP_PORT}:80
- ${APP_PORT_SSL}:443
volumes:
- ./var/bin/:/tmp/bin/
- ./app/:/var/www/html/
- ./log/apache2/:/var/log/apache2/
- ./etc/php/conf/:/usr/local/etc/php/conf.d/
environment:
- VIRTUAL_HOST=${VIRTUAL_HOST}
db:
build:
context: ./etc/mysql
args:
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- DUMP_FILE=${DUMP_FILE}
volumes:
- ./etc/mysql/conf:/etc/mysql/conf/conf.d
- ./data:/var/lib/mysql
- ./log/:/var/log/
ports:
- "${MYSQL_PORT}:3306"
phpmyadmin:
image: phpmyadmin/phpmyadmin
environment:
MYSQL_ROOT_PASSWORD: root
ports:
- ${MYADMIN_PORT}:80
environment:
- VIRTUAL_HOST=phpmyadmin.localhost
And the .env with variables:
VIRTUAL_HOST=foo.local
APP_PORT=80
APP_PORT_SSL=443
MYADMIN_PORT=8081
APP_HOST=foo.local
ADMIN_APP_HOST=admin-foo.local
MYSQL_DATABASE=foo_local
MYSQL_USER=root
MYSQL_HOST=172.26.0.2
MYSQL_PASSWORD=root
MYSQL_ROOT_PASSWORD=root
MYSQL_PORT=3306
Oh, and here's the code I try to run:
$this->link = $socket ? new mysqli(null, $user, $pass, $database, $port, $socket) :
new mysqli($host, $user, $pass, $database, $port);
Output of echo $host.'<br>'.$user.'<br>'.$pass.'<br>'.$database.'<br>'.$port.'<br>'.$socket; is following:
172.26.0.2
root
root
hq_local
3306
check your container IP with a docker inspect [container name] but write IP in a file is not very good. Replace IP by name of your db container.
You can always use host.docker.internal as IP, therefore you can use something like this:
$db = new \PDO('mysql:host=host.docker.internal;port=3306;dbname=db', 'root', 'pass');
Check out the /etc/hosts configuration inside your web service container for container linkage.
docker exec -it <container_name> cat /etc/hosts
Docker network won't be assigning the same IP to db container that you have specified for the MYSQL_HOST all the time. So better ti use the conatiner name in order to connect from web container.
Also, based on the context that you have specified in docker-compose.yml, try this:
new mysqli('etc/mysql', $user, $pass, $database, $port);
all you need to do is to specify the value of the host in mysql the official environment variable is MYSQL_ROOT_HOST: localhost if you do not do that then the host becomes the name of the service which in your case it is db.
Put everything in .env file and call the environment variables from there. Don´t worry about changing code if you write it as:
$mylink = mysqli_connect(
env("DB_HOST"),
env("DB_USER"),
env("DB_PASS"),
env("DB_NAME"),
env("DB_PORT",3306)
)
Related
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
My question is how to configure connection to mysql container.
Here is my docker-compose.yml
version: '3'
services:
php:
build: ./php-fpm
volumes:
- ./iym:/var/www/iym
- ./php-fpm/php.ini:/usr/local/etc/php/php.ini
depends_on:
- mysql
web:
build: ./nginx
ports:
- "8888:80"
volumes:
- ./iym:/var/www/iym
- ./nginx/iym.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php
mysql:
image: mysql:5.6
restart: always
command: --default-authentication-plugin=mysql_native_password
volumes:
- ${DB_PATH_HOST}:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: "symf0ny"
ports:
- "3306:3306"
And here is my DATABASE_URL in .env file
DATABASE_URL=mysql://root:symf0ny#127.0.0.1:3306/iym
When i try to run php bin/console doctrine:database:create i get an error like "SQLSTATE[HY000] [2002] Connection refused". OS - ubuntu 18.04. What should i do to connect to DB? Many thanks!
I assume you are trying to connect from another container/service defined in docker-compose and you are using current version of docker-compose (2.4 or 3.7)
You need to change
DATABASE_URL=mysql://root:symf0ny#127.0.0.1:3306/iym
to
DATABASE_URL=mysql://root:symf0ny#mysql:3306/iym
The reason is that 127.0.0.1 is refering to the localhost of the machine on which php runs. In this case it's the php's container localhost. But the db doesn't run there. It runs in another docker container, which can be reached under the service name, mysql in this case.
In docker-compose networking docs is written:
By default Compose sets up a single network for your app. Each container for a service joins the default network and is both reachable by other containers on that network, and discoverable by them at a hostname identical to the container name.
but, the service is discoverable under the container name (which is automatically generated to projectName_serviceName_1 (project name begin by default folder name), but also under service name, link and service alias if defined. I would recommend using service name wherever possible.
More in docs: https://docs.docker.com/compose/networking/
In my case, the Docker variable overrides the parameter from .env file and I'm trying to connect to the wrong host. Found that via dd($this->constructPdoDsn($params)) in the Doctrine\DBAL\Driver\PDO\MySQL\Driver::connect, maybe it will be helpful
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
Ok, so here's the deal: I'm using Docker-Compose to create 3 services: one for the platform, one for db (mysql) and the third for PHPMyAdmin
I'm trying to use mysqli to connect to the database on port 5001.
What’s interesting is that I can connect to the database using SQL Workbench and PHPMyAdmin with the same parameters, but I get an error (seen below) when connecting using PHP MySQLi
Platform:
$db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_PORT);
The host is 127.0.0.1, the DB_USER is root with its respective password, I've provided a DB_Name and the port is 5001.
My Docker-Compose.yml looks like this:
version: '3.3'
services:
platform:
build: .
ports:
- "5000:80"
links:
- db:mysql
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
ports:
#- "5001:80"
- "5001:3306"
environment:
MYSQL_ROOT_PASSWORD: some_great_password_here
MYSQL_DATABASE: DB_NAME_HERE
MYSQL_USER: USERNAME
MYSQL_PASSWORD: PASSWORD
phpmyadmin:
image: phpmyadmin/phpmyadmin
links:
- db:mysql
ports:
- 8181:80
environment:
MYSQL_USERNAME: USERNAME
MYSQL_ROOT_PASSWORD: PASSWORD
volumes:
db_data:
For some reason, I keep getting the error:
mysqli::mysqli(): (HY000/2003): Can't connect to MySQL server on '127.0.0.1' (111) in ...
Any tips or a solution would be much appreciated!
I found a solution to my problem after churning through documentation and other Stackoverflow posts.
When attempting to connect to the database from inside a container, we need to use the container / service name as opposed to 'localhost' or 127.0.0.1. This is because when we call "localhost," it's looking for localhost inside each container. We need to connect to a MySQL database inside a different container, via a network bridge.
The way we do this is to simply alias the container name as the host, such that:
$db = new mysqli("db", DB_USER, DB_PASS, DB_NAME, DB_PORT);
Notice that the Hostname is the container name "db," as defined in the docker-compose.yml file. This works because of the docker network bridge that is created between containers. The port is the default MySQL port of 3306.
It's important to note however, if we want to use an "external" app like Sequel Pro or Workbench to connect to the database, we can use localhost or 127.0.0.1 to connect to the database since we are not dealing directly with containers. It should be noted however, that the default port of 3306 won't work in this situation. We need to map an external port with 3306. In my case, that would be 5001, as shown in my docker-compose.yml file.
You have mapped mysql port to 3306 as per
- "5001:3306"
You should try to connect at port 3306 instead of 5001. Make sure that your containers are using Bridge Networking for them to communicate with each other.
$db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME, 3306);
Instead of hardcoding the db_username and password, I want to define a env variable in docker. I am new to Docker, so some stuff I still need to learn more about.
Another question i want to ask is, if someone else want to run my container, like clone from github, they will have to set themselves the env variables to connect to db right? Create a .env and stuff like that..
config.php
<?php
define('DB_SERVER', getenv('DB_SERVER'));
define('DB_USERNAME', getenv('DB_USERNAME'));
define('DB_PASSWORD', getenv('DB_PASSWORD'));
define('DB_NAME', getenv('DB_NAME'));
$link = mysqli_connect(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME);
if ($link === false) {
die ("ERROR: Could not connect. " . mysqli_connect_error());
}
?>
.env
DB_SERVER=db
DB_USERNAME=dbuser
DB_PASSWORD=dbpassword
DB_NAME=company
docker-compose.yml
db:
build: ./backend
restart: always
ports:
- "3306:3306"
volumes:
- /var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=dbpassword
php:
build: ./frontend
ports:
- "80:80"
volumes:
- ./frontend:/var/www/html
environment:
- DB_SERVER=${DB_SERVER}
- DB_USERNAME=${DB_USERNAME}
- DB_PASSWORD=${DB_PASSWORD}
- DB_NAME=${DB_NAME}
env_file: ./.env
links:
- db
Dockerfile in ./frontend
FROM php:7.2-apache
RUN docker-php-ext-install mysqli
WORKDIR /var/www/html
COPY . /var/www/html/
Dockerfile in ./backend
FROM mysql:5.7
COPY ./demo.sql /docker-entrypoint-initdb.d
I don't know if the way it is right now, is getting the variables form the env file, when i run with the docker-compose up, and go to 192.168.99.100, my application is working, but i get
In the .yml file, i think i don't need the environment variables set, but i was testing if i could get that variables, directly put into the config.php, for someone who will run my container, only need to run "docker-compose up" and not set everything.
Warning: mysqli_connect(): (HY000/1045): Access denied for user
'dbuser'#'172.17.0.3' (using password: YES) in
/var/www/html/config.php on line 8
I don't know how to solve that. So basically, it's two questions, why this error, and if I'm doing the environment variables right.
I have solved this problem
You need to add variable PHP_FPM_CLEAR_ENV=no
environment:
- PHP_FPM_CLEAR_ENV=no
After that everything is ok!
I managed to get it to work, i don't really know what i changed, but basically i removed the environment: from the php container, and moved to the db container, using the mysql image env variables from the dockerhub.