简体   繁体   中英

Running EF Core migrations in Heroku

I'm currently developing a prototype in .NET Core and for the sake of simplicity, I went with Docker/Heroku.

What I noticed is that when trying to run the migrations via heroku dotnet run ef database update , the dotnet CLI was not available. I quickly noticed this was due to my final image having only the runtime, not the sdk. The question I have is: what would make the most sense in order to be able to run migrations while at the same time having a lighter image running only the runtime? Am I making to big a deal out of having only the runtime?

This is how my current image is, in order to be able to run the migrations as I currently am:

FROM mcr.microsoft.com/dotnet/core/sdk:3.0
WORKDIR /app
COPY --from=build-env /app/out ./

RUN dotnet tool install --global dotnet-ef

# Set ASPNETCORE_URLS to run the app on the port Heroku exposes.
# Kestrel run by default on 5000/1 and Heroku doesn't allow that.
CMD ASPNETCORE_URLS=http://*:$PORT dotnet Lazarus.dll

It just feels wrong that I have both the SDK and I have to install EF CLI in the production image, so any insight is welcome!

After playing around with different options, the easiest/simplest approach was to run the migrations before the startup of the application hooking into the webhost, in the actual application code.

By creating an extension function such as:

public static IWebHost MigrateDatabase<T>(this IWebHost webHost) where T : DbContext
{
    using(var scope = webHost.Services.CreateScope())
    {
        var services = scope.ServiceProvider;
        try
        {
            var db = services.GetRequiredService<T>();
            db.Database.Migrate();
        }
        catch (Exception ex)
        {
            var logger = services.GetRequiredService<ILogger<Program>>();
            logger.LogError(ex, "An error occurred while migrating the database.");
        }
    }
    return webHost;
}

It can be used in the main entry point as follows:

public static void Main(string[] args)
{
    CreateWebHostBuilder(args)
        .Build()
        .MigrateDatabase<DatabaseContext>()
        .Run();
}

While it does not run the migrations as part of the deployment process, but as part of the startup process, I felt it was much easier and required less moving parts in order to get started. This also allowed shipping a much smaller image which simply contains the runtime and not the SDK along with all the tooling.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM