mysqldockergodocker-composeufw

cant connect to local database using external IP:Port


I have 2 Servers, A and B.

They both run the same replicated server-application (rest-API) written in go. On Server B, I also have a database running. Both server and database in docker-containers.

docker-compose.yml

...

 userDB:
      image: mysql:oracle
      restart: always
      container_name: userDB
      environment:
        MYSQL_DATABASE: 'mydb'
        MYSQL_USER: 'user'
        MYSQL_PASSWORD: 'mypw
        MYSQL_ROOT_PASSWORD: 'myrootpw'
      cap_add:
        - SYS_NICE
      ports:
        - '3307:3306'
      networks:
        - dbnet
...


go_rest:
    build:
      context: .
      dockerfile: ./goREST/Dockerfile
    container_name: go_rest
    command: ["./goREST"]
    restart: always
    ports:
      - 8081:8081
    networks:
      - dbnet

Inside the Server, I connect to the database like so:

    db, err := sql.Open("mysql", "root:myrootpw@tcp(bbb.bbb.bbb.bbb:3307)/mydb")


    var usr DBUser
    stmt, _ := db.Prepare(`SELECT * from user;`)
    _ = stmt.QueryRow().Scan(&usr.SteamId)
    log.Println(*usr.SteamId)

note, that the bbb.bbb.... is the public IP of my Server B.

Now the problem:

Running th server-application on Server A (which doesn't have the database), works fine. I can also connect to the database from my development machine using this command:

ssh -L 3307:127.0.0.1:3307 usr@bbb.bbb.bbb.bbb

But when using dockerized version on the machine which holds the database, I can't connect to the database? This only happens, when running inside docker, when I just run the executable like ./goRest on Server B, it also works fine. I am really confused.

In case my explanation was confusing:

A -----> B(docker) works
B -----> B(local) works
B -----> B(docker) doesn not work

(docker) referes to the server-application. The database is always dockerized.

OS: Ubuntu 20.04LTS

EDIT

The error that occurs looks like this:

rest  | 2022/08/29 22:54:00 http: panic serving ......6:45264: runtime error: invalid memory address or nil pointer dereference
rest  | goroutine 9 [running]:
rest  | net/http.(*conn).serve.func1(0xc0000eefa0)
rest  |     /usr/local/go/src/net/http/server.go:1805 +0x153
rest  | panic(0x7d9900, 0xbb2e50)
rest  |     /usr/local/go/src/runtime/panic.go:971 +0x499
rest  | database/sql.(*Stmt).QueryContext(0x0, 0x9b5b10, 0xc00001a088, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
rest  |     /usr/local/go/src/database/sql/sql.go:2630 +0x63
rest  | database/sql.(*Stmt).QueryRowContext(0x0, 0x9b5b10, 0xc00001a088, 0x0, 0x0, 0x0, 0x9af7a0)
rest  |     /usr/local/go/src/database/sql/sql.go:2705 +0x6d


Solution

  • I now found a solution.

    So the problem was with ufw. I had rules like this:

    3307                       ALLOW       aaa.aaa.aaa.aaa
    3307                       ALLOW       prod.local.ip.notebook
    3307                       ALLOW       bbb.bbb.bbb.bbb
    
    

    That's why the acces from my local development computer (aka. prod.local.ip.notebook) and the access from server A (aka aaa.aaa.aaa.aaa) works

    The problem was bbb.bbb.bbb.bbb, because the container with the rest-API accessing the database was not allowed in ufw. To allow this IP, I had to get the container's IP.

    So I ran: docker exec -it xyz /bin/sh, then inside the container: ifconfig which returned 172.22.0.5 for eth0.

    This is the IP which had to be added to ufw. So my new ufw configuration looks like this:

    3307                       ALLOW       aaa.aaa.aaa.aaa <- remote server
    3307                       ALLOW       prod.local.ip.notebook <- development
    3307                       ALLOW       bbb.bbb.bbb.bbb
    3307                       ALLOW       172.22.0.5 <- container ip