15 - Deploy
Deploy
Deploy your ASP.NET Core MVC App into cloud – MS Azure
Several ways how to do it
- Full bare metal server
- Virtual server
- App hosting (azure) (deployable directly from Rider)
- Most standardized way – containers – Docker
Docker
Docker desktop
Download and install docker desktop for your platform (apple m1 is fully supported)
Its free!
When you create a docker image of your app, you need to upload it to somewhere – so hosting can download it from there. Typically, docker hosts do not allow direct uploads! Docker hub is free service to host your public images.
Dockerfile
- Create Dockerfile in solution folder
- It uses two ready-made base images from MS (based on Debian 10)
sdk:6.0
– for building (or :latest)
Full .net core sdkaspnet:6.0
– for running (or :latest)
This image only contains .net core and ASP.NET runtime – its smaller
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /app
# copy csproj and restore as distinct layers
COPY *.sln .
# copy ALL the projects
COPY WebApp/*.csproj ./WebApp/
RUN dotnet restore
# copy everything else and build app
# copy all the projects
COPY WebApp/. ./WebApp/
WORKDIR /app/WebApp
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS runtime
WORKDIR /app
COPY /app/WebApp/out ./
ENTRYPOINT ["dotnet", "WebApp.dll"]
.dockerignore
To keep size even more down and control the bin/obj directory problems - add .dockerignore
**/bin
**/obj
**/out
**/.vscode
**/.vs
.dotnet
.Microsoft.DotNet.ImageBuilder
DB connections strings
Take care of DB strings in image.
- In Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:latest AS runtime
ENV ConnectionStrings:SqlServerConnection="Server=sql.akaver.com,1533;…”
- or set env variables externally when image is starting up
dockerfile full example
FROM mcr.microsoft.com/dotnet/sdk:latest AS build
WORKDIR /app
EXPOSE 80
# copy csproj and restore as distinct layers
COPY *.props .
COPY *.sln .
COPY BLL.App/*.csproj ./BLL.App/
COPY BLL.App.DTO/*.csproj ./BLL.App.DTO/
COPY BLL.Base/*.csproj ./BLL.Base/
COPY Contracts.BLL.App/*.csproj ./Contracts.BLL.App/
COPY Contracts.BLL.Base/*.csproj ./Contracts.BLL.Base/
COPY Contracts.DAL.App/*.csproj ./Contracts.DAL.App/
COPY Contracts.DAL.Base/*.csproj ./Contracts.DAL.Base/
COPY DAL.App.DTO/*.csproj ./DAL.App.DTO/
COPY DAL.App.EF/*.csproj ./DAL.App.EF/
COPY DAL.Base/*.csproj ./DAL.Base/
COPY DAL.Base.EF/*.csproj ./DAL.Base.EF/
COPY Contracts.Domain/*.csproj ./Contracts.Domain/
COPY Domain.App/*.csproj ./Domain.App/
COPY Domain.Base/*.csproj ./Domain.Base/
COPY PublicApi.DTO.v1/*.csproj ./PublicApi.DTO.v1/
COPY Extensions/*.csproj ./Extensions/
COPY WebApp/*.csproj ./WebApp/
RUN dotnet restore
# copy everything else and build app
COPY BLL.App/. ./BLL.App/
COPY BLL.App.DTO/. ./BLL.App.DTO/
COPY BLL.Base/. ./BLL.Base/
COPY Contracts.BLL.App/. ./Contracts.BLL.App/
COPY Contracts.BLL.Base/. ./Contracts.BLL.Base/
COPY Contracts.DAL.App/. ./Contracts.DAL.App/
COPY Contracts.DAL.Base/. ./Contracts.DAL.Base/
COPY DAL.App.DTO/. ./DAL.App.DTO/
COPY DAL.App.EF/. ./DAL.App.EF/
COPY DAL.Base/. ./DAL.Base/
COPY DAL.Base.EF/. ./DAL.Base.EF/
COPY Contracts.Domain/. ./Contracts.Domain/
COPY Domain.App/. ./Domain.App/
COPY Domain.Base/. ./Domain.Base/
COPY PublicApi.DTO.v1/. ./PublicApi.DTO.v1/
COPY Extensions/. ./Extensions/
COPY WebApp/. ./WebApp/
WORKDIR /app/WebApp
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/core/aspnet:latest AS runtime
WORKDIR /app
EXPOSE 80
ENV ConnectionStrings:SqlServerConnection="Server=alpha.akaver.com,1533;User Id=student;Password=Student.Bad.password.0;Database=akaver_sportmap_123;MultipleActiveResultSets=true"
COPY /app/WebApp/out ./
ENTRYPOINT ["dotnet", "WebApp.dll"]
Build image
-
Build your app into docker image
> docker build -t webapp .
-
Run it locally via docker (set envs for db if needed)
> docker run --name webapp_docker --rm -it -p 8000:80 webapp
-p 8000:80
– map port 8000 (local machine) to docker port 80 ---name webapp_docker
– name of instance --it
– interactive (can close down with ctrl-c) ---rm
- clean resources after closing down
Open browser to http://localhost:8000/
Publish image
-
Tag your docker image (needed for publishing)
> docker tag webapp akaver/webapp:test
-
Publish your docker image to registry
> docker login -u [username] -p [password]
> docker push akaver/webapp:test
-
Check your image in Docker Hub
Deploy - Azure
- Create Azure account, (using your TalTech Uni-Id)
- Sadly, no student support currently – or maybe it works for you! (has worked randomly)
- Activate free plan (or pay-as-you-go)
Azure Basics
- Create new resource group - easy to kill everything later in one go
- Instance name – some_website_name.azurewebsites.net
- Publish: Docker image
- Operating system: Linux
- Location: North Europe
- Sku and size: Free F1
Azure Docker
- Options: Single Container
- Image Source: Docker Hub
- Access Type: Public
- Image and tag: [your_repo/your_image:your_tag]
- Create!
- Ca 2 min later
Container update
- Get the webhook url for docker registry – this notifies the Azure when new image is available.
- Deployment Center > Webhook URL
Monitor your app
M1 (Apple silicon)
2023 info
Use arm sdk for build and x86 image for runtime.
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
# copy csproj and restore as distinct layers
COPY *.props .
COPY *.sln .
# copy all the projects from host to image
# Base
COPY BLL.Contracts.Base/*.csproj ./BLL.Contracts.Base/
COPY Contracts.Base/*.csproj ./Contracts.Base/
COPY DAL.Contracts.Base/*.csproj ./DAL.Contracts.Base/
COPY Domain.Contracts.Base/*.csproj ./Domain.Contracts.Base/
COPY BLL.Base/*.csproj ./BLL.Base/
COPY DAL.Base/*.csproj ./DAL.Base/
COPY DAL.EF.Base/*.csproj ./DAL.EF.Base/
COPY Domain.Base/*.csproj ./Domain.Base/
COPY Helpers.Base/*.csproj ./Helpers.Base/
# App
COPY BLL.Contracts.App/*.csproj ./BLL.Contracts.App/
COPY DAL.Contracts.App/*.csproj ./DAL.Contracts.App/
COPY BLL.App/*.csproj ./BLL.App/
COPY BLL.DTO/*.csproj ./BLL.DTO/
COPY DAL.DTO/*.csproj ./DAL.DTO/
COPY DAL.EF.App/*.csproj ./DAL.EF.App/
COPY Domain.App/*.csproj ./Domain.App/
COPY Public.DTO/*.csproj ./Public.DTO/
COPY Resources.App/*.csproj ./Resources.App/
COPY Tests/*.csproj ./Tests/
COPY WebApp/*.csproj ./WebApp/
RUN dotnet restore
# copy everything else and build app
# Base
COPY BLL.Contracts.Base/. ./BLL.Contracts.Base/
COPY Contracts.Base/. ./Contracts.Base/
COPY DAL.Contracts.Base/. ./DAL.Contracts.Base/
COPY Domain.Contracts.Base/. ./Domain.Contracts.Base/
COPY BLL.Base/. ./BLL.Base/
COPY DAL.Base/. ./DAL.Base/
COPY DAL.EF.Base/. ./DAL.EF.Base/
COPY Domain.Base/. ./Domain.Base/
COPY Helpers.Base/. ./Helpers.Base/
# App
COPY BLL.Contracts.App/. ./BLL.Contracts.App/
COPY DAL.Contracts.App/. ./DAL.Contracts.App/
COPY BLL.App/. ./BLL.App/
COPY BLL.DTO/. ./BLL.DTO/
COPY DAL.DTO/. ./DAL.DTO/
COPY DAL.EF.App/. ./DAL.EF.App/
COPY Domain.App/. ./Domain.App/
COPY Public.DTO/. ./Public.DTO/
COPY Resources.App/. ./Resources.App/
COPY Tests/. ./Tests/
COPY WebApp/. ./WebApp/
WORKDIR /src/WebApp
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/aspnet:7.0-bullseye-slim-amd64 AS runtime
WORKDIR /app
EXPOSE 80
COPY --from=build /src/WebApp/out ./
ENTRYPOINT ["dotnet", "WebApp.dll"]
Build x86 image, retag, push -> configure azure
docker buildx build --progress=plain -t webapp:latest .
docker tag webapp akaver/aw-struct-train-dist-22-23s-app:latest
docker push akaver/aw-struct-train-dist-22-23s-app:latest
Configure env settings
-- ConnectionStrings__DefaultConnection
-- Host=dist2223db.postgres.database.azure.com;Database=aw-train;Username=postgres;Password=Foo.bar.1