Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 385
Owen Pauling Avatar asked May 03 '19 12:05

Owen Pauling


People also ask

How do I enable migrations in Entity Framework Core?

Migrations are enabled by default in EF Core. They are managed by executing commands. If you have Visual Studio, you can use the Package Manager Console (PMC) to manage migrations. Alternatively, you can use a command line tool to execute Entity Framework CLI commands to create a migration.

How do I enable auto migration in .NET Core?

Run the Enable-Migrations –EnableAutomaticMigrations command in Package Manager Console This command has added a Migrations folder to our project. This new folder contains one file: The Configuration class. This class allows you to configure how Migrations behaves for your context.


3 Answers

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();
    }
}
like image 171
Michelh91 Avatar answered Sep 19 '22 19:09

Michelh91


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

public void ApplyMigrations(ApplicationDbContext context) {
    if (context.Database.GetPendingMigrations().Any()) {
        context.Database.Migrate();
    }
}
like image 34
M. Ruiz Avatar answered Sep 20 '22 19:09

M. Ruiz


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.

like image 45
Andrew May Avatar answered Sep 19 '22 19:09

Andrew May