mysql - 表“test_db.colors”不存在
问题描述
我正在使用 Docker、docker-compose、MySQL 和 Go 构建一个应用程序。
当我尝试测试一个端点时,我收到错误Table 'test_db.colors' doesn't exist。
似乎 sql 转储没有正确导入。
但是我可以连接数据库,至少没有错误,这是在同一个.sql
文件中创建的。
当我启动应用程序时,终端显示:
golang_app | 2020/06/20 21:48:04 docker:docker@tcp(db_mysql:3306)/test_db
golang_app | 2020/06/20 21:48:04 DB Connected
在我向端点发出请求后,我得到:
2020/06/20 22:05:00 File: handlers.go Function: main.testDBHandler Line: 26 Error 1146: Table 'test_db.colors' doesn't exist
文件结构为:
./
|_app/
|_docker-compose.yml
|_Go/
|_*.go
|_Dockerfile
|_MySQL/
|_Dockerfile
|_.env
|_sql-scripts/
|_test.sql
文件的内容如下所示:
码头工人-compose.yml
version: '3'
services:
fullstack-mysql:
container_name: db_mysql
build:
context: ./MySQL
ports:
- 3306:3306
volumes:
- database_mysql:/var/lib/mysql
- mysql-log:/var/log/mysql
- mysql-conf:/etc/mysql/conf.d
- ./MySQL/sql-scripts:/docker-entrypoint-initdb.d
networks:
- fullstack
app:
container_name: golang_app
env_file:
- ./Go/.env
build:
context: ./Go
ports:
- 9000:9000
restart: unless-stopped
volumes:
- api:/usr/src/app/
depends_on:
- fullstack-mysql
networks:
- fullstack
phpmyadmin:
image: phpmyadmin/phpmyadmin
container_name: phpmyadmin_container
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
- PMA_ARBITRARY=1
ports:
- 9095:80
restart: always
networks:
- fullstack
links:
- fullstack-mysql
volumes:
api:
database_mysql:
mysql-log:
driver: local
mysql-conf:
driver: local
networks:
fullstack:
driver: bridge
应用程序/MySQL/Dockerfile
FROM mysql:8.0
ENV MYSQL_ROOT_PASSWORD=$(MYSQL_ROOT_PASSWORD)
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 ./sql-scripts/test.sql /docker-entrypoint-initdb.d/
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
应用程序/MySQL/sql-scripts/test.sql
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 SELECT, INSERT, UPDATE, DELETE ON *.* TO 'docker'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
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;
INSERT INTO `colors` (`id`, `name`) VALUES
(2, 'black'),
(4, 'blue'),
(5, 'green'),
(3, 'red'),
(1, 'white'),
(6, 'yellow');
main.go
package main
import (
"database/sql"
"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())
}
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
log.Println(connStr)
db, err := sql.Open(config.mysqlDriver, connStr)
if err != nil {
log.Fatal(whereami.WhereAmI(), err.Error())
}
err = db.Ping()
if err != nil {
log.Println("Ping Error: " + err.Error())
} else {
dbx.conn = db
log.Println("DB Connected")
}
//log.Println(fmt.Sprintf("%s", 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...")
}
}
}
处理程序.go
package main
import (
"fmt"
"log"
"net/http"
"github.com/jimlawless/whereami"
)
func testDBHandler(w http.ResponseWriter, req *http.Request) {
id := 1
var name string
if err := dbx.conn.QueryRow("SELECT name FROM colors WHERE id = ? LIMIT 1", id).Scan(&name); err != nil {
log.Println(whereami.WhereAmI(), err.Error())
}
fmt.Fprintf(w, name)
}
解决方案
需要检查的几件事:
- mysql 容器是否表明它已正确启动?
- 您的 mysql 设置是否太复杂(见下文)?
- 您是否尝试过使用另一个应用程序(例如 datagrip 或其他一些 mysql 客户端)连接到您的 mysql 实例?
- 在连接到它之前,您是否确保 mysql 实际上已经完成了它的启动过程?
depends_on
在这里可能无法真正正常工作——其他应用程序在 mysql 启动之前不会启动,但 mysql 不一定会被配置——即你的 test.sql 可能没有实际运行。
您的 mysql 设置似乎有些复杂。有必要吗?我使用了一组类似的技术,我的数据库 docker compose 看起来像这样:
fullstack-mysql:
image: mysql:8.0
ports:
- 3306:3306
volumes:
- database_mysql:/var/lib/mysql
- mysql-log:/var/log/mysql
- mysql-conf:/etc/mysql/conf.d
- ./MySQL/sql-scripts:/docker-entrypoint-initdb.d
environment:
- 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
networks:
- fullstack
假设您不需要做任何复杂的事情,这应该删除大部分 mysql 数据库设置。我做的唯一不同的事情是映射单个启动脚本,而不是整个目录——即
volumes:
./MySQL/sql-scripts/test.sql:/docker-entrypoint-initdb.d/test.sql
虽然我认为您指定的文件夹映射应该可以工作。我刚刚注意到的另一点:在您的 mysql dockerfile 中,您可以这样做:COPY ./sql-scripts/test.sql /docker-entrypoint-initdb.d/
但这对于 docker-compose 文件来说似乎是多余的,它将一个卷放在同一位置。
推荐阅读
- string - 在网格中查找一系列字符以形成字符串(一次向下或向右移动一步)
- windows - 从 Windows 目录中的所有 zip 中删除 __MACOSX 文件夹和 .DS_Store 文件
- node.js - 等待 sequelizer findOne 在返回值之前检查数据库
- java - 没有记录层,我怎样才能只获得 TLS 握手?
- python-3.x - 试图复制一个 kik 用户图像消息!需要建议
- arrays - 如何将文件中的总行数分配给 bash 脚本中数组的大小变量?
- tensorflow - 如何在不上传数据的情况下在谷歌云中训练?
- php - PHP 在从客户端上传到服务器时保留 .jpg 元数据
- java - 如何为继承自抽象类的两个 java 类创建数据库
- c# - 如何替换使用 SqlMembershipProvider 来使用 .NET Standard 2.0