如何使用Go和Docker等待PostgreSQL数据库?

huangapple go评论125阅读模式
英文:

How to wait postgres db using go with docker?

问题

我使用docker-compose部署了一个使用gorm和postgres的Go应用程序。

我通过另一个容器服务进行了数据库创建和数据迁移。这里只列出了应用程序和数据库容器的问题。

docker-compose.yml

  1. app:
  2. build: ./app
  3. command: ["/bin/wait-for-it.sh", "db:5432", "--", "/bin/main"]
  4. volumes:
  5. - ./app/:/app/
  6. ports:
  7. - 8080:8080
  8. environment:
  9. - DB_USER=postgres
  10. - DB_NAME=mydb
  11. - DB_PASS=password
  12. depends_on:
  13. - db
  14. links:
  15. - db
  16. db:
  17. image: postgres:13-alpine
  18. environment:
  19. - POSTGRES_PASSWORD=password
  20. - POSTGRES_DB=mydb

Dockerfile

  1. FROM golang:1.16.3-alpine3.13 AS builder
  2. WORKDIR /app
  3. COPY . .
  4. RUN CGO_ENABLED=0 GOOS=linux go build -o main
  5. FROM alpine:3.13
  6. RUN apk update && apk --no-cache add bash
  7. COPY --from=builder /app /bin/.
  8. RUN ["chmod", "+x", "/bin/wait-for-it.sh"]

db/db.go

  1. package db
  2. import (
  3. "fmt"
  4. "os"
  5. "gorm.io/driver/postgres"
  6. "gorm.io/gorm"
  7. )
  8. var (
  9. db *gorm.DB
  10. )
  11. func Init() {
  12. conn := fmt.Sprintf("host=db port=5432 user=%s password=%s dbname=%s sslmode=disable", os.Getenv("DB_USER"), os.Getenv("DB_PASS"), os.Getenv("DB_NAME"))
  13. _, err := gorm.Open(postgres.Open(conn), &gorm.Config{})
  14. if err != nil {
  15. panic(err)
  16. }
  17. }
  18. func GetDB() *gorm.DB {
  19. return db
  20. }

models/post.go

  1. package models
  2. type Post struct {
  3. ID int `json:"id" gorm:"primary_key"`
  4. Title string `json:"title"`
  5. Body string `json:"body"`
  6. }

main.go

  1. 1 package main
  2. 2
  3. 3 import (
  4. 4 "app/db"
  5. 5 "app/models"
  6. 6 "fmt"
  7. 7 )
  8. 8
  9. 9 func main() {
  10. 10 db.Init()
  11. 11
  12. 12 db := db.GetDB()
  13. 13
  14. 14 var posts []models.Post
  15. 15 db.Find(&posts)
  16. 16 fmt.Println(posts)
  17. 17 }

在构建docker-compose时,它首先尝试连接数据库,但似乎数据库尚未可达。即使添加了wait-for-it,也无法解决问题。

  1. app_1 | wait-for-it.sh: waiting 15 seconds for db:5432
  2. db_1 |
  3. db_1 | PostgreSQL Database directory appears to contain a database; Skipping initialization
  4. db_1 |
  5. app_1 | wait-for-it.sh: db:5432 is available after 0 seconds
  6. db_1 | 2021-06-02 03:53:03.731 UTC [1] LOG: starting PostgreSQL 13.2 on x86_64-pc-linux-musl, compiled by gcc (Alpine 10.2.1_pre1) 10.2.1 20201203, 64-bit
  7. db_1 | 2021-06-02 03:53:03.731 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
  8. app_1 | panic: runtime error: invalid memory address or nil pointer dereference
  9. app_1 | [signal SIGSEGV: segmentation violation code=0x1 addr=0x28 pc=0x59c446]
  10. app_1 |
  11. app_1 | goroutine 1 [running]:
  12. app_1 | gorm.io/gorm.(*DB).getInstance(0x0, 0xc000026038)
  13. app_1 | /go/pkg/mod/gorm.io/gorm@v1.21.10/gorm.go:355 +0x26
  14. app_1 | gorm.io/gorm.(*DB).Find(0x0, 0x868220, 0xc00000c018, 0x0, 0x0, 0x0, 0xc000094058)
  15. app_1 | /go/pkg/mod/gorm.io/gorm@v1.21.10/finisher_api.go:159 +0x2f
  16. app_1 | main.main()
  17. app_1 | /app/main.go:15 +0x7f
  18. db_1 | 2021-06-02 03:53:03.731 UTC [1] LOG: listening on IPv6 address "::", port 5432
  19. db_1 | 2021-06-02 03:53:03.734 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
  20. db_1 | 2021-06-02 03:53:03.741 UTC [22] LOG: database system was shut down at 2021-06-02 03:52:34 UTC
  21. db_1 | 2021-06-02 03:53:03.747 UTC [1] LOG: database system is ready to accept connections
  22. myapp_app_1 exited with code 2

如何正确设置?

/app/main.go:15有什么问题吗?它应该正常工作并获取数据。

英文:

I deployed a go with gorm app using postgres by docker-compose.

I did db creation and data migration by an another container service. Here only listed the app and db container issues.

docker-compose.yml

  1. app:
  2. build: ./app
  3. command: ["/bin/wait-for-it.sh", "db:5432", "--", "/bin/main"]
  4. volumes:
  5. - ./app/:/app/
  6. ports:
  7. - 8080:8080
  8. environment:
  9. - DB_USER=postgres
  10. - DB_NAME=mydb
  11. - DB_PASS=password
  12. depends_on:
  13. - db
  14. links:
  15. - db
  16. db:
  17. image: postgres:13-alpine
  18. environment:
  19. - POSTGRES_PASSWORD=password
  20. - POSTGRES_DB=mydb

Dockerfile

  1. FROM golang:1.16.3-alpine3.13 AS builder
  2. WORKDIR /app
  3. COPY . .
  4. RUN CGO_ENABLED=0 GOOS=linux go build -o main
  5. FROM alpine:3.13
  6. RUN apk update && apk --no-cache add bash
  7. COPY --from=builder /app /bin/.
  8. RUN ["chmod", "+x", "/bin/wait-for-it.sh"]

db/db.go

  1. package db
  2. import (
  3. "fmt"
  4. "os"
  5. "gorm.io/driver/postgres"
  6. "gorm.io/gorm"
  7. )
  8. var (
  9. db *gorm.DB
  10. )
  11. func Init() {
  12. conn := fmt.Sprintf("host=db port=5432 user=%s password=%s dbname=%s sslmode=disable", os.Getenv("DB_USER"), os.Getenv("DB_PASS"), os.Getenv("DB_NAME"))
  13. _, err := gorm.Open(postgres.Open(conn), &gorm.Config{})
  14. if err != nil {
  15. panic(err)
  16. }
  17. }
  18. func GetDB() *gorm.DB {
  19. return db
  20. }

models/post.go

  1. package models
  2. type Post struct {
  3. ID int `json:"id" gorm:"primary_key"`
  4. Title string `json:"title"`
  5. Body string `json:"body"`
  6. }

main.go

  1. 1 package main
  2. 2
  3. 3 import (
  4. 4 "app/db"
  5. 5 "app/models"
  6. 6 "fmt"
  7. 7 )
  8. 8
  9. 9 func main() {
  10. 10 db.Init()
  11. 11
  12. 12 db := db.GetDB()
  13. 13
  14. 14 var posts []models.Post
  15. 15 db.Find(&posts)
  16. 16 fmt.Println(posts)
  17. 17 }

When start to build docker-compose, it tried to connect db first, but it seems that db didn't become reachable yet. Even added wait-for-it doesn't work.

  1. app_1 | wait-for-it.sh: waiting 15 seconds for db:5432
  2. db_1 |
  3. db_1 | PostgreSQL Database directory appears to contain a database; Skipping initialization
  4. db_1 |
  5. app_1 | wait-for-it.sh: db:5432 is available after 0 seconds
  6. db_1 | 2021-06-02 03:53:03.731 UTC [1] LOG: starting PostgreSQL 13.2 on x86_64-pc-linux-musl, compiled by gcc (Alpine 10.2.1_pre1) 10.2.1 20201203, 64-bit
  7. db_1 | 2021-06-02 03:53:03.731 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
  8. app_1 | panic: runtime error: invalid memory address or nil pointer dereference
  9. app_1 | [signal SIGSEGV: segmentation violation code=0x1 addr=0x28 pc=0x59c446]
  10. app_1 |
  11. app_1 | goroutine 1 [running]:
  12. app_1 | gorm.io/gorm.(*DB).getInstance(0x0, 0xc000026038)
  13. app_1 | /go/pkg/mod/gorm.io/gorm@v1.21.10/gorm.go:355 +0x26
  14. app_1 | gorm.io/gorm.(*DB).Find(0x0, 0x868220, 0xc00000c018, 0x0, 0x0, 0x0, 0xc000094058)
  15. app_1 | /go/pkg/mod/gorm.io/gorm@v1.21.10/finisher_api.go:159 +0x2f
  16. app_1 | main.main()
  17. app_1 | /app/main.go:15 +0x7f
  18. db_1 | 2021-06-02 03:53:03.731 UTC [1] LOG: listening on IPv6 address "::", port 5432
  19. db_1 | 2021-06-02 03:53:03.734 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
  20. db_1 | 2021-06-02 03:53:03.741 UTC [22] LOG: database system was shut down at 2021-06-02 03:52:34 UTC
  21. db_1 | 2021-06-02 03:53:03.747 UTC [1] LOG: database system is ready to accept connections
  22. myapp_app_1 exited with code 2

How to set it correctly?

Does /app/main.go:15 anything incorrect? It should work and get data normally.

答案1

得分: 1

你需要在你的命令中添加等待时间:

  1. 命令: ["/bin/wait-for-it.sh", "db:5432", "-t", "600000000", "--", "/bin/main"]

这里的时间是等待的最长时间,当数据库启动并运行时,应用程序/bin/main将立即执行。

当你不使用-t参数运行时,默认等待时间为15秒。

更多信息请参考这里

英文:

you need to add the Time for waiting in your command:

  1. command: ["/bin/wait-for-it.sh", "db:5432", "-t", "600000000", "--", "/bin/main"]

the time is here the maximun time for waiting, the app /bin/main will be excuted as soon the DB is up and running.

when you run without -t the default is 15 seconds

more info Here

huangapple
  • 本文由 发表于 2021年6月2日 13:44:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/67799504.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定