I am using golang app , wrapped up in a docker container to connect to mysql db running on my localhost(not container). Her eis what I tried:
Docker File
FROM artifactory.cloud.com//golang:1.10-alpine3.7
RUN mkdir -p /go/src/github.kdc.mafsafdfsacys.com/perfGo/
WORKDIR /go/src/github.kdc.mafsafdfsacys.com/perfGo
COPY ./ $WORKDIR
RUN apk update && apk upgrade
RUN go build
RUN chmod +x ./entrypoint.sh
RUN ls
RUN chmod +x ./perfGo
ENTRYPOINT ["./entrypoint.sh"]
perfGo.go
package main
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
func main() {
db, err := sql.Open("mysql", "root:#tcp(localhost:3306)/testdb")
checkErr(err)
_,dbErr := db.Exec("USE testdb")
if err != nil {
panic(dbErr)
}
// insert
_, inErr := db.Query("INSERT INTO books VALUES('rewyrewryewwrewyt','dsfdsfs','fdsfasaf','55')")
defer db.Close()
// if there is an error inserting, handle it
if inErr != nil {
panic(inErr.Error())
}
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
entrypoint.sh
!/usr/bin/env bash
./perfGo
Command am using to build is
docker build .
command used to run the container:
docker run -p 3306:3306 -ti
The error that I see is
panic: dial tcp 127.0.0.1:3306: connect: connection refused
goroutine 1 [running]:
main.main()
/go/src/github.kdc.capitalone.com/midnight-tokens/perfGo/perf.go:22 +0x1d4
If I run the binary without the container, it runs totally fine on my mac, but when I try to run it as part of docker container, it fails to connect
If the application is running in a container, and the database is on the host, then the address of the database from the container is obviously not localhost (That is the loopback device of the container).
If you are using Docker For Mac, then you can use:
"docker.for.mac.localhost:3306" in place of "localhost:3306"
Related
I'm trying to connect mysqlDB which is created on Docker from my local go file.
main.go
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
func main() {
fmt.Println("Hello")
// All following 4 codes won't connect to the database.
// "db01" is docker container name. "test" is db name.
// db, err := sql.Open("mysql", "root:password#tcp(localhost:3306)/test")
// db, err := sql.Open("mysql", "root:password#tcp(localhost)/test")
// db, err := sql.Open("mysql", "root:password#tcp(db01)/test")
db, err := sql.Open("mysql", "root:password#tcp(db01:3306)/test")
if err != nil {
fmt.Println(err)
}
defer db.Close()
fmt.Println(db)
err = db.Ping()
if err != nil {
fmt.Println(err)
}
}
docker command
docker run --name db01 -dit -e MYSQL_ROOT_PASSWORD=password mysql:latest
error message
when trying with localhost:3306
dial tcp [::1]:3306: connect: connection refused
when trying with db01
dial tcp: lookup db01: no such host
mysql db is created on docker container without any issue, so I think connection between go file and docker container is not going well.
Do I have to create docker-compose.yml file?
I want to connect without it at now.
Thank you.
You created a docker container and ran MySQL in it. That container will have its own network address. You can publish a port of that container on your localhost by running:
docker run --name db01 -p 3306:3306 -dit -e MYSQL_ROOT_PASSWORD=password mysql:latest
This will publish the port 3306 of the container on localhost:3306. Then you can connect to it.
Alternatively, you can get the IP address of the container running using docker inspect <containerId>, and connect to that address:3306.
I am new to golang, docker and mysql. I am trying to connect to mysql running in docker locally on my macos using golang.
Here is the code:
`package main
import (
"context"
"database/sql"
_ "github.com/go-sql-driver/mysql"
"log"
"time"
)
func dbConn() *sql.DB {
db, err := sql.Open("mysql", "root:Abc123$##tcp(172.17.0.2:3306)/test")
if err != nil {
log.Printf("Error %s when opening DB connection\n", err)
return nil
}
db.SetMaxOpenConns(10)
db.SetMaxIdleConns(10)
db.SetConnMaxLifetime(time.Minute * 2)
ctx, cancelfunc := context.WithTimeout(context.Background(), time.Second)
defer cancelfunc()
err = db.PingContext(ctx)
if err != nil {
log.Printf("Error %s pinging DB", err)
return db
}
log.Print("Connected to the DB successfully\n")
defer func() {
err := db.Close()
if err != nil {
log.Print(err)
}
}()
return db
}
func main() {
db := dbConn()
defer db.Close()
}`
I am running docker with the following command:
docker run --name mysql -e MYSQL_ROOT_PASSWORD=abcd1234 -p 3306:3306 -d mysql:8.0.30
I get the following error:
Error dial tcp 172.17.0.2:3306: i/o timeout pinging DB
docker is running locally. I created a test-db with command-line:
`mysql> create database test_db;`
and then did a
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test_db |
+--------------------+
6 rows in set (0.00 sec)
Please help me understand my mistake here? Or what am I missing?
I used host.docker.internal in this docker-compose.yml file to create the mysql sever in docker.
version: '3'
services:
mysql-development:
image: mysql:8.0.30
environment:
MYSQL_ROOT_PASSWORD: xyz1234
MYSQL_DATABASE: test
ports:
- "3306:3306"
extra_hosts:
- "host.docker.internal:host-gateway"
Used this to run the docker image:
docker-compose -f docker-compose.yml up
Then connected to docker mysql instance using:
docker exec -it 24f058c73227 mysql -P 3306 --protocol=tcp -u root -p
Then created a separate user and granted all privileges to the new user.
mysql> CREATE user ‘user2’#‘172.19.0.1' IDENTIFIED BY ‘xyz1234’;
mysql> GRANT ALL PRIVILEGES ON *.* TO 'user2'#'172.19.0.1' WITH GRANT
OPTION;
This helped me connect to mysql server running on the docker locally on macos.
I'm trying to build a Docker container that contains both MySQL and a Go server.
Just importing the MySQL libraries cause the error.
Any pointers to what I'm doing wrong?
This is the terminal after build:
Successfully built 5d5356e2ca72
Successfully tagged test3:latest
$GOPATH/go.mod exists but should not
But there is no go.mod in the $GOPATH
$ ls -a $GOPATH
. .. bin pkg
This is the go server:
package main
import (
"database/sql"
"flag"
"fmt"
"log"
"net/http"
"strings"
_ "github.com/go-sql-driver/mysql"
)
type FileSystem struct {
fs http.FileSystem
}
var listen = flag.String("listen", ":8989", "listen address")
var dir = flag.String("dir", ".", "directory to serve")
func main() {
db()
flag.Parse()
directory := "./"
fileServer := http.FileServer(FileSystem{http.Dir(directory)})
http.Handle("/", fileServer)
fmt.Printf("Web server running. Listening on %q", *listen)
err := http.ListenAndServe(*listen, http.FileServer(http.Dir(*dir)))
fmt.Printf("%v\n", err)
}
func (fs FileSystem) Open(path string) (http.File, error) {
f, err := fs.fs.Open(path)
if err != nil {
return nil, err
}
s, err := f.Stat()
if s.IsDir() {
index := strings.TrimSuffix(path, "/") + "/index.html"
if _, err := fs.fs.Open(index); err != nil {
return nil, err
}
}
return f, nil
}
func db() {
db, err := sql.Open("mysql", "root:root#tcp(192.168.0.33:4200)/mysql")
if err != nil {
log.Print(err.Error())
} else {
log.Print("DB connected successfully")
}
defer db.Close()
}
This is my go.mod
module test3
go 1.14
require github.com/go-sql-driver/mysql v1.5.0
This is the Dockerfile
FROM golang:alpine AS builder
ENV GO111MODULE=auto \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64
COPY . .
COPY ./server.go .
COPY ./favicon.ico .
COPY ./assets /assets
EXPOSE 8989
CMD ["go", "run", "./server.go"]
And this is how I build the container:
docker rmi test3 -f
docker build --no-cache -t test3 .
docker run -p 8989:8989 test3
$GOPATH/go.mod exists but should not
By default the goland:alpine image starts the working directory in the GOPATH (i.e. /go) folder where globally installed packages are created with the go install command.
The folder structure looks like:
go/
bin/
src/
pkg/
By directly copying go.mod into the working directory (i.e. GOPATH, i.e. /go), the golang toolkit throws an error, because go.mod is supposed to be in a package folder.
Before the release of Go modules in version 1.11, the convention was to create your packages in the /go/src folder. However, with the release of Go modules you can create golang packages anywhere as long as they include a go.mod file.
So to fix the error, you could copy the golang files (go.mod, etc) into a folder under /home/app or /go/src/app.
Copy into /home/app
RUN mkdir ../home/app
WORKDIR /../home/app
COPY . .
Copy into /go/src/app
RUN mkdir src/app
WORKDIR /src/app
COPY . .
I try to lunch application in ECS.
There is no problem when lunching in my local docker environment.
But it can't accrss to api server in ECS because of rds connection problem.
I use golang in api server and mysql for db.
I call db.go in main.go
func main() {
db := db.NewDatabase(os.Getenv("MYSQL_USER"), os.Getenv("MYSQL_PASSWORD"), os.Getenv("MYSQL_HOST"))
Error occurs when connecting to rds database
func NewDatabase(user, password, host string) *Database {
db, err := sql.Open("mysql", user+":"+password+"#tcp("+host+":3306)/article")
if err != nil {
panic(err.Error())
}
err = db.Ping()
// error occurs here
if err != nil {
panic(err.Error())
}
I deploy it to elastic beanstalk.
I checked environment variables are correctly set.
Here is the full source code:
https://github.com/jpskgc/article
I expect there is no error in elastic beans.
But the actual is not.
I want to know solution for that.
Here is the error log in elastic beanstalk.
-------------------------------------
/var/log/containers/server-4c66c8d1848a-stdouterr.log
-------------------------------------
panic: dial tcp 172.31.26.91:3306: connect: connection timed out
goroutine 1 [running]:
article/api/db.NewDatabase(0xc00002401b, 0x4, 0xc00002a00f, 0xb, 0xc00002800b, 0x3c, 0xdb94f2)
/app/db/db.go:20 +0x3bc
main.main()
/app/main.go:18 +0xee
"connection timed out" means that there are firewall limitation, and you can also check your mysql whitelist, which should has ip of your ECS.
I've written a piece of code in Golang to test Google Cloud SQL:
package main
import (
"database/sql"
"flag"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
var addr = flag.String("db", "", "The database address")
func main() {
flag.Parse()
db, err := sql.Open("mysql", *addr)
if err != nil {
fmt.Println("mysql open failed: ", err)
return
}
defer db.Close()
err = db.Ping()
if err != nil {
fmt.Println("mysql ping failed: ", err)
return
}
fmt.Println("mysql ping success")
}
I've tested the above code, the output is mysql ping success
Then I want to test this function inside Docker container, the Dockerfile following:
FROM golang
ADD . $GOPATH/src/github.com/pdu/gcloud-sql-test
RUN go install github.com/pdu/gcloud-sql-test
ENTRYPOINT ["gcloud-sql-test"]
CMD ["-db=\"user:passwd#tcp(gcloud.sql.ip.address:3306)/database\""]
After building the Docker image, and run the container, I got the following output:
mysql ping failed: Error 1045: Access denied for user '"user'#'my.local.ip.address' (using password: YES)
I've already configured that my local IP can access Google Cloud SQL. I don't know why it doesn't work inside Docker container but works outside Docker container.
Updates, I've fixed the issue because of Dockerfile error
FROM golang
ADD . $GOPATH/src/github.com/pdu/gcloud-sql-test
RUN go install github.com/pdu/gcloud-sql-test
CMD ["gcloud-sql-test", "-db=user:passwd#tcp(gcloud.sql.ip.address:3306)/database"]
The main difference is to remove the quotation mark in the Dockerfile:CMD parameter, while you need the quotation mark when you execute the program from Terminal.
Try
FROM golang
ADD . $GOPATH/src/github.com/pdu/gcloud-sql-test
RUN go install github.com/pdu/gcloud-sql-test
CMD ["gcloud-sql-test","-db=\"user:passwd#tcp(gcloud.sql.ip.address:3306)/database\""]
CMD and ENTRYPOINT are different commands
I've fixed the issue because of Dockerfile error
FROM golang
ADD . $GOPATH/src/github.com/pdu/gcloud-sql-test
RUN go install github.com/pdu/gcloud-sql-test
CMD ["gcloud-sql-test", "-db=user:passwd#tcp(gcloud.sql.ip.address:3306)/database"]
The main difference is to remove the quotation mark in the Dockerfile:CMD parameter, while you need the quotation mark when you execute the program from Terminal.