2

I'm trying to lock down access to a MySQL user account to one IP address, but it seems that every time you start a docker container, the IP address changes.

docker run -it company/my-app bash

Setup mysql-client on it

apt-get update
apt-get upgrade
apt-get install mysql-client

Now I would connect using:

mysql -u blah -h database.host.com -p
Access denied for user 'blah'@'172.17.0.63' (using password: YES)

Then I would grant all privileges for blah'@'172.17.0.63 and I'd be able to access the database from the container. Now I would start a new docker container and repeat the above steps and I would once again get:

Access denied for user 'blah'@'172.17.0.64' (using password: YES)

The IP address seems to increment every time you start a docker container.

I can limit the hosts to %.%.%.%, but that just means any IP address can connect which is not as secure as I want it.

Is there some sort of way to limit access to a mysql account to only one docker container or group of containers?

Jan Vladimir Mostert
  • 12,380
  • 15
  • 80
  • 137
  • If you only plan to have 1-2 DB instances, one of the solutions could be just to make a mapping to a fixed port. – Axalix May 17 '15 at 15:01
  • @Axalix, how would that work? Currently I only have one DB and one docker instance connecting to it, but in the near future it will be multiple docker instances connecting to the master for read-write, each with their own credentials and multiple instances connecting to the slaves, also each with their own read-only credentials. – Jan Vladimir Mostert May 17 '15 at 15:30
  • http://stackoverflow.com/questions/16958729/how-to-assign-as-static-port-to-a-container – Axalix May 17 '15 at 15:32
  • The DB is running outside a docker instance so is already running on a fixed port 3306. – Jan Vladimir Mostert May 17 '15 at 16:03
  • 1
    I withdrew my incorrect answer. Instead see http://stackoverflow.com/questions/28358008/how-to-properly-specify-an-ip-for-a-docker-container/28370012#28370012 for suggestions. – Richard Neish May 18 '15 at 14:33

2 Answers2

1

I think your current approach is wrong. You can simply use the official MySQL container and link to it the cointainers you want to have access:

docker run --name some-app --link some-mysql:mysql -d app-that-uses-mysql

This will add an entry to the some-app /etc/hosts file with the name "mysql" pointing to the MySQL container, as described in the docker linking docs.

dukebody
  • 7,025
  • 3
  • 36
  • 61
  • DB is running outside of docker for the simple reason that I want the flexibility to switch to AWS RDS or Google Cloud SQL without changing my docker scripts. – Jan Vladimir Mostert May 18 '15 at 11:49
  • You will always have that flexibility. Docker containers have access to the Internet. You would simply have to drop the --link option and point the app to the external MySQL service. – dukebody May 18 '15 at 14:33
  • I would never put a production database inside a docker image and cloud databases like Google Cloud SQL is already outside a docker image. Even if I did put it inside a docker image, I'd still have the problem where anyone, any device, anything that can access port 3306 will just be a password away from accessing the DB instead of having some sort of IP filtering via MySQL account and a firewall doing IP filtering in front of that. – Jan Vladimir Mostert May 18 '15 at 14:54
  • No, if you link containers but don't publish their ports to the host machine, only the app container will have access to the MySQL instance. If you do publish the ports of the MySQL container, you can still use a firewall. – dukebody May 18 '15 at 15:02
  • ... but that still means MySQL has to run in docker container? – Jan Vladimir Mostert May 18 '15 at 18:58
  • If you want to use the --link feature, yes, it has to run in a docker container. Otherwise I advise you to use a firewall in your host instead of restricting MySQL logins by IP. – dukebody May 20 '15 at 09:21
1

You can configure a small dnsmasq instance to be used by MySQL, and run a script to automatically update the DNS record when the container's IP address has changed.

I've written a small script to do this (pasted below), which automatically update DNS record which has the same name as the containers' name and points them to the containers' IP addresses:

#!/bin/bash

# 10 seconds interval time by default
INTERVAL=${INTERVAL:-10}

# dnsmasq config directory
DNSMASQ_CONFIG=${DNSMASQ_CONFIG:-.}

# commands used in this script
DOCKER=${DOCKER:-docker}
SLEEP=${SLEEP:-sleep}
TAIL=${TAIL:-tail}

declare -A service_map

while true
do
    changed=false
    while read line
    do
        name=${line##* }
        ip=$(${DOCKER} inspect --format '{{.NetworkSettings.IPAddress}}' $name)
        if [ -z ${service_map[$name]} ] || [ ${service_map[$name]} != $ip ] # IP addr changed
        then
            service_map[$name]=$ip
            # write to file
            echo $name has a new IP Address $ip >&2
            echo "host-record=$name,$ip"  > "${DNSMASQ_CONFIG}/docker-$name"
            changed=true
        fi
    done < <(${DOCKER} ps | ${TAIL} -n +2)

    # a change of IP address occured, restart dnsmasq
    if [ $changed = true ]
    then
        systemctl restart dnsmasq
    fi

    ${SLEEP} $INTERVAL
done

Then, create your MySQL user with the host equal to the container's name, e.g. your container's name is blah then you create MySQL user as 'you'@'blah'.

xuhdev
  • 8,018
  • 2
  • 41
  • 69