Docker-Compose Using PHP (MySQLi) to Connect to MySQL database - php

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

Related

Can't connect to a remote mysql database from php within a docker container

My setup: docker (php, mysql, nginx and some other)
My Problem: I can not connect to a remote mysql database within the php docker container
php Example:
try
{
$this->live['pdo'] = new PDO(
'mysql:host='.$_ENV['DB_REMOTE_HOST'].';port='.$_ENV['DB_REMOTE_PORT'].';dbname='.$_ENV['DB_REMOTE_DATABASE'],
$_ENV['DB_REMOTE_USERNAME'],
$_ENV['DB_REMOTE_PASSWORD']
);
$this->live['pdo']->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->live['pdo']->exec("SET NAMES utf8");
$this->live['pdo']->exec("SET CHARACTER SET utf8");
}
catch (PDOException $e)
{
echo $e->getMessage();
exit;
}
my .env
DB_REMOTE_HOST = "5.9.xxx.xx"
DB_REMOTE_PORT = 3306
DB_REMOTE_DATABASE = "somedb"
DB_REMOTE_USERNAME = "someuser"
DB_REMOTE_PASSWORD = "xxxxxx"
part of my docker-compose.yml
php:
build:
context: .
dockerfile: ./php/Dockerfile
args:
ENVIRONMENT: ${ENVIRONMENT}
container_name: php
restart: "unless-stopped"
ports:
- "9000"
- "9006"
- "3306:3306"
volumes:
- ./app/myapp.com:/var/www/html:cached
working_dir: /var/www/html
networks:
- my_network
So when i try to run the php example above, i am getting:
SQLSTATE[HY000] [1045] Access denied for user 'someuser'#'85.110.xxx.xx' (using password: YES
85.110.xxx.xx is the acutal ip address i am getting with my macbook on https://whatsmyip.com/
thats wierd for me, because the ip i try to reach is 5.9.xxx.xx. The mysql user, the database and the password are correct i triple checked it. I can even login with sequel. I already tried to make the port 3306 public for the php container, doesn't change anything.
I will be very thankful, if anyone can help me on this.
In MySQL a user is defined by a username AND an IP address from which they connect. There is the exceptional "%" meaning every IP is accepted. So if your MySQL user isn't defined on the server like 'someuser'#'85.110.xxx.xx' or 'someuser'#'%', the server will deny access to you.

Docker container can't connect to each other

I have two containers in a docker compose, a Postgres DB and a Symfony PHP app.
From within the backend-app (PHP Symfony) I would like to execute commands that handle the DB connection, but none of the configs I try seem to work.
I added expose (https://docs.docker.com/compose/compose-file/#expose) as hinted here and also added a default network as hinted here
docker-compose.yml
version: '3'
services:
database:
image: postgres:11
ports:
- 5431:5432
expose:
- "5431"
environment:
POSTGRES_PASSWORD: password
POSTGRES_USER: user
POSTGRES_DB: my_db
volumes:
- ./database:/var/lib/postgresql/data
frontend:
image: frontend-image:latest
ports:
- 8090:80
backend-app:
image: backend-app:latest
links:
- database
backend-web:
image: backend-web:latest
ports:
- 8091:80
depends_on:
- backend-app
- database
networks:
default:
Depending on the DB config in the Backend Container I get different error messages when executing php bin/console doctrine:schema:update --force inside backend-app:
DATABASE_URL="postgresql://user:password#database:5431/my_db?serverVersion=11&charset=utf8"
leads to
An exception occurred in driver: SQLSTATE[08006] [7] could not connect to server: Connection refused. Is the server running on host "database" (172.21.0.2) and accepting TCP/IP connections on port 5431?
and
DATABASE_URL="postgresql://user:password#localhost:5431/my_db?serverVersion=11&charset=utf8"
leads to
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 5431?
Where am I wrong in my approaches?
You don't get to choose what the container expose inside the internal docker network created by compose.
The postgress image exposes the port 5432, so your expose: 5431 instruction just exposes a port on which postgress is not listening, so it is useless.
So in between containers, you are stuck to using the port 5432 for postgress, unless you derive from the existing image, change the configuration there and expose the port you'd like.
The instruction below just change the port on which the container is exposed to the outside world, as pointed by the documentation
ports:
- 5431:5432
This means that you are exposing the port 5432 of the container to the port 5431 of your host.
Either specify both ports (HOST:CONTAINER), or just the container port (an ephemeral host port is chosen).
Source: https://docs.docker.com/compose/compose-file/#ports
To sum up:
your Symfony configuration should read:
DATABASE_URL="postgresql://user:password#database:5432/my_db?serverVersion=11&charset=utf8"
the expose directive in your compose file is useless
the ports directive as you wrote it there is only convenient if you want to connect from your host machine to the postgress container on a different port than the default one (i.e. because you already have a local postgress server running and, so the port is in use)

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 PHP MySQL connection refused

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)
)

Docker mysql cant connect to container

I've got docker-compose file for creating mysql image and expose port to 3306, but when I try to install CMS, it gives me error that it can't connect to Database. I try to scan port 3306 and it's showing me that it's open so mysql is running.
Why the two of docker containers can't see each other ?
Here is my docker-compose file:
phpfpm:
restart: always
extends:
file: php-fpm-5.6.yml
service: phpfpm
links:
- db:db
nginx:
restart: always
image: nginx
ports:
- "8000:80"
links:
- phpfpm:phpfpm
volumes:
- ./nginx/vhost.conf:/etc/nginx/conf.d/default.conf
- ./app:/var/www/html
- ./log/nginx:/var/log/nginx
db:
restart: always
image: mysql
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_DATABASE: database
To connect to the database, use the link/alias you provided as a hostname. So, you CMS can connect to MySQL using db as hostname, and port 3306.
You won't be able to connect to localhost or 127.0.0.1, because "localhost" is the localhost inside each container, so, using "localhost" in the phpfpm container will try to connect to a MySQL database inside the phpfpm container, but there's no server running there.
Note that you don't have to publish ("3306":"3306") the MySQL ports if you only connect to the database from inside the linked containers. Publishing the ports exposes MySQL on the public network interface, which may be "the Internet"

Categories