Starting on a new side-project, I decided to go with the full Azure experience.
AzureDevOps has become a daily tool for me and in addition I always containerize my applications (no more version, OS hell).
The last missing part was deploying my containers to Azure using their
Azure Container Service.
To my surprise it was a bit more difficult than I would have imagined and the Azure Portal UI/UX leaves a lot to be desired in terms of understanding what is happening or is required.
I have the same feeling a lot of times when using Azure Portal, it is very flexible but at the same time very generic.
Hopefully with this article other people won't have to go through the same struggles that I had.
- Containerize your application
- Set up your Azure DevOps
- Set up your Azure Cloud
- Navigate to your app's url :)
Containerize your application
I think this boils down to the individual application and your needs.
However bellow you can find what I usually employ as my dockerfile. (this is a working example but you should use it with considerations).
FROM mcr.microsoft.com/dotnet/nightly/sdk:5.0.100-focal-amd64 AS base WORKDIR /app FROM mcr.microsoft.com/dotnet/nightly/sdk:5.0.100-focal-amd64 AS build COPY ["MyApp/MyApp.csproj", "MyApp/"] COPY ["NuGet.config", "NuGet.config"] RUN dotnet restore --configfile ../NuGet.config "MyApp/MyApp.csproj" COPY . . WORKDIR /Fina FROM build AS publish ARG BUILD_CONFIG RUN dotnet publish "MyApp.csproj" -c $BUILD_CONFIG -o /app/publish RUN dotnet dev-certs https --clean FROM base AS final WORKDIR /app COPY --from=publish /app/publish . EXPOSE 5001 EXPOSE 5000 ENTRYPOINT ["dotnet", "MyApp.dll"]
Set up your Azure DevOps
This step assumes you have a basic knowledge of how to use Azure DevOps and/or other similar tools to set up pipelines.
So Azure DevOps has two distinct features that behave similarly and can be used for the same exact reasons, however the context that they operate in is different. I am talking about "Pipelines" and "Releases".
This separation comes probably from the separation of CI/CD.
Pipelines are part of the Continuous Integration and Releases part of Continuous Delivery.
Pipeline usually takes code, build it, tests and creates an artifact. Release takes the artifact and releases/deploys it.
That however does not mean you cannot do Releases within your pipelines and that is where it becomes confusing and I would leave that to the discretion of the implementer.
The flow is pretty simple, when code is pushed, a build pipeline is initiated which acts as a gatekeeper for the health of the code base.
If all is good a docker image is pushed. For this implementation I used Azure Container Registry but any registry can be used.
After the build pipeline succeeds an automatic trigger creates the new Release using the
Continuous Delivery Trigger on the master branch.
This is very important in case you also want to transfer artifacts from the
Build Pipeline over to the
Release Pipeline can contain different steps, like sending some notifications or webhooks, however the important one is to execute the
Azure App Service Deploy.
You will need to connect your Azure Cloud account to get access to the subscriptions etc.
Important At this point I was confused, but in hindsight it makes a lot of sense, that you can only target an existing
App Service- so head over to Azure and create an App Service with target
Containereither for Windows or Linux.
Configuring the application
The Azure Container service cannot know what port you have exposed on your container/application so by default it looks for Port 80.
There were 2 problems in my case, my App was configured to run on
By default Azure Container Service checks the health of the initiated container by pinging the container on Http:80. You can imagine why this is problematic.
After digging around I found out that if you want to configure the health-check to use a different port it needs to be provided as
App setting with the following Key Value pair
The second issue was that the Container service can only direct towards http (or at least I cannot find how to switch it to https), I tried setting up https redirect but the requests always go to http and thus created an infinite redirect loop.
To counter this, I disabled https redirection on the application.
To save you the trouble, if you believe that the container has not restarted correctly or that the logs seem funky, you might be correct.
Changes don't propagate as fast or even always, especially if
Always On is turned off. Due to the way that the warm up of idle states works, the changes might not happen immediately, I had to enable
Always On to make my changes appear many times. Disclaimer, I am not sure how that affects pricing.
Hopefully this article will help anyone having issues like myself. 🙏