在 Postgres 中使用 Docker 进行 Entity Framework 核心更新的最佳方法是什么?

What is the best way to use Docker for Entity Framework core update with Postgres?

背景

我正在构建一个 API 以使用 dotnet 核心和 EF 核心在 Postgres 数据库中保存用户信息。

我不认为它对以下问题有任何影响,但作为背景说明,我还使用 IdentityServer4 和 Npgsql 包来访问 Postgres。

在本地,一切都非常好,我可以根据需要更新我的模式,并且它都反映在数据库中的正确性。现在我想用这些来制作这个容器,以帮助新的团队成员快速设置。

问题

当我尝试直接从 dotnet API 容器更新架构时出现问题。这是我的 docker 文件:

第一次尝试只有 docker文件

API Docker文件:

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine AS build-env

WORKDIR /app

# Explicitly ask for path to be added
ENV PATH="${PATH}:/root/.dotnet/tools"

RUN dotnet tool install --global dotnet-ef --version 3.1.3

# Copy csproj and restore as distinct layers
COPY *.csproj /app
RUN dotnet restore api.csproj

COPY . /app
RUN dotnet publish api.csproj -c Release -o out

# Run updates
RUN dotnet ef database update -c HelloApiDbContext
RUN dotnet ef database update -c ConfigurationDbContext

# Build runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
COPY --from=build-env /app/out .

ENTRYPOINT ["dotnet", "api.dll"]

Postgres Docker文件:

FROM postgres:12-alpine AS build-env
WORKDIR /app

ENV POSTGRES_USER docker
ENV POSTGRES_PASSWORD docker
ENV POSTGRES_DB docker

# Expose the PostgreSQL port
EXPOSE 5432

# Add VOLUMEs to allow backup of config, logs and databases
VOLUME  ["/etc/postgresql", "/var/log/postgresql", "/var/lib/postgresql"]

# Set the default command to run when starting the container
CMD ["postgres"]

我的默认配置连接字符串也是这样的:

"DefaultConnection": "Server=localhost;Database=docker;Port=32778;User id=docker;Password=docker"

但结果总是:

Build started...
Build succeeded.
Npgsql.NpgsqlException (0x80004005): Exception while connecting
 ---> System.Net.Internals.SocketExceptionFactory+ExtendedSocketException (99): Address not available [::1]:32778
   at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
   at Npgsql.NpgsqlConnector.Connect(NpgsqlTimeout timeout)
   at Npgsql.NpgsqlConnector.Connect(NpgsqlTimeout timeout)
   at Npgsql.NpgsqlConnector.RawOpen(NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
   at Npgsql.NpgsqlConnector.Open(NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
   at Npgsql.NpgsqlConnection.<>c__DisplayClass32_0.<<Open>g__OpenLong|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---

我已经尝试了几种方法。

备注

如果我 运行 从包管理器或我的 Powershell 更新,使用本地 EF,它工作正常。

第二次尝试撰写

我了解到问题来自 Docker 容器的内部 DNS 未得到解决。 我使用了其他方法来 link 两个最有希望的方法是 shell 脚本跟随 this post 像这样:

#!/bin/bash

set -e
run_cmd="dotnet run --server.urls http://*:80"

until dotnet ef database update -c HelloApiDbContext; do
>&2 echo "SQL Server is starting up"
sleep 1
done

>&2 echo "SQL Server is up - executing command"
exec $run_cmd

还有一个 docker-compose 文件:

version: '3.4'

networks: 
  api-dev:
    driver: "bridge"

services: 
  logic-api:
    image: project/api:latest
    depends_on: 
     - "usersdb"
    build:
      context: ./api/
      dockerfile: dockerfile
    ports: 
        - "5000:80"
    networks: 
      - api-dev

  usersdb:
    image: usersdb:latest
    build:
      context: ./users-db/
      dockerfile: dockerfile
    ports: 
      - "32778:5432"
    volumes: 
      - db_volume:/var/lib/postgresql/data
    environment: 
      POSGRES_USER: "docker"
      POSTGRES_PASSWORD : "docker"
      POSGRES_DB: "docker"
    networks: 
      - api-dev
volumes: 
  db_volume:

并更改了 API docker 文件的入口点以确保 Postgres 数据库与 DBeaver

一起运行

在像这样启动更新命令之前:

EXPOSE 80/tcp
RUN chmod +x ./entrypoint.sh
CMD /bin/bash ./entrypoint.sh

我也将默认连接更改为

"DefaultConnection": "Server=usersdb;Database=docker;Port=32778;User id=docker;Password=docker"

所有尝试都失败了,我一直在运行解决这个连接问题。

问题

我在几篇文章中读到,使用 SQL 脚本而不是 EF 自动迁移更容易管理产品中的 SQL 迁移。 我应该放弃从一个容器更新到另一个容器的想法吗?

如果可能的话,我想完全使用 EF。 有没有办法让这个连接以干净的方式工作?

请更新您的连接字符串。

将端口号改回 5432

新连接字符串:

"DefaultConnection": "Server=usersdb;Database=docker;Port=5432;User id=docker;Password=docker"

理由:

API-DEV是私有网络

使用 docker 技巧是了解您所使用的网络。

您的示例中有两个网络:

  • 你的host/localcomputer
  • 第二 API-DEV

API Dev 将继续为 Postgres 使用默认端口 5432。

进一步思考

我在多个地方 read/heard 认为 docker 数据库不是一个好的选择。根据我有限的知识,我建议您使用原生安装的 postgress

Docker-compose 也有一些限制。 Kubernetes 和 YAML 文件解决创建基础设施的方式比 docker-compose 更好。也考虑这些。