Toggle navigation
首页
技术
骑行
羽毛球
资讯
联络我
登录
asp.net core mvc集成CI-CD时,update-database的时机选择
2018-03-28
.NET Core
Docker
> 使用 docker 来部署 ASP.NET CORE MVC,在部署到正式环境的时候,如何根据 migrations 更新数据库,是一个需要仔细考虑的问题。 方法大致有3个: 1. 直接使用 aspnetcore-build 镜像来构建项目、更新数据库、运行项目,参考:[Compose and ASP.NET Core with SQL Server](https://docs.docker.com/compose/aspnet-mssql-compose/) 2. 通过命令将 migrations 导出为通用 sql script,然后通过脚本更新 database,参考:[How to best run Database Migrations](https://github.com/dotnet/dotnet-docker-samples/issues/89) 3. 在 MVC app 中更新 database,参考:[Razor Pages with EF Core in ASP.NET Core - Migrations](https://docs.microsoft.com/en-us/aspnet/core/data/ef-rp/migrations) # 该如何选择呢? ## 直接使用 aspnetcore-build 镜像 Dockerfile如下: ```dockerfile FROM microsoft/aspnetcore-build:lts COPY . /app WORKDIR /app RUN ["dotnet", "restore"] RUN ["dotnet", "build"] EXPOSE 80/tcp RUN chmod +x ./entrypoint.sh CMD /bin/bash ./entrypoint.sh ``` entrypoint.sh 脚本如下: ```bash #!/bin/bash set -e run_cmd="dotnet run --server.urls http://*:80" until dotnet ef database update; do >&2 echo "SQL Server is starting up" sleep 1 done >&2 echo "SQL Server is up - executing command" exec $run_cmd ``` 可以看到,这种方法虽然可以达到效果,但是有两个问题: 1. 集群部署时,每个单独的app都会执行 database update,可能会带来冲突 2. 使用 aspnetcore-build 镜像,使得最终运行环境镜像浪费大量硬盘空间。 aspnetcore-build 和 aspnetcore 镜像大小对比: > https://hub.docker.com/r/microsoft/aspnetcore/tags/ > https://hub.docker.com/r/microsoft/aspnetcore-build/tags/ 微软官网提醒内容: > We recommend production apps should not call Database.Migrate at application startup. Migrate shouldn't be called from an app in server farm. For example, if the app has been cloud deployed with scale-out (multiple instances of the app are running). > Database migration should be done as part of deployment, and in a controlled way. Production database migration approaches include: > * Using migrations to create SQL scripts and using the SQL scripts in deployment. > * Running dotnet ef database update from a controlled environment. ## 导出为通用 sql script 在github上有人也问道,最好的更新数据库的方式是什么,最后他的解决方案是,通过命令将 migrations 导出为通用 sql script,然后用sql command更新数据库。 命令如下: dotnet ef migrations script -o migrate.sql --idempotent 这种方法可以达到效果,且符合微软官网推荐,但是在实际的执行过程中,有如下问题: * 更新数据库的sql command,不同的 database 不同。 * 需要为sql command额外维护一套 db connection 还是不太理想。 ## 在 MVC app 中更新 database 有没有办法解决上面方法遇到的问题呢? * 不用研究不同的database需要如何执行sql command来导入数据 * 不用额外维护一套 db connection 有,如果可以在部署的时候,让 mvc app 运行一次,专门并更新数据库,完成之后退出,则可以完美解决。 步骤如下: 1. 修改 mvc app 可以读取 arguments,如果收到 updata dabase 命令,则专门更新数据库 Program.cs ```c# public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config)=>{ config.AddCommandLine(args); }) ``` Startup.cs ```c# public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifetime, DbContext dbContext) { if (Configuration["updatedb"] == "true") { dbContext.Database.Migrate(); appLifetime.StopApplication(); } } ``` 2. 建立一个 update database 的yml文件: docker-compose.updatedb.yml ``` version: '3' services: web: entrypoint: - dotnet - mvc.dll - --updatedb - 'true' ``` 3. 建立 update database 的 script: ```bash #!/bin/bash update_db_check_container_name="_mvc_" echo "update database" docker-compose \ -f docker-compose.yml \ -f docker-compose.development.yml \ -f docker-compose.postgres.yml \ -f docker-compose.updatedb.yml \ up -d # wait for database update while [ "$(docker ps --quiet --filter name=$update_db_check_container_name)" ] do echo "wait for update database" sleep 1 done ```
×
本文为博主原创,如需转载,请注明出处:
http://www.supperxin.com
返回博客列表