phpmysqldockerdocker-compose

PHP app cannot connect to docker mysql container at 127.0.0.1


Mysql is in it's own docker-compose.yml as I want a mysql server up and running that any other php application can connect to. So I do not have php and mysql in the same docker-compose.yml. From the php application, I can connect to mysql if I use the mysql container's gateway ip address by looking it up and then hard coding it into the php application. docker inspect mysql-db. But docker will change that 172... ip address each time mysql restarts so that is not ideal for development.

I can connect to mysql via mysql -h 127.0.0.1 no problem, but from the php application if I try to use 127.0.0.1 I get connection refused. I can only connect if I use the 172... gateway ip address.

How do I get the mysql container listening for connections from the host to 127.0.0.1?

docker-compose.yml for mysql

version: "3"

services:
  mysql:
    container_name: mysql-db
    image: mysql
    build:
      dockerfile: Dockerfile
      context: ./server/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=admin
    volumes:
      - ./data/mysql:/var/lib/mysql
    ports:
      - 3306:3306

docker-compose.yml for php

version: "3"

services:
  nginx:
    container_name: nginx_myapp
    image: nginx
    build:
      dockerfile: Dockerfile
      context: ./server/nginx
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./app:/var/www/html
    networks:
      - myapp
  php:
    container_name: php_myapp
    image: php:7.3-fpm
    build:
      dockerfile: Dockerfile
      context: ./server/php-fpm
    environment:
      CI_ENV: development
    volumes:
      - ./app:/var/www/html
    networks:
      - myapp

networks:
  myapp:

Solution

  • 127.0.0.1 is the loopback address. It points to localhost. In the context of docker, localhost is the container itself. There is no db running on your php container so the connection will never succeed.

    What you need to do is to configure the default network in you mysql compose file so that you will predictably control its name for later convenience (else it will be calculated from your compose project name which could change if you rename the containing folder...):

    Important note: for the below to work, you need to use compose file version >= 3.5

    ---
    version: '3.7'
    #...
    networks:
      default:
        name: shared_mysql
    

    You can now use that shared_mysql network as external from any other compose project.

    version: '3.7'
    
    services:
      nginx:
        #...
        networks:
          - myapp
      php:
        #...
        networks:
          - myapp
          - database
    
    networks:
      myapp:
      database:
        external: true
        name: shared_mysql
    

    You can then connect to mysql from your php container using the service name mysql (e.g. mysql -h mysql -u user -p)

    Reference: https://docs.docker.com/compose/networking/