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?
Solution 1:
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();
}
}
Solution 2:
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.