无法使用 Docker 从 Golang 上的两个不同服务迁移到一个数据库

问题描述 投票:0回答:1

我在 Docker 内的两个用 Golang 编写的应用程序之间迁移 PostgreSQL 时遇到问题。 仅创建一个表,该表首先通过 Docker 容器迁移。

我使用迁移实用程序。第一个应用程序是“Items”,第二个应用程序是“Order”。在这些应用程序的每个目录中都有“migrations”文件夹。在“Items/migrations”内部分别有001_create_items_up.sql和“down”,在“order/migrations”内部有001_create_order_up.sql。 如果先启动“items”容器,则不会创建“order”表,反之亦然。

001_create_items_up.sql

CREATE TABLE IF NOT EXISTS items (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    price DECIMAL NOT NULL
);

001_create_order_up.sql

CREATE TABLE IF NOT EXISTS orders (
    id SERIAL PRIMARY KEY,
    item_id INT NOT NULL,
    quantity INT DEFAULT 1
);

两个应用程序的 Dockerfile

FROM golang:1.22 as builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o service .
FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/service .
COPY --from=builder /app/migrations /root/migrations
CMD ["./service"]

Docker 组合

version: '3.8'
services:
  postgres:
    image: postgres:13
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: dbname
    ports:
      - "5432:5432"
    volumes:
      - /database:/var/lib/postgresql_data
  items-service:
    build: 
      context: /items
      dockerfile: Dockerfile
    depends_on:
      - postgres
  orders-service:
    build: 
      context: /order
      dockerfile: Dockerfile
    depends_on:
      - postgres

应用程序“items”和“order”的代码

package main

import (
    "log"

    "github.com/golang-migrate/migrate/v4"
    _ "github.com/golang-migrate/migrate/v4/database/postgres"
    _ "github.com/golang-migrate/migrate/v4/source/file"
)

func main() {
    m, err := migrate.New(
        "file://migrations",
        "postgres://user:password@postgres:5432/dbname?sslmode=disable",
    )
    if err != nil {
        log.Fatalf("migration failed to initialize: %v", err)
    }
    if err := m.Up(); err != nil && err != migrate.ErrNoChange {
        log.Fatalf("migration failed: %v", err)
    }
}
postgresql docker go docker-compose migration
1个回答
0
投票

您使用的工具 go-migrate 假设每个数据库都有一个目录。它将数字标识符(递增数字或日期时间)存储在表中以确定数据库的版本,因此它知道要做什么。

如果您使用递增数字(就像您在问题中所做的那样),当您的第二个服务启动时,migrate 会认为所有迁移都已执行。

如果您使用日期时间(正如您根据@DavidMaze的评论尝试的那样),您会发现迁移可能会发现数据库的版本比您的最高版本高

up
,因此,请尝试降级,却发现没有
down
脚本。

解决此问题的方法是使用 x-migrations-table 选项指示 migrate 使用 different 表来跟踪两个不同应用程序的迁移。

所以你的

main
会变成这样:


func main() {
    m, err := migrate.New(
        "file://migrations",
        "postgres://user:password@postgres:5432/dbname?sslmode=disable&x-migrations-table=orders-service-schema",
    )

    // your error handling and what not
}
© www.soinside.com 2019 - 2024. All rights reserved.