Azure Container Instances - C# .NET Core apps running as containers in your private Azure Container Registry
Guide to running .NET Core apps as containers in Azure Container Instances. Step by step, from ground to cloud with Tobias Zimmergren!
I've recently discussed a couple of tips and tricks around running Azure Kubernetes Services, running your own C# code as containers and how you can deal with different scenarios when using Kubernetes in the Microsoft cloud - at small scale and big.
Today I had another talk with someone, where they have pretty much the same requirements as would be fitting for AKS, but instead want just a single container, or at most a handful of them. Requirements on no-maintenance, no container-orchestration and no infrastructural decisions to think about - just run the code.
That's the game we're playing today. Tag, you're it.
Build your .NET Core app as a Container image
This step is optional, as I'm sure you've already got a dozen apps lying around just waiting to be containerized and enter the modern world of micro-services and cloud infrastructure.
If you don't have any specific app in mind that you want to bring over, then in this step I'm walking you through creating a simple C# Console app, the steps to build this into a docker image, tag and push it to your Azure Container Registry.
Assumptions
- You already have an Azure Container Registry. If not, just create one.
- You obviously need an Azure subscription.
- You have the Docker tools installed on your machine, so you can run Docker commands.
- You have the Azure CLI installed.
- You have a test Azure Storage Account you want to insert dummy data into.
GitHub source code: https://github.com/Zimmergren/dotnet-core-aci-demo
Build .NET Core Application and push to Azure Container Registry
I've walked through exactly these steps before, but for the sake of clarity in this blog post, I'm elaborating these steps again.
If you're using the code from my GitHub sample, then the following steps should work as-is. If you however are pushing your own apps to your ACR, then you should replace any filenames and contents in the below commands to suit your own code. Great, let's roll.
Build the C# .NET Core project
With the code from my sample, or your own code, you need to make sure to build and publish the binaries.
Run the following command from the project root:
dotnet build && dotnet publish
Build the Dockerfile into a Docker image
From the folder that contains the Dockerfile
, run this and tag it with whatever name you want. Just be sure to remember it, as you'll need it in the sequencing steps:
docker build . -t aci-demo-app
Ensure Admin user is Enabled on ACR
az acr update -n acrdemomagic -g demos --admin-enabled true
This will give you the following output, indicating that the adminUserEnabled
is now set to true. If it were already set to true, it would just keep that value. Also, the -g demos
command specifies the name of the resource group where my ACR is located, which indeed is called just that, demos.
Output of above command:
{
"adminUserEnabled":true,
"creationDate":"2019-02-18T19:37:36.716694+00:00",
"id":"/subscriptions/YOUR_SUBSCRIPTION_GUID/resourceGroups/demos/providers/Microsoft.ContainerRegistry/registries/acrdemomagic",
"location":"westeurope",
"loginServer":"acrdemomagic.azurecr.io",
"name":"acrdemomagic",
"provisioningState":"Succeeded",
"resourceGroup":"demos",
"sku":{
"name":"Basic",
"tier":"Basic"
},
"status":null,
"storageAccount":null,
"tags":{
},
"type":"Microsoft.ContainerRegistry/registries"
}
Get credentials for the Admin user of your Azure Container Registry
In order to know the password of the Admin user of the ACR, you can either check it out in the Azure Portal, or simply run these quick Azure CLI commands to figure it out. The Admin username is the same as your ACR name (in my case acrdemomagic
).
Command to retrieve password from the Azure CLI:
az acr credential show -n acrdemomagic -g demos --query "passwords"
[
{
"name": "password",
"value": "RvHy7+an9u9CAHBUb0tgB=Pkkc7w"
},
{
"name": "password2",
"value": "Racfw4X7BrbMOfZTtJrEiMGhRd="
}
]
Push the Docker image to Azure Container Registry
In order to take the currently built Docker image and send it off to your ACR, you should tag it accordingly, log in to ACR and then push it. Follow my lead, good fellow! You should have the Username and Password already from the previous steps.
Login:
> docker login acrdemomagic.azurecr.io -u acrdemomagic
Password:
Login Succeeded
Tag, and push the Docker image:
docker tag aci-demo-app acrdemomagic.azurecr.io/aci-demo-app:latest
docker push acrdemomagic.azurecr.io/aci-demo-app:latest
If all things are well, you should see the successful push come through:
Verify that the image is indeed in the ACR
Quick check to ensure that the image is where we think we put it:
az acr repository list -n acrdemomagic
[
"aci-demo-app"
]
This enables us to dig into the new repository aci-demo-app
and find out a bit more, should we want to:
az acr repository show -n acrdemomagic --repository aci-demo-app
{
"changeableAttributes": {
"deleteEnabled": true,
"listEnabled": true,
"readEnabled": true,
"writeEnabled": true
},
"createdTime": "2019-02-18T20:44:19.5626376Z",
"imageName": "aci-demo-app",
"lastUpdateTime": "2019-02-18T20:44:19.6306895Z",
"manifestCount": 1,
"registry": "acrdemomagic.azurecr.io",
"tagCount": 1
}
Summary
Great, now we have accomplished the following already:
- Built a C# application in .NET Core 2.x
- Build a Docker image based on said C# application
- Enabled Admin user for the ACR
- Found out the credentials to the ACR
- Tagged and Pushed this Docker image into our ACR
We're ready for the next steps, which is to create an Azure Container Instance, ACI, and see our image in action.
Create an Azure Container Instance with your private Azure Container Registry images
If you've buckled up and prepared for some deep technical magic, I'm sorry to disappoint. There's a lot more of that stuff when managing certain cloud services, but with ACI it's pretty straight forward. A single container instance, running your code with little to no management efforts.
Create an Azure Container Instance with the Azure CLI
For the following steps, you need to have the Username and Password of your ACR at hand. You can enable this using either the Azure CLI, or from the Azure Portal.
To follow suit with the subsequent commands in the Azure CLI, here's how to enable the Admin user if it isn't already, on your Azure Container Registry.
Create the Azure Container Instance from your private image
We have the image in ACR, we have the credentials to connect to it, so now we just need to create our ACI instance. We'll continue to use the Azure CLI for this purpose (single line, I made them multi-line for visual appeal):
az container create
-n my-aci-app
-g demos
--image "acrdemomagic.azurecr.io/aci-demo-app:latest"
--registry-username "acrdemomagic"
--registry-password "YOUR_ACR_PASSWORD"
-e AzureStorageAccountConnectionString="YOUR_STORAGE_CONNECTION_STRING"
{
"containers": [
{
"command": null,
"environmentVariables": [
{
"name": "AzureStorageAccountConnectionString",
"secureValue": null,
"value": "REDACTED_BUT_YOUR_VALUE_WOULD_GO_HERE"
}
],
"image": "acrdemomagic.azurecr.io/aci-demo-app:latest",
"instanceView": {
"currentState": {
"detailStatus": "",
"exitCode": null,
"finishTime": null,
"startTime": "2019-02-18T20:53:37+00:00",
"state": "Running"
},
"events": [
{
"count": 1,
"firstTimestamp": "2019-02-18T20:53:24+00:00",
"lastTimestamp": "2019-02-18T20:53:24+00:00",
"message": "pulling image \"acrdemomagic.azurecr.io/aci-demo-app:latest\"",
"name": "Pulling",
"type": "Normal"
},
{
"count": 1,
"firstTimestamp": "2019-02-18T20:53:33+00:00",
"lastTimestamp": "2019-02-18T20:53:33+00:00",
"message": "Successfully pulled image \"acrdemomagic.azurecr.io/aci-demo-app:latest\"",
"name": "Pulled",
"type": "Normal"
},
{
"count": 1,
"firstTimestamp": "2019-02-18T20:53:37+00:00",
"lastTimestamp": "2019-02-18T20:53:37+00:00",
"message": "Created container",
"name": "Created",
"type": "Normal"
},
{
"count": 1,
"firstTimestamp": "2019-02-18T20:53:37+00:00",
"lastTimestamp": "2019-02-18T20:53:37+00:00",
"message": "Started container",
"name": "Started",
"type": "Normal"
}
],
"previousState": null,
"restartCount": 0
},
"livenessProbe": null,
"name": "my-aci-app",
"ports": [],
"readinessProbe": null,
"resources": {
"limits": null,
"requests": {
"cpu": 1.0,
"memoryInGb": 1.5
}
},
"volumeMounts": null
}
],
"diagnostics": null,
"id": "/subscriptions/YOUR_SUBSCRIPTION_GUID/resourceGroups/demos/providers/Microsoft.ContainerInstance/containerGroups/my-aci-app",
"imageRegistryCredentials": [
{
"password": null,
"server": "acrdemomagic.azurecr.io",
"username": "acrdemomagic"
}
],
"instanceView": {
"events": [],
"state": "Running"
},
"ipAddress": null,
"location": "westeurope",
"name": "my-aci-app",
"osType": "Linux",
"provisioningState": "Succeeded",
"resourceGroup": "demos",
"restartPolicy": "Always",
"tags": {},
"type": "Microsoft.ContainerInstance/containerGroups",
"volumes": null
}
Investigating the json a bit from above, you can follow the instanceView.events
property's collection of events:
Pulling image
Pulled image
Created container
Started container
Alas, it looks like the events were all successful and that this works. But let's make sure, again.
Verify that the Azure Container Instance is running
Verify that the instance is running by using the az container attach
command to attach to the output and error streams:
az container attach -n my-aci-app -g demos
Container 'my-aci-app' is in state 'Running'...
(count: 1) (last timestamp: 2019-02-18 20:53:24+00:00) pulling image "acrdemomagic.azurecr.io/aci-demo-app:latest"
(count: 1) (last timestamp: 2019-02-18 20:53:33+00:00) Successfully pulled image "acrdemomagic.azurecr.io/aci-demo-app:latest"
(count: 1) (last timestamp: 2019-02-18 20:53:37+00:00) Created container
(count: 1) (last timestamp: 2019-02-18 20:53:37+00:00) Started container
Start streaming logs:
MESSAGE: I was processesed at 2019-02-18 21:00:11Z. MACHINE: wk-caas-4fd3ba8c40924964bad21c641ec80c2c-df0ab73db9f91fcad7062a.
MESSAGE: I was processesed at 2019-02-18 21:00:11Z. MACHINE: wk-caas-4fd3ba8c40924964bad21c641ec80c2c-df0ab73db9f91fcad7062a.
MESSAGE: I was processesed at 2019-02-18 21:00:11Z. MACHINE: wk-caas-4fd3ba8c40924964bad21c641ec80c2c-df0ab73db9f91fcad7062a.
MESSAGE: I was processesed at 2019-02-18 21:00:11Z. MACHINE: wk-caas-4fd3ba8c40924964bad21c641ec80c2c-df0ab73db9f91fcad7062a.
MESSAGE: I was processesed at 2019-02-18 21:00:12Z. MACHINE: wk-caas-4fd3ba8c40924964bad21c641ec80c2c-df0ab73db9f91fcad7062a.
MESSAGE: I was processesed at 2019-02-18 21:00:12Z. MACHINE: wk-caas-4fd3ba8c40924964bad21c641ec80c2c-df0ab73db9f91fcad7062a.
The container is running, image pull and creation and start of container was a success - and we can indeed see the log messages from our C# .NET Core application. The machine name reported is the machine name of the ACI.
If we peek into the Azure Storage Explorer to verify that the table indeed has some data, we can also see that it's working on that end:
Delete the Azure Container Instance, to avoid cost for the demo app ;)
Given the number of non-stop transactions we're making in this sample app, it's a wise decision to kill it.
az container delete -n my-aci-app -g demos
Summary
This was fun. We have touched on these topics:
- C# .NET Core apps can easily be containerized
- Build a Docker image out of our C# code
- Enable Admin user for our ACR
- Grab the credentials from the ACR
- Login and Push the Docker image to ACR
- Verified the image does indeed exist in the ACR
- Created an ACI with our new private ACR image
- Verified that the instance is running
- Deleted it again, so we could start this all over ;)
I hope it helps. Please do leave a comment!
Recent comments