Search code examples
dockercontainersdocker-swarm

Port forward on Docker Swarm overlay network


I have a flask and a mysql service running under an overlay network, and each are publishing a port (8080 and 3306 respectively). Here's an inspection of my-network

"Containers": {
            "4698a46d9748b802c74d3eb3cd47c76b9c8ff9fb2aa954338be3ec0ca6fba028": {
                "Name": "mysql-app.1.bfoy8mz5ts9mb7jmuyaqy1ytu",
                "EndpointID": "4c229598a84bc2a3488c24cf15f870bbaa7c48a9b67801558bc9c6382f0f8445",
                "MacAddress": "02:42:0a:00:00:03",
                "IPv4Address": "10.0.0.3/24",
                "IPv6Address": ""
            },
            "4ca9811fe4e04d4ec9a8b0d887b7d971c7d6251e08702729487c2de531dc582f": {
                "Name": "flask-app.1.56j825gcgfrfvv2vkj6e65seu",
                "EndpointID": "260568e4f00aa596ed1fd2b68c51eaf9827d602f54d9d0573d6fcd1da038e899",
                "MacAddress": "02:42:0a:00:00:06",
                "IPv4Address": "10.0.0.6/24",
                "IPv6Address": ""
            }
        },

I can connect to MySQL through Flask using 10.0.0.3. This isn't a guaranteed IP address and isn't able to be set manually. I want there to be a way where I can connect to MySQL without having to check its IP in the first place.

Here's my current command to create the service: docker service create -p 3306:3306 --network my-network --replicas 2 -e MYSQL_ROOT_PASSWORD=password --name mysql-app mysql. My assumption was publishing the port to 3306 would forward it to my-network and I could connect to my-network's gateway.


Solution

  • DNSRR is a key concept of docker swarm mode: https://docs.docker.com/engine/swarm/key-concepts/#load-balancing

    Because you're deploying your MySQL service with --name mysql-app and assign your flask-app in the same network --network my-network, both services can reach each other just by their name. There is no need to figure out the IP address.

    Try

    # create a test network
    docker network create testnetwork
    
    # start mariadb
    docker run -d --name bettermysql --network testnetwork -e MYSQL_ROOT_PASSWORD=nomysql mariadb:latest
    
    # start some other linux and ping mariadb by name
    docker run -ti --network testnetwork alpine:3.7 /bin/sh
    / # ping bettermysql
    PING bettermysql (172.19.0.2): 56 data bytes
    64 bytes from 172.19.0.2: seq=0 ttl=64 time=1.661 ms
    ...
    

    When you're developing in swarm mode, you'd like to use --attachable option in your docker network create command. Than you can access the overlay networks with normal docker container (docker run ...) for testing and debugging.

    TL;DR

    Use mysql-app as MYSQL_HOST in your flask-app config.