When you are using Entity Framework Core and Oracle, you may want to create an InitContainer for Kubernetes to handle your Database migrations.
Multistage Dockerfile
ARG VERSION=0.1.0
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 8080
ENV ASPNETCORE_URLS=http://+:8080
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
ARG VERSION
ARG configuration=Release
WORKDIR /src
COPY . .
WORKDIR "/src/SOMEPROJECT"
RUN dotnet restore "SOMEPROJECT.csproj"
RUN dotnet build "SOMEPROJECT.csproj" -c $configuration -o /app/build -p:Version=${VERSION}
FROM build as migrationbuilder
ENV PATH $PATH:/root/.dotnet/tools
RUN dotnet tool install --global dotnet-ef
RUN mkdir /migrations
RUN dotnet ef migrations bundle --self-contained -r linux-x64 -o /migrations/migration
RUN cp ./initentrypoint.sh /migrations/initentrypoint.sh
FROM mcr.microsoft.com/dotnet/runtime:7.0 as initcontainer
ENV CONNECTIONSTRING="User Id=ORACLEUSER;Password=ORACLEPASSWORD;Data Source=db:1521/FREEPDB1;"
COPY --from=migrationbuilder /migrations /migrations
COPY --from=migrationbuilder /src/src/AksPoc/appsettings.json /migrations/appsettings.json
RUN chmod 755 /migrations/migration
RUN chmod 755 /migrations/initentrypoint.sh
WORKDIR /migrations
ENTRYPOINT [ "./initentrypoint.sh" ]
FROM build AS publish
ARG configuration=Release
RUN dotnet publish "SOMEPROJECT.csproj" -c $configuration -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "SOMEPROJECT.dll"]
Initscript
#!/bin/bash
./migration --connection "$CONNECTIONSTRING"
How to build the InitContainer
docker build --target initcontainer -t initcontainer:latest .
How to build the application container
docker build -t appcontainer:latest .
How does it work
To build an InitContainer you just need to add 2 new Stages in your DockerFile.
Stage 1 — Migrationbuilder:
This stage is using the .net sdk and installing the dotnet-ef tools to build a migration bundle.
Stage 2 — Initcontainer
This stage holds the code to run your migrations in kubernetes. It can be build by setting the option target in the docker build:
--target initcontainer
When you now run your initcontainer you simply need to set the environment variable “CONNECTIONSTRING” to a valid oracle .net connectionstring.
Good to know:
- Migrationbundles need a valid appsettings.json next to the migration bundle
- You should mount a tnsnames.ora into the container
- You should set the environment variable TNS_ADMIN to point to the folder containing tnsnames.ora
- The initscript is launching the migration with the connectionstring from your environment variable “CONNECTIONSTRING”