Issue
I am trying the following:
- spin MySQL 5.5 in one container with an exposed port, say 4200.
- spin MySQL 5.7 in one container with an exposed port, say 4300.
- spin a golang container to run my app.
The idea is I need my tests to run against different database versions.
For this I need to be able to talk to each of the sql containers from my golang container.
What I have tried:
Method 1 - Using --link:
MYSQL CONTAINER:
docker run --name mysql55c -p 127.0.0.1:4200:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:5.5
GO LANG APP CONTAINER
docker run -w /go/src/app -it --link mysql55c -d --name golangapp -v $(pwd):/go/src/app golang bash -c "go get github.com/go-sql-driver/mysql;go build main.go; go test -v
--config ./config.ini"
Method 2 - Using --net (bridge network &host): Create a bridge nw
docker network mynw
MYSQL CONTAINER:
docker run --name mysql55c --net mynw -p 127.0.0.1:4200:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:5.5
GO LANG APP CONTAINER
docker run -w /go/src/app -it --net mynw -d --name golangapp -v $(pwd):/go/src/app golang bash -c "go get github.com/go-sql-driver/mysql;go build main.go; go test -v
--config ./config.ini"
Instead of creating a bridge network of my own I also tired
--net host
I am able to connect to the sql containers from the host - mysql workbench. But, the golangapp is getting a connection refused error when trying to connect to the mysql servers inside the containers.
All the containers are on the same host.
I am not using a dockerfile or docker compose as:
- trying to get the above done with docker cli commands for easy jenkins integration using official docker images.
Go code to connect to the db using config url
func dbconn() (*sql.DB, error) {
opendb, err := sql.Open("mysql", *dsn + *dbname) //coming from flag
if err != nil {
return nil, err
}
return opendb, nil
}
dsn url combinations I have tried in config:
- dsn = "root:root@tcp(localhost:4200)/"
dsn = "root:root@tcp(172.17.0.0.x:4200)/" (docker0 ip)
dbname="somename"
How can we look at the above? Suggestions about best practices or new methods to achieve my objective are welcome :) Need Help!! Thank you :)
Solution
This should work, follow these steps:
- Run mysql container
docker run --name mysql55c -p 4200:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:5.5
- Create
Dockerfile
for golang with following contents:
FROM golang:latest
COPY . /
RUN go get "github.com/go-sql-driver/mysql"
CMD go run /main.go
- Create
main.go
with following contents:
package main
import(
_ "github.com/go-sql-driver/mysql"
"database/sql"
"log"
)
func main() {
// Open up our database connection.
db, err := sql.Open("mysql", "root:root@tcp(192.168.0.33:4200)/mysql")
// if there is an error opening the connection, handle it
if err != nil {
log.Print(err.Error())
} else {
log.Print("DB connected successfully")
}
defer db.Close()
}
- Build golang container image using
docker build -t goapp .
- Run golang container
docker run -itd goapp
- Check logs of the golang container:
$ docker logs dbd5294abd61
2019/06/19 13:24:17 DB connected successfully
NOTE: I ran mysql container which is exposed on 4200 port of the host. In golang code my connection string was root:root@tcp(192.168.0.33:4200)/mysql
where 192.168.0.33
is private ip of my machine.
The main takeaway for you should be that your db connection string should point to private/public ip of your host. If you run golang without container linking.
If container linking is used while running golang suppose
docker run -itd --link mysql55c:mydb goapp
then mysql connection string in your golang code should be root:root@tcp(mydb:4200)/mysql
Try this and let me know.
Answered By - mchawre
Answer Checked By - Terry (JavaFixing Volunteer)