在 Docker 中运行容器时如何创建迁移和数据库架构?
我编写了以下 docker-compose 文件,一切都开始顺利,但是当我尝试访问数据库并在那里搜索实体时,表不在那里。如何在启动容器时创建它们(如果它们不存在)?
别用石头打我,我只是第一天掌握 docker
version: '3.4'
networks:
webapi:
driver: bridge
services:
webapi:
container_name: webapi-dev
image: ${DOCKER_REGISTRY-}webapi
build:
context: .
dockerfile: webapi/Dockerfile
ports:
- "8080:8080"
networks:
- "webapi"
environment:
- ASPNETCORE_ENVIRONMENT=Development
depends_on:
- postgres_db
- redis
- clamav
postgres_db:
container_name: postgres
image: postgres:latest
ports:
- "5432:5432"
networks:
- "webapi"
restart: always
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: 123
POSTGRES_DB: filecryptweb
volumes:
- postgres-data:/var/lib/postgresql/data
redis:
container_name: redis
image: redis:latest
ports:
- "6379:6379"
networks:
- "webapi"
clamav:
container_name: clamav
image: mkodockx/docker-clamav:alpine
environment:
CLAMD_CONF_MaxFileSize: 250M
CLAMD_CONF_MaxScanSize: 250M
CLAMD_CONF_StreamMaxLength: 250M
restart: always
ports:
- "3310:3310"
networks:
- "webapi"
volumes:
postgres-data:
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER app
WORKDIR /app
EXPOSE 8080
EXPOSE 8081
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["webapi/webapi.csproj", "webapi/"]
RUN dotnet restore "./webapi/webapi.csproj"
COPY . .
WORKDIR "/src/webapi"
RUN dotnet build "./webapi.csproj" -c $BUILD_CONFIGURATION -o /app/build
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./webapi.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "webapi.dll"]
2024-03-16 04:10:54 webapi-dev | [21:10:54 INF] { username = , id = , role = } { path = /api/auth/login, method = POST }
2024-03-16 04:10:54 webapi-dev | [21:10:54 INF] Executing endpoint 'webapi.Controllers.Account.AuthSessionController.Login (webapi)'
2024-03-16 04:10:54 webapi-dev | [21:10:54 INF] Route matched with {action = "Login", controller = "AuthSession"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] Login(webapi.DTO.AuthDTO) on controller webapi.Controllers.Account.AuthSessionController (webapi).
2024-03-16 04:10:55 postgres | 2024-03-15 21:10:55.845 UTC [33] ERROR: relation "users" does not exist at character 91
2024-03-16 04:10:55 postgres | 2024-03-15 21:10:55.845 UTC [33] STATEMENT: SELECT u.id, u.email, u.is_2fa_enabled, u.is_blocked, u.password, u.role, u.username
2024-03-16 04:10:55 postgres | FROM users AS u
2024-03-16 04:10:55 postgres | WHERE u.email = $1
2024-03-16 04:10:55 postgres | LIMIT 1
2024-03-16 04:10:55 webapi-dev | [21:10:55 ERR] Failed executing DbCommand (99ms) [Parameters=[@__ToLowerInvariant_0='?'], CommandType='Text', CommandTimeout='30']
2024-03-16 04:10:55 webapi-dev | SELECT u.id, u.email, u.is_2fa_enabled, u.is_blocked, u.password, u.role, u.username
2024-03-16 04:10:55 webapi-dev | FROM users AS u
2024-03-16 04:10:55 webapi-dev | WHERE u.email = @__ToLowerInvariant_0
2024-03-16 04:10:55 webapi-dev | LIMIT 1
2024-03-16 04:10:55 webapi-dev | [21:10:55 ERR] An exception occurred while iterating over the results of a query for context type 'webapi.DB.FileCryptDbContext'.
2024-03-16 04:10:55 webapi-dev | Npgsql.PostgresException (0x80004005): 42P01: relation "users" does not exist
2024-03-16 04:10:55 webapi-dev |
2024-03-16 04:10:55 webapi-dev | POSITION: 91
2024-03-16 04:10:55 webapi-dev | at Npgsql.Internal.NpgsqlConnector.ReadMessageLong(Boolean async, DataRowLoadingMode dataRowLoadingMode, Boolean readingNotifications, Boolean isReadingPrependedMessage)
2024-03-16 04:10:55 webapi-dev | at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
2024-03-16 04:10:55 webapi-dev | at Npgsql.NpgsqlDataReader.NextResult(Boolean async, Boolean isConsuming, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Npgsql.NpgsqlDataReader.NextResult(Boolean async, Boolean isConsuming, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Npgsql.NpgsqlCommand.ExecuteReader(Boolean async, CommandBehavior behavior, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Npgsql.NpgsqlCommand.ExecuteReader(Boolean async, CommandBehavior behavior, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Npgsql.NpgsqlCommand.ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
2024-03-16 04:10:55 webapi-dev | Exception data:
2024-03-16 04:10:55 webapi-dev | Severity: ERROR
2024-03-16 04:10:55 webapi-dev | SqlState: 42P01
2024-03-16 04:10:55 webapi-dev | MessageText: relation "users" does not exist
2024-03-16 04:10:55 webapi-dev | Position: 91
2024-03-16 04:10:55 webapi-dev | File: parse_relation.c
2024-03-16 04:10:55 webapi-dev | Line: 1449
2024-03-16 04:10:55 webapi-dev | Routine: parserOpenTable
2024-03-16 04:10:55 webapi-dev | Npgsql.PostgresException (0x80004005): 42P01: relation "users" does not exist
2024-03-16 04:10:55 webapi-dev |
2024-03-16 04:10:55 webapi-dev | POSITION: 91
2024-03-16 04:10:55 webapi-dev | at Npgsql.Internal.NpgsqlConnector.ReadMessageLong(Boolean async, DataRowLoadingMode dataRowLoadingMode, Boolean readingNotifications, Boolean isReadingPrependedMessage)
2024-03-16 04:10:55 webapi-dev | at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
2024-03-16 04:10:55 webapi-dev | at Npgsql.NpgsqlDataReader.NextResult(Boolean async, Boolean isConsuming, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Npgsql.NpgsqlDataReader.NextResult(Boolean async, Boolean isConsuming, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Npgsql.NpgsqlCommand.ExecuteReader(Boolean async, CommandBehavior behavior, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Npgsql.NpgsqlCommand.ExecuteReader(Boolean async, CommandBehavior behavior, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Npgsql.NpgsqlCommand.ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
2024-03-16 04:10:55 webapi-dev | Exception data:
2024-03-16 04:10:55 webapi-dev | Severity: ERROR
2024-03-16 04:10:55 webapi-dev | SqlState: 42P01
2024-03-16 04:10:55 webapi-dev | MessageText: relation "users" does not exist
2024-03-16 04:10:55 webapi-dev | Position: 91
2024-03-16 04:10:55 webapi-dev | File: parse_relation.c
2024-03-16 04:10:55 webapi-dev | Line: 1449
2024-03-16 04:10:55 webapi-dev | Routine: parserOpenTable
2024-03-16 04:10:55 webapi-dev | [21:10:55 FTL] Npgsql.PostgresException (0x80004005): 42P01: relation "users" does not exist
2024-03-16 04:10:55 webapi-dev |
2024-03-16 04:10:55 webapi-dev | POSITION: 91
2024-03-16 04:10:55 webapi-dev | at Npgsql.Internal.NpgsqlConnector.ReadMessageLong(Boolean async, DataRowLoadingMode dataRowLoadingMode, Boolean readingNotifications, Boolean isReadingPrependedMessage)
2024-03-16 04:10:55 webapi-dev | at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
2024-03-16 04:10:55 webapi-dev | at Npgsql.NpgsqlDataReader.NextResult(Boolean async, Boolean isConsuming, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Npgsql.NpgsqlDataReader.NextResult(Boolean async, Boolean isConsuming, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Npgsql.NpgsqlCommand.ExecuteReader(Boolean async, CommandBehavior behavior, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Npgsql.NpgsqlCommand.ExecuteReader(Boolean async, CommandBehavior behavior, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Npgsql.NpgsqlCommand.ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
2024-03-16 04:10:55 webapi-dev | at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
2024-03-16 04:10:55 webapi-dev | at webapi.DB.Repository`1.GetByFilter(Func`2 queryModifier, CancellationToken cancellationToken) in C:\Users\Stewi\Source\Repos\air2921\FileCryptWeb\webapi\DB\Repository.cs:line 77
2024-03-16 04:10:55 webapi-dev | Exception data:
2024-03-16 04:10:55 webapi-dev | Severity: ERROR
2024-03-16 04:10:55 webapi-dev | SqlState: 42P01
2024-03-16 04:10:55 webapi-dev | MessageText: relation "users" does not exist
2024-03-16 04:10:55 webapi-dev | Position: 91
2024-03-16 04:10:55 webapi-dev | File: parse_relation.c
2024-03-16 04:10:55 webapi-dev | Line: 1449
2024-03-16 04:10:55 webapi-dev | Routine: parserOpenTable
2024-03-16 04:10:56 webapi-dev | [21:10:56 INF] Executing ObjectResult, writing value of type '<>f__AnonymousType0`1[[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]'.
2024-03-16 04:10:56 webapi-dev | [21:10:56 INF] Executed action webapi.Controllers.Account.AuthSessionController.Login (webapi) in 1115.6806ms
2024-03-16 04:10:56 webapi-dev | [21:10:56 INF] Executed endpoint 'webapi.Controllers.Account.AuthSessionController.Login (webapi)'
2024-03-16 04:10:56 webapi-dev | [21:10:56 INF] Status Code: 500
2024-03-16 04:10:56 webapi-dev | [21:10:56 INF] Request finished HTTP/2 POST https://localhost:8081/api/auth/login - 500 null application/json; charset=utf-8 1280.3549ms
事实上,您在 docker-compose 中指定的卷在构建(Dockerfile)以开始迁移时不可见,我认为在运行时使用从命令参数启动的脚本执行此操作是有意义的:docker-撰写
那些。我们写这样的东西:start.sh
删除Dockerfile中对应行
在 docker-compose 中,像这样:
在构建中进行迁移的想法没有意义,因为...... 数据库位于您的卷中,这已经是运行时的一部分,而不是构建的一部分,所以
我再重复一遍 - Docker 文件用于组装“硬件映像”,您将把它放入 docker 存储库中并平等地部署到所有实例,而 docker-compose 是这些容器的运行时编排器的配置,可以这么说,“kubrnetics 幼虫”,即 这个想法是在服务器上旋转的。
您可能还只需要运行一次迁移,在这种情况下,只需选择您如何知道需要启动迁移(例如版本已更改),在容器中构建时放置此标志(例如,作为 db_version 文件),检查版本是否匹配的启动脚本(稍后会看到什么),如果不匹配,则运行迁移并将版本文件的内容放入卷(添加到撰写)中(与此进行比较)
一切都用一行代码解决了。
就我而言,我的 DbContext 类构造函数主体为空:
但是在构造函数主体中添加对我的上下文是否存在数据库的检查后,创建了表: