Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
366 lines (280 sloc) 9.3 KB

Deployment

Publishing locally

https://docs.microsoft.com/en-us/aspnet/core/publishing/#publish-to-a-folder

Publishing to Production (Azure App Service)

Publishing using Docker

Prerequisites

Using Visual Studio

Add Docker support to the BackEnd project by right clicking the project file and selecting Add > Docker Support

A new project is added to the solution docker-compose.dcproj containing the following files.

  • .dockerignore
  • docker-compose.yml
  • docker-compose.override.yml

A Dockerfile is also added to the BackEnd project.

FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY ConferencePlanner.sln ./
COPY BackEnd/BackEnd.csproj BackEnd/
COPY ConferenceDTO/ConferenceDTO.csproj ConferenceDTO/
RUN dotnet restore -nowarn:msb3202,nu1503
COPY . .
WORKDIR /src/BackEnd
RUN dotnet build -c Release -o /app

FROM build AS publish
RUN dotnet publish -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "BackEnd.dll"]

Repeat the same step for the FrontEnd project. The Dockerfile is added to the project for it.

FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY ConferencePlanner.sln ./
COPY FrontEnd/FrontEnd.csproj FrontEnd/
COPY ConferenceDTO/ConferenceDTO.csproj ConferenceDTO/
RUN dotnet restore -nowarn:msb3202,nu1503
COPY . .
WORKDIR /src/FrontEnd
RUN dotnet build -c Release -o /app

FROM build AS publish
RUN dotnet publish -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "FrontEnd.dll"]

The docker-compose.yml file is updated to reflect that there are two projects to build images.

version: '3'

services:
  backend:
    image: backend
    build:
      context: .
      dockerfile: BackEnd/Dockerfile

  frontend:
    image: frontend
    build:
      context: .
      dockerfile: FrontEnd/Dockerfile

Linking / Networking

In the previous architecture, there were some setting and manual orchestration to start up and wire the applications together.

  • BackEnd tested for OS type and set the application to use SQL Server or SQLite
  • FrontEnd application had the API url set in the appsetting.json file.
  • BackEnd hard coded the url:port - http://localhost:56009

Using Docker, adding a container for SQL Server and linking the containers in the compose file simplifies this.

Adding SQL Server

Open the docker-compose.yml file and add the following entry. Note the $ is doubled for escaping

  db:
    image: "microsoft/mssql-server-linux"
    environment:
      SA_PASSWORD: "ConferencePlanner1234$$"
      ACCEPT_EULA: "Y

Since the BackEnd application must have connectivity and cannot start until the database container is ready. Add the depends_on entry to the backend definition in the compose file.

  backend:
    image: backend
    build:
      context: .
      dockerfile: BackEnd/Dockerfile
    depends_on:
      - db

Finally, change the connection string for the database in the BackEnd\appsettings.json file.

  "ConnectionStrings": {
    "DefaultConnection": "Server=db;Initial Catalog=ConferencePlanner;User=sa;Password=ConferencePlanner1234$;MultipleActiveResultSets=true"
  }
Linking / Networking FrontEnd & BackEnd

In the docker-compose.yml file, add the links section to the frontend definition. This sets up the host name in the Docker networking allowing for the web application to call the API by name. http://backend

  frontend:
    image: frontend
    build:
      context: .
      dockerfile: FrontEnd/Dockerfile
    links:
      - backend

Change the value for the ServiceUrl in FrontEnd/appsetting.json

{
  "ServiceUrl": "http://backend/",

Remove or comment out the .UseUrls(http://localhost:56009) in BackEnd\Program.cs.

Finally open the docker-compose.override.yml file. Change the ports for the backend entry to 56009:80 and for the frontend, make it 5001:80

version: '3'

services:
  backend:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
    ports:
      - "56009:80"

  frontend:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
    ports:
      - "5001:80"

By changing these values, the API can still be hit via http://localhost:56009, allowing for testing using the swagger UI. The FrontEnd web application will run on http://localhost:5001, however communicates to the API via internal networking hostname backend.

Starting and Debugging

Once the changes are complete, F5 to build start the application in Docker. Debugging is still available in all projects, but now the application is running in containers.

Changes can be made to Razor pages and seen immediately without rebuilds, however and *.cs file changes require rebuilds.

Using VS Code or other editors

Create and ddd the following Dockerfile for the BackEnd application.

FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY ConferencePlanner.sln ./
COPY BackEnd/BackEnd.csproj BackEnd/
COPY ConferenceDTO/ConferenceDTO.csproj ConferenceDTO/
RUN dotnet restore -nowarn:msb3202,nu1503
COPY . .
WORKDIR /src/BackEnd
RUN dotnet build -c Release -o /app

FROM build AS publish
RUN dotnet publish -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "BackEnd.dll"]

Create and ddd the following Dockerfile for the BackEnd application.

FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY ConferencePlanner.sln ./
COPY FrontEnd/FrontEnd.csproj FrontEnd/
COPY ConferenceDTO/ConferenceDTO.csproj ConferenceDTO/
RUN dotnet restore -nowarn:msb3202,nu1503
COPY . .
WORKDIR /src/FrontEnd
RUN dotnet build -c Release -o /app

FROM build AS publish
RUN dotnet publish -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "FrontEnd.dll"]

At the root of the ConferencePlanner solution, add the following docker-compose.yml file.

version: '3'

services:
  backend:
    image: backend
    build:
      context: .
      dockerfile: BackEnd/Dockerfile
    ports:
      - "56009:80"
      - "56001:443"
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
    depends_on:
      - db

  frontend:
    image: frontend
    build:
      context: .
      dockerfile: FrontEnd/Dockerfile
    ports:
      - "5001:80"
      - "5003:443"
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
    links:
      - backend

  db:
    image: "microsoft/mssql-server-linux"
    environment:
      SA_PASSWORD: "ConferencePlanner1234$$"
      ACCEPT_EULA: "Y"

SQL Server Configuration

Change the connection string for the database in the BackEnd\appsettings.json file.

  "ConnectionStrings": {
    "DefaultConnection": "Server=db;Initial Catalog=ConferencePlanner;User=sa;Password=ConferencePlanner1234$;MultipleActiveResultSets=true"
  }

Linking / Networking FrontEnd & Backend

Change the value for the ServiceUrl in FrontEnd/appsetting.json

{
  "ServiceUrl": "http://backend/",

Remove or comment out the .UseUrls(http://localhost:56009) in BackEnd\Program.cs.

Building and Running

  • Build the Docker images docker-compose build
  • Run docker-compose up -d to start the application
  • Run docker-compose down to stop the application

Bonus

Helm Chart

A helm chart is located in /save-points/6-Deployment-docker/helm allowing for deployment to a Kubernetes cluster using helm install ./workshop.

values.yaml

Here values for the service and deployment templates are defined. Docker images and tags should be updated to your repository name in the image and tag fields for each part of the application prior to deplyoyment.

db:
  replicaCount: 1
  name: db
  internalPort: 55555
  externalPort: 55555
  image: microsoft/mssql-server-linux
  tag: latest
  pullPolicy: IfNotPresent
  eula: ACCEPT_EULA
  eulaValue: \Y
  sa: SA_PASSWORD
  saValue: ConferencePlanner1234$
  restart: Always

frontend:
  replicaCount: 1
  name: frontend
  internalPort: 80
  externalPort: 80
  image: frontend
  tag: latest
  environment: Production
  pullPolicy: IfNotPresent
  restart: Always

backend:
  replicaCount: 1
  name: backend
  internalPort: 80
  externalPort: 80
  image: backend
  tag: latest
  environment: Production
  pullPolicy: IfNotPresent
  restart: Always

Next: Session #7 - Challenges | Previous: Session #5 - Add Agenda