I’ve been searching the web for hours but do not find any solution to my problem.
I have 3 containers:
- nginx
- php
- mysql
They are all connected to the same network.
If I try to log into mysql from the mysql container, all works fine.
If I try to make a pdo connection from the php container to the mysql container, I always receive the message “Access denied for user”. I have no idea why. Let me show you guys what happens.
This is my docker-compose file:
version: ‘3’
networks:
danvers:
services:
#WebServer Service
danvers-nginx:
image: nginx:stable
container_name: danvers-nginx
ports:
- ‘8080:80’
volumes:
- ./:/var/www
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- danvers-php
- danvers-mysql-app
networks:
danvers:
#PHP Service
danvers-php:
build:
context: ./
dockerfile: Dockerfile
container_name: danvers-php
volumes:
- ./:/var/www
- ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini
depends_on:
- danvers-mysql-app
networks:
danvers:
#MySQL Service for App Database
danvers-mysql-app:
image: mysql:5.7.22
container_name: danvers-mysql-app
restart: unless-stopped
tty: true
ports:
- “33061:3306”
environment:
- MYSQL_ROOT_PASSWORD=securerootpassword
- MYSQL_DATABASE={DB_APP_DATABASE}
- MYSQL_USER={DB_APP_USERNAME}
- MYSQL_PASSWORD=${DB_APP_PASSWORD}
volumes:
- danvers-app-data:/var/lib/mysql
- ./docker/mysql/my.cnf:/etc/mysql/my.cnf
networks:
danvers:
volumes:
danvers-app-data:
If I go inside the danvers-php container and open a interactive shell for php and try to make a pdo connection I get this:
php > new PDO(‘mysql:host=danvers-mysql-app;dbname=danvers-app’, ‘d-app-conn-user’, ‘cable’);
Warning: Uncaught PDOException: SQLSTATE[HY000] [1045] Access denied for user ‘d-app-conn-user’#‘danvers-php.projectdanvers_danvers’ (using password: YES) in php shell code:1
Stack trace:
#0 php shell code(1): PDO->__construct(‘mysql:host=danv…’, ‘d-app-conn-user’, ‘cable’)
#1 {main}
thrown in php shell code on line 1
The connection is made as I see the incoming request in the log from danvers-mysql-app.
What seems odd here is that the user-format in the error looks strange. I have no clue where the “danvers-php.projectdanvers_danvers” comes from. This is a concatenation of the php container and the network the containers are on. I think this is why the access is denied by have no clue how to change this as I assumed this should be the mysql containers name instead.
Does anybody have a clue to what I am doing wrong here?
Thanks for any reply or feedback.
EDIT:
In my mysql container I logged in with root and get this users list:
+-----------------+-----------+
| user | host |
+-----------------+-----------+
| d-app-conn-user | % |
| root | % |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+-----------------+-----------+
Output from select user, host from mysql.user
The % for host name means no matter what the hostname is, as long as the username is correct, I should be able to login. The credentials are working from inside the mysql container but when the connection is made from another container, it fails.
If I try to make a connection with SequelPro from my local machine through port 33061, it also works. The problem only exist when it's an inter container connection.
EDIT2:
So I changed the nginx and php configuration with a php:7.4-apache configuration in my Dockerfile and now this problem does not exist anymore. I am able to log into the mysql container from the php container. The problem is related to the Nginx web server.
Related
I'm on a symfony project and i'm using docker here's my docker-compose.yml :
version: '3.7'
services:
db:
image: mysql:latest
container_name: ruakh_db
restart: always
volumes:
- db-data:/var/lib/mysql
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
networks:
- dev
phpmyadmin:
image: phpmyadmin:latest
container_name: ruakh_phpmyadmin
restart: always
depends_on:
- db
ports:
- 8080:80
environment:
PMA_HOST: db
networks:
- dev
maildev:
image: maildev/maildev
container_name: ruakh_mail_dev
restart: always
command: bin/maildev --web 80 --smtp 25 --hide-exetensions STARTTLS
ports:
- 8081:80
networks:
- dev
apache:
build: php
container_name: ruakh_www
ports:
- 8088:80
volumes:
- ./php/vhosts:/etc/apache2/sites-enabled
- ./:/var/www
restart: always
networks:
- dev
networks:
dev:
volumes:
db-data:`
here's the database url used in my symfony project :
DATABASE_URL=mysql://root:root#ruakh_db/ruakh
I'm trying to run a php bin/console make:migration however when i'm running I get this error :
An exception occurred in driver: SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution
I'm assuming that the database url is incorrect, when I changed it to :
DATABASE_URL=mysql://root:root#127.0.0.1:8080/ruakh
This error is thrown:
An exception occurred in driver: SQLSTATE[HY000] [2006] MySQL server has gone away
How can I manage to connect my symfony project to my docker database ?
There is a couple things wrong with your DATABASE_URL.
DATABASE_URL=mysql://root:root#ruakh_db/ruakh
You don't set the password in your service config
You have the wrong host name
You don't specify the database
You are using native authentication, which must be enabled when using MySQL 8
(optional) your database port is not exposed
Password
In your docker-compose.yml. you do not specify the root password and instead allow for an empty password. You can set the root password using an environment variable:
services:
db:
...
environment:
MYSQL_ROOT_PASSWORD: example
Database name
In order to create a default database named ruakh you need to provide another environment variable MYSQL_DATABASE.
Host
The next issue is the host name in your DATABASE_URL: ruakh_db. This is the name of the container, but not the name of the service (i.e. the host in the virtual network that docker-compose sets up). This should be db instead.
Port
You will not be able to access your mysql database from outside the docker container, because you do not expose any ports. That is not necessarily an issue, but you should be aware of it. Looking at your other database url DATABASE_URL=mysql://root:root#127.0.0.1:8080/ruakh this will not work, because the port 8080 is for the web interface provided by phpmyadmin. It is not the port of the actual database. Also, the port for the database is not exposed. You probably want to add:
services:
db:
...
ports:
- 3306:3306
Authentication
Another issue, you will face is using the image mysql:latest this will use MySQL 8.0 which does not allow the authentication mechanism you want to use by default. You will have to change the command executed when running the container or downgrade to MySQL 5.7. If you want to keep MySQL 8, you should add this:
services:
db:
...
command:
- 'mysqld'
- '--character-set-server=utf8mb4'
- '--collation-server=utf8mb4_unicode_ci'
- '--default-authentication-plugin=mysql_native_password'
Summary
This is roughly what your db service should look like to work with your DATABASE_URL:
db:
image: mysql:latest
ports:
- '3306:3306'
environment:
MYSQL_DATABASE: ruakh
MYSQL_ROOT_PASSWORD: 'root'
command:
- 'mysqld'
- '--character-set-server=utf8mb4'
- '--collation-server=utf8mb4_unicode_ci'
- '--default-authentication-plugin=mysql_native_password'
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
Can a services running in two different docker stack communicate ?
This is what I have tried and not able to achieve it.
Created a stack (stack1) running nginx and php-fpm its running great.
Created another stack (stack2) running mysql database.
Now I want to make the stack1 service able to communicate with stack2 such that it can access the database service.
I though this might help and created a external network and trying to
add the service in stack1 and stack2 to it such that they can
communicate with each others too
Mystack1 docker-compose file
version: "3.4"
networks:
apps-net:
db-net:
external:
name: db-net
services:
web:
image: nginx:latest
ports:
- "9080:80"
volumes:
- ./code:/code
- ./site.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php
networks:
- apps-net
- db-net
deploy:
mode: replicated
replicas: 1
php:
image: php:7-fpm
volumes:
- ./code:/code
networks:
- apps-net
- db-net
deploy:
mode: replicated
replicas: 1
MY stack2 docker-compose file
version: '3.3'
networks:
db-net:
external:
name: db-net
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: wordpress
MYSQL_USER: root
MYSQL_PASSWORD: password
networks:
- db-net
volumes:
db_data:
I created a swarm scope network with docker network create db-net command
OUTPUT:
The nginx and php is working fine but I added the database connection
codes in the index.php which resulted in error message.Is the error
because they are not connected? I have installed php-mysql extensions
too but it has the error. How can I make sure the services are
communicating successfully.
nginx and php working
Fatal error: Uncaught Error: Call to undefined function mysqli_connect() in /code/index.php:11 Stack trace: #0 {main} thrown in /code/index.php on line 11
Instead of networks (which I often see asked here on stack as not working like expected) try using external_links which is well explained here.
Try removing all custom network configurations and simply modify your application compose file like this:
version: "3.4"
# removed all custom networks configuration
services:
web:
image: nginx:latest
external_links:
- mysql_1:mysql
[..]
php:
image: php:7-fpm
external_links:
- mysql_1:mysql
[..]
where mysql_1 is a actual container name create by your latter compose file, and mysql is a alias by which your service will be available inside php and web containers
Links are a legacy option in v3 and Docker suggests using networks instead.
I'll post a edit about swarm deployment as approach would be totally different because Docker ignores links when deploying swarm.
I'm seasoned in Symfony but quite new to docker, and I have a "connection refused error" I don't manage to solve.
Pretty sure it is a beginner error and that the solution here is quite simple...
Here is the content of my docker-compose file:
version: '3.2'
services:
cg-demo:
build: docker/cg-demo
container_name: cg-demo
working_dir: /var/www/html
volumes:
- .:/var/www/html
- ./docker/demo/vhost.conf:/etc/apache2/sites-available/000-default.conf:ro
- ./docker/demo/php.ini:/usr/local/etc/php/php.ini:ro
- ~/.ssh:/var/www/.ssh
- ~/.composer:/var/www/.composer
environment:
- SYMFONY_ENV
- DOMAIN_NAME: cg-demo.docker
- VIRTUAL_HOST: cg-demo.docker
depends_on:
- database
env_file: .env
ports:
- 8000:80
database:
image: percona:5.6
ports:
- 3306:3306
expose:
- 3306
container_name: cg-demo-database
volumes:
- /docker/database:/etc/mysql/conf.d
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: demo
tmpfs:
- /var/lib/mysql
- /tmpfs:size=300M
This has been based from another project that works, but I'm not sure of all that's happening here...
I also have a phpmyadmin container, not shown here. PhpMyAdmin connects correctly to the database and can use it without problem from any web server. However when it comes to the symfony container, I have this whenever trying to use the database:
[Doctrine\DBAL\Exception\ConnectionException]
An exception occured in driver: SQLSTATE[HY000] [2002] Connection refused
[Doctrine\DBAL\Driver\PDOException]
SQLSTATE[HY000] [2002] Connection refused
[PDOException]
SQLSTATE[HY000] [2002] Connection refused
The connection information is the following, in a .env file:
# Database credentials
DATABASE_HOST=database
DATABASE_PORT=3306
DATABASE_USER=root
DATABASE_PASSWORD=root
DATABASE_DB=cg-demo
Calling docker ps gives me this:
CONTAINER ID IMAGE COMMAND
CREATED STATUS PORTS NAMES
16a67dadeebb phpmyadmin/phpmyadmin "/run.sh phpmyadmin" 15 minutes ago Up 15 minutes 0.0.0.0:8001->80/tcp cg.phpmyadmin.docker
8bd783aa1dd1 cg_cg-demo "entrypoint.sh apa..." 15 minutes ago Up 15 minutes 0.0.0.0:8000->80/tcp cg-demo
2fc7cd9105ba percona:5.6 "docker-entrypoint..." 15 minutes ago Up 15 minutes (healthy) 3306/tcp cg-database
I've tried to ping database from the demo container and it works...
EDIT 1:
Added the following to the database container:
ports:
- 3306:3306
EDIT 2:
Removed the following from all containers:
networks:
- default
EDIT 3:
My doctrine configuration in app/config/config.yml:
dbal:
host: "%env(DATABASE_HOST)%"
port: "%env(DATABASE_PORT)%"
dbname: "%env(DATABASE_DB)%"
user: "%env(DATABASE_USER)%"
password: "%env(DATABASE_PASSWORD)%"
charset: UTF8
mapping_types:
enum: string
server_version: 5.6
EDIT 4:
Added the following to the database configuration:
expose:
- 3306
This answer is for docker-compose version 2 and it also works on version 3:
The problem is a Linking Containers problem. We need to define additional aliases that services can use to reach one another.
Expose 3306 port will not solve your problem. mysql or percona container will expose by deffault that port. Take a look to the docker hub of percona image.
. It's mentioned there:
Connect to MySQL from an application in another Docker container
This image exposes the standard MySQL port (3306), so container
linking makes the MySQL instance available to other application
containers. Start your application container like this in order to
link it to the MySQL container:
$ docker run --name some-app --link some-percona:mysql -d application-that-uses-mysql
So, you should links the database to you cg-demo container. There's tow solutions:
1) Add a link under configuration :
services:
cg-demo:
build: docker/cg-demo
container_name: cg-demo
.
.
.
links:
- mysql
The diffirence between depeds_on and links is that depends_on docker-compose up will start services in dependency order. In your following example, database will be started before web.
We can also access data. But this is not enough, because we want to make sure that your web container (cg-demo) always connect to the database container.
Links allow you to define extra aliases by which a service is reachable from another service.
In the following example, database is reachable from web (cg-demo) at the hostname database. This means that thecg-demo can connect the database contanier from the 3306 port.
2) The second solution, is to configure the default network instead of (or in addition to) customizing your own network. Simply define a default entry under networks:
networks:
bridge_name:
driver: bridge
And then you should link every container to that bridge via networks tag:
cg-demo:
.
.
networks:
- bridge_name
database:
.
.
networks:
- bridge_name