Posted on Leave a comment

Containerize a .NET app with Docker and vs code

When you build your application with cloud native technologies you will build microservices on containers instead of monolithic applications. We will now examine how easy is to build a .NET application in a container and run this application on your local machine.

First we will need to create the visual studio solution. I will go through that with visual studio IDE and then I will use vs code. For my microservice I am using a ASP .NET Core web api with default code.

The target framework for the solution will be the latest .NET framework which is version 7. All other settings will be set to defaults.

When you run the app locally with IIsExpress you will be able to access the swagger interface through the port which you defined in the launchSettings.json. 

https://localhost:7057/swagger/index.html

This file can be located under Properties and there you can configure on which port the application will run. In the profiles section under https settings, you can find the default application URL and port. This will be needed in later steps.

Microsoft provides the below documentation in order to create a containerized application that runs on .NET

Build and run an ASP.NET Core app in a container
In this guide you will learn how to: Create a Dockerfile file describing a simple .NET Core service container. Build…code.visualstudio.com

In order to create a microservice based on our vs solution we will need a dockerfile. This can be created automatically with vs code.

In vs code command dialog search for docker add and select docker compose files to workspace.

Then select asp net core.

and after that your operating system. The next step will be to select the exposed port, or otherwise under which port your application will run. There we should provide the port that we found under our launchSettings.json or the one that we configured manually. In my case I will select the default one for the solution which was 7057.

When a popup window appears on the screen you should select add Dockerfile and automatically the build files will be generated.

Dockerfile

Based on my setup I altered two things in the generated Dockerfile. The first thing will be to change configuration to Debug instead of Release. For production environments you will consider using the release build directive. The second thing will be to add an environmental variable ASPNETCORE_ENVIRONMENT inside the container with the value Development.

FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 7057

ENV ASPNETCORE_URLS=http://*:7057
ENV ASPNETCORE_ENVIRONMENT=Development

FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["AspNetWebApi.csproj", "./"]
RUN dotnet restore "AspNetWebApi.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "AspNetWebApi.csproj" -c Debug -o /app/build

FROM build AS publish
RUN dotnet publish "AspNetWebApi.csproj" -c Debug -o /app/publish /p:UseAppHost=false

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

docker build command

after the build is completed and the image is created you can run a new container locally.

Keep in mind that in order to test your container you should create a port forward from the container to your host. I used the same port for the host so I added the -p 7057:7057

The logs of the container indicate a successful run of the application.

Our application now runs as a microservice container inside the host machine (my laptop). 

We can verify the access to our application using the URL with the swagger.

Youtube video:

Posted on 1 Comment

Install python silently on Windows container and add to PATH

A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another.

In this article we will examine how we can silently install python on a container running windows and add it to path. By doing so we can run python scripts inside our container and perform various tests, or even create webservices that will be hosted as containers inside a Cloud provider.

In order to host python inside a windows system I am using the below Dockerfile. A file named configuration.ps1 could exist inside your building directory and contain other instructions like modules installation. If you do not want this step you can remove the last two lines of the Dockerfile.

FROM mcr.microsoft.com/dotnet/framework/sdk:4.8-windowsservercore-ltsc2019
 RUN Invoke-WebRequest -UseBasicParsing https://www.python.org/ftp/python/3.10.7/python-3.10.7-amd64.exe -OutFile python.exe; `
    Start-Process python.exe -Wait -ArgumentList /PrependPath=1, /quiet; `
    Remove-Item -Force python.exe
COPY ./configuration.ps1 .
CMD .\configuration.ps1

When python is installed inside your container you will need to add it on PATH in order to use the verb python. This is done by appending the installation directory on windows PATH.

In order to do you will need to get an interactive session with your container.

docker exec -it container_name powershell

With the below command you can find where is the python installation located. You will need to change python version to the one that you installed. If you had installed the version 3.5 then you would need to change 3.10 to 3.5.

py -3.10 -c "import sys; print(sys.executable[:-10])"

The last step would be to set this location in the PATH. You can do that using the command below.

setx path "%path%;C:\Users\ContainerAdministrator\AppData\Local\Programs\Python\Python310\"

Then you can just press python and voilà.

Posted on Leave a comment

Push multiple docker container images using a loop – Azure DevOps

On a pipeline that I was creating I wanted to push multiple docker images on an Azure container registry based on a list. In order to do that I used the docker@2 task on a loop providing the images that I had to push as a parameter. Code is attached below.

trigger:
– none
pr: none
parameters:
– name: containerlist
type: object
default: ["core/image1","core/image2","core/image3","core/image4"]
– name: DockerPushID
type: string
pool:
name: demo-app
stages:
– stage: containers
displayName: Push containers to container registry $(registry)
jobs:
– job: pushcontainers
displayName: Push containers on testexample.azurecr.io
steps:
– checkout: none
– ${{ each container in parameters.containerlist }}:
– task: Docker@2
displayName: pushing image ${{container}}
inputs:
containerRegistry: 'registryconnection'
repository: '${{container}}'
command: 'push'
tags: |
current-${{parameters.DockerPushID}}
current-latest

This task will run steps based on the images you provide on the parameters list. An important note is that you need to have the image named accordingly in order to get a successful result. For example if you need to push on geralexgr.azurecr.io you will need to have your images named as below.

geralexgr.azurecr.io/image1:current-latest
geralexgr.azurecr.io/image2:current-latest

Else you may notice some failures indicating the below.

The push refers to repository [***/kati/image1] 
An image does not exist locally with the tag: ***/kati/image1

A successful run of the pipeline.

Additional information regarding loops and expressions on Azure DevOps pipelines:

https://docs.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops#functions

Video tutorial on YouTube: