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
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