Golang MySQL Docker в соединении отказано - PullRequest
0 голосов
/ 17 июня 2020

У меня есть приложение, которое использует docker -compose, и я получаю connection refused как для phpMyAdmin, так и для Golang. В комментариях к коду есть операторы отладки.

Любые указания на то, что я делаю неправильно?

#docker-compose.yml
version: '3'
services:
  fullstack-mysql:
    container_name: db_mysql
    build:
      context: ./MySQL
    ports:
      - 3306:3306
    volumes:
      - database_mysql:/var/lib/mysql
    networks:
      - fullstack

  app:
    container_name: golang_app
    env_file:
      - ./Go/.env
    build:
      context: ./Go
    ports:
      - 9000:9000
    restart: on-failure
    volumes:
      - api:/usr/src/app/
    depends_on:
      - fullstack-mysql
    networks:
      - fullstack

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: phpmyadmin_container
    env_file:
      - ./MySQL/.env
    depends_on:
      - fullstack-mysql
    environment:
      - PMA_HOST=fullstack-mysql #Note the "mysql". Must be the name of the what you used as the mysql service.
      - PMA_USER=root
      - PMA_PORT=3306
      - PMA_PASSWORD=root
    ports:
      - 9090:80
    restart: always
    networks:
      - fullstack

volumes:
  api:
  database_mysql:

networks:
  fullstack:
    driver: bridge
//server.go
package main

import (
    "database/sql"
    "fmt"
    "log"
    "net"
    "net/http"
    "os"
    "os/exec"
    "strconv"
    "strings"

    _ "github.com/go-sql-driver/mysql"
    "github.com/jimlawless/whereami"
)

func setConfig() {
    config = Configs{}
    config.cookieName = os.Getenv("COOKIE_NAME")
    config.cookieValue = os.Getenv("COOKIE_VALUE")
    age, err := strconv.Atoi(os.Getenv("COOKIE_MAX_AGE"))
    if err != nil {
        log.Println(whereami.WhereAmI(), err.Error())
    }
    config.cookieMaxAge = age

    config.cookieHTTPOnly, err = strconv.ParseBool(os.Getenv("COOKIE_HTTP_ONLY"))
    if err != nil {
        log.Println(whereami.WhereAmI(), err.Error())
    }

    config.cookiePath = os.Getenv("COOKIE_PATH")
    config.domain = os.Getenv("DOMAIN")
    config.port = os.Getenv("PORT")
    config.apiKey = os.Getenv("APP_KEY")
    config.apiVersion = os.Getenv("API_VERSION")
    config.apiPath = os.Getenv("API_PATH")
    config.protocol = os.Getenv("PROTOCOL")
    config.mysqlDB = os.Getenv("MYSQL_DATABASE")
    config.mysqlHost = os.Getenv("MYSQL_HOST")
    config.mysqlPassword = os.Getenv("MYSQL_PASSWORD")
    config.mysqlPort = os.Getenv("MYSQL_PORT")
    config.mysqlUser = os.Getenv("MYSQL_USER")
    config.mysqlDriver = os.Getenv("MYSQL_DRIVER")
}

func main() {
    defer recoverPanic()
    setConfig()
    err := db()
    if err != nil {
        //log.Fatal(whereami.WhereAmI(), err.Error())
        log.Println(whereami.WhereAmI(), err.Error())
    }

    fmt.Println(config)
    //{panda 123456987 0 true / 127.0.0.1 :9000 secret-sauce v1 /api/ http:// docker docker 3306 127.0.0.1 test_db mysql}

    routes()
}

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() error {
connStr:=config.mysqlUser+":"+config.mysqlPassword+"@tcp("+config.mysqlHost+":"+config.mysqlPort+")/"+config.mysqlDB
    //Ping Error: dial tcp: lookup db:127.0.0.1:3306: no such host
    //Ping Error: dial tcp 23.195.69.108:3306: connect: connection refused <-- MYSQL_HOST=fullstack-mysql

    //connStr:=config.mysqlUser+":"+config.mysqlPassword+"@tcp(db:"+config.mysqlPort+")/"+config.mysqlDB
    //Ping Error: dial tcp 23.195.69.108:3306: connect: connection refused

    log.Println(connStr)
    //docker:docker@tcp(fullstack-mysql:3306)/test_db
    db, err := sql.Open(config.mysqlDriver, connStr)
    if err != nil {
        log.Println(whereami.WhereAmI(), err.Error())
    } else {
        log.Println(fmt.Sprintf("%s", db), whereami.WhereAmI())
    }
    defer db.Close()

    err = db.Ping()
    if err != nil {
        log.Println("Ping Error: " + err.Error())
    } else {
        dbx.conn = db
    }

    log.Println(fmt.Sprintf("%s", dbx.conn), whereami.WhereAmI())
    log.Println(fmt.Sprintf("%T", dbx.conn), whereami.WhereAmI())
    return err
}

func recoverPanic() {
    if rec := recover(); rec != nil {
        err := rec.(error)
        log.Println(whereami.WhereAmI(), err.Error())

        var l *net.TCPListener
        file, err := l.File()
        if err != nil {
            log.Println(whereami.WhereAmI(), err.Error())
        }

        path := os.Args
        args := []string{"-graceful"}

        cmd := exec.Command(path[0], args...)
        cmd.Stdout = os.Stdout
        cmd.Stderr = os.Stderr
        cmd.ExtraFiles = []*os.File{file}

        err2 := cmd.Start()
        if err2 != nil {
            log.Println(whereami.WhereAmI(), err2.Error())
        } else {
            log.Println(whereami.WhereAmI(), "Restarted...")
        }
    }
}
//structs.go
package main

import (
    "database/sql"
    "net/http"
)

var dbx dbConnection
var config Configs

type FileSystem struct {
    fs http.FileSystem
}

type dbConnection struct {
    conn *sql.DB
}

type Configs struct {
    cookieName     string
    cookieValue    string
    cookieMaxAge   int
    cookieHTTPOnly bool
    cookiePath     string
    domain         string
    port           string
    apiKey         string
    apiVersion     string
    apiPath        string
    protocol       string
    mysqlUser      string
    mysqlPassword  string
    mysqlPort      string
    mysqlHost      string
    mysqlDB        string
    mysqlDriver    string
}

#./Go/Dockerfile
FROM golang:alpine AS builder
ENV GO111MODULE=on
ENV MYSQL_PASSWORD=$(MYSQL_PASSWORD)
ENV MYSQL_USER=$(MYSQL_USER)
ENV MYSQL_DATABASE=$(MYSQL_DATABASE)
ENV MYSQL_PORT=$(MYSQL_PORT)
ENV MYSQL_DRIVER=$(MYSQL_DRIVER)
RUN mkdir /app
ADD . /app/
WORKDIR /app
COPY ./structs.go .
COPY ./handlers.go .
COPY ./server.go .
COPY ./favicon.ico .
COPY ./assets /assets
RUN go mod init stuff.com
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build $(ls -1 *.go)
EXPOSE 9000
CMD ["go", "run", "."]
#./MySQL/Dockerfile
FROM mysql:8.0
ENV MYSQL_PASSWORD=$(MYSQL_PASSWORD)
ENV MYSQL_USER=$(MYSQL_USER)
ENV MYSQL_DATABASE=$(MYSQL_DATABASE)
ENV MYSQL_PORT=$(MYSQL_PORT)
ENV MYSQL_DRIVER=$(MYSQL_DRIVER)
COPY test.sql /docker-entrypoint-initdb.d/test.sql
EXPOSE 3306
#./Mysql/.env
MYSQL_ROOT_PASSWORD=root
MYSQL_PASSWORD=docker
MYSQL_USER=docker
MYSQL_DATABASE=test_db
MYSQL_HOST=127.0.0.1
MYSQL_PORT=3306
MYSQL_DRIVER=mysql
#./Go/.env
MYSQL_ROOT_PASSWORD=root
MYSQL_PASSWORD=docker
MYSQL_USER=docker
MYSQL_DATABASE=test_db
MYSQL_HOST=fullstack-mysql
MYSQL_PORT=3306
MYSQL_DRIVER=mysql

COOKIE_NAME=panda
COOKIE_VALUE=123456987
COOKIE_MAX_AGE=0
COOKIE_PATH=/
COOKIE_HTTP_ONLY=true
DOMAIN=127.0.0.1
PORT=:9000
API_PATH=/api/
API_VERSION=v1
APP_KEY=secret-sauce
PROTOCOL=http://

Вот как я создаю базу данных

CREATE DATABASE IF NOT EXISTS test_db;

CREATE USER IF NOT EXISTS 'root'@'%' IDENTIFIED BY 'root';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;

CREATE USER IF NOT EXISTS 'docker'@'%' IDENTIFIED BY 'docker';
GRANT ALL PRIVILEGES ON *.* TO 'docker'@'%' WITH GRANT OPTION;

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";

CREATE TABLE IF NOT EXISTS `colors` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

Я пробовал использовать: MYSQL_HOST = fullstack- mysql

Код обновлен выше.

Ошибка Ping: наберите tcp 23.195.69.108:3306: connect: соединение отклонено <- MYSQL_HOST = fullstack- mysql</p>

Строка подключения: docker:docker@tcp(fullstack-mysql:3306)/test_db

После изменения строки подключения на:

docker:docker@tcp(db_mysql:3306)/test_db

Ошибка Ping: Ошибка 1044: Отказано в доступе пользователю 'docker' @ '%' к базе данных 'test_db'

Пользователь docker должен иметь все права.

1 Ответ

2 голосов
/ 17 июня 2020

Ваше приложение Go пытается подключиться к MySQL по адресу MYSQL_HOST, значение которого равно 127.0.0.1. Вам нужно установить MYSQL_HOST на имя_контейнера, то есть db_mysql для приложения Go.

После исправления MYSQL_HOST попробуйте следующую строку подключения:

// Connecting string: docker:docker@tcp(db_mysql:3306)/test_db")
connStr:=config.mysqlUser+":"+config.mysqlPassword+"@tcp("+config.mysqlHost+":"+config.mysqlPort+")/"+config.mysqlDB
...