【发布时间】:2020-09-19 03:58:18
【问题描述】:
背景
我正在使用 dotnet 核心和 EF 核心构建一个 API 来将用户信息保存在 Postgres 数据库中。
我认为它对以下问题没有任何影响,但作为背景解释,我也在使用 IdentityServer4 和 Npgsql 包进行 Postgres 访问。
在本地,一切正常,我可以根据需要更新我的架构,这一切都反映了数据库中的正确性。现在我想用这些容器制作这些容器,以帮助新团队成员快速设置。
问题
当我尝试直接从 dotnet API 容器更新架构时会出现问题。这是我的 dockerfile:
仅使用 dockerfile 的第一次尝试
API Dockerfile:
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 Dockerfile:
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 ---
我已经尝试了几件事。
注意
如果我使用本地 EF 从包管理器或我的 Powershell 运行更新,它可以正常工作。
第二次尝试撰写
我了解到问题来自 Docker 容器的内部 DNS 未得到解决。 我使用其他方法将两者联系起来,最有希望的方法是 this post 之后的 shell 脚本,如下所示:
#!/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 dockerfile 的入口点以确保 Postgres db 与 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 自动迁移更容易在 prod 中管理 SQL 迁移。 我应该放弃从一个容器更新到另一个容器的想法吗?
如果可能的话,我想完全使用 EF。 有没有办法让这种连接以干净的方式工作?
【问题讨论】:
标签: postgresql docker .net-core entity-framework-core npgsql