简体   繁体   中英

Apply Entity Framework migrations when using ASP.Net Core in a Docker image

I have an ASP.Net Core application which uses Entity Framework with Sqlite. I am building a Docker image to deploy this.

The ASP.Net Core application runs fine when debugging with VS Code, but when running in a Docker container I receive an error:

SqliteException: SQLite Error 1: 'no such table: MyTable'.

I figured this is because I need to run the Entity Framework migrations when I build the Docker image. I have added dotnet ef database update to my Dockerfile, which looks like:

FROM microsoft/dotnet:sdk AS build-env
WORKDIR /app

COPY *.csproj ./
RUN dotnet restore

COPY . ./
RUN dotnet publish -c Release -o out

RUN dotnet ef database update

FROM microsoft/dotnet:aspnetcore-runtime
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "MyApplication.dll"]

The image builds without errors. However, when I create a container and look at the database, it is empty with no tables.

What is the correct way to set up a database with Entity Framework when building a Docker image?

Regardless of your deployment type, you can Apply migrations at runtime on your Startup class at the very end of your Configure method, eg calling the following method:

public void ApplyMigrations(ApplicationDbContext context) {
    if (context.Database.GetPendingMigrations().Any()) {
        context.Database.Migrate();
    }
}

A couple of things:

1) A RUN command in a Dockerfile is an instruction executed during the build of the container image - so it will run once (and probably fail because there's no database) where you are building the image rather than when you later run the image.

2) I would recommend separating performing migrations from the deployment of a new version of your container. You may only be running a single copy of the container at the moment, but if you ever ran 2 or more then you would have multiple containers all checking to see if they should run migrations and that could cause issues. There's also the problem that you have deployed code that depends upon the migration, but you don't yet know that the migration will work - better to run the migrations first, and if they fail, don't deploy the new container.

For anyone on .net 6 I used this to apply migrations at startup just before app.Run() in Program.cs file

using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;

    var context = services.GetRequiredService<ApplicationDbContext>();
    if (context.Database.GetPendingMigrations().Any())
    {
        context.Database.Migrate();
    }
}

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