What we started with
When we first started developing the MFI Core application, we followed most of the Microsoft documentation on deploying a Docker image to an Azure App Service. It worked and was fine, but we have a small IT team and are always seeking to reduce complexity whenever possible.
Shout out to the Nonprofit Team1 at GitHub for the free organization membership.
Here is what our process looked like when we first had everything wired up:
|Publish Build||Azure DevOps||Github integration|
|Store Image||Azure Container Registry||Push from build pipeline|
|Trigger Release||Azure DevOps||Successful build|
|Pull Image from ACR||Azure App Service||Integration with Azure DevOps Release|
This worked, but we had to bounce between Github, Azure DevOps, and Azure portal to check the progress of the image and the final deployment.
Cutting out Azure DevOps
Our first step for reducing complexity was to remove the Azure DevOps release pipeline and call an App Service webhook2 from the Azure Container Registry that would send a request to the App Service to let it know a new build was available with the appropriate tag. This was wonderful because our release pipeline really wasn’t doing much. However, it now seemed a little silly to have to log into the DevOps portal just to maintain a build pipeline. So we started to investigate GitHub actions for building and pushing the images to ACR.
Having little experience with using GitHub actions, I was impressed by how easy it was. We just included a
main.yaml file in
/.github/workflows/ of our project and GitHub handled the rest. To start out we were using the example from the Azure team found here: https://github.com/Azure/docker-login.
1 2 3 4 5 6 7 8 9 10 ### snippet for building and pushing - uses: azure/docker-login@v1 with: login-server: contoso.azurecr.io username: $ password: $ - run: | docker build . -t contoso.azurecr.io/k8sdemo:$ docker push contoso.azurecr.io/k8sdemo:$
To get this to work properly, you need to get your username and password from ACR and store them as secrets in your GitHub repository under
With this change, we has now cut out the need for Azure DevOps.
|Publish Build||Github||Github Action|
|Store Image||Azure Container Registry||Push from GitHub Action|
|Pull Image from ACR||Azure App Service||Webhook call from ACR|
Cutting out Azure Container Registry
While investigating GitHub actions, we came across this template: github.com/actions/starter-workflows/blob/master/ci/docker-push.yml. This template was created to build and push Docker images to GitHub’s Package service. Similar to GitHub Actions, we had no exposure to GitHub Packages. We had seen the product announcement from GitHub but had no reason to dig any deeper. Luckily, modifying our GitHub action was a simple as switching out some YAML, so we gave this starter template a shot.
One thing we instantly liked was being able to remove the ACR secrets from our repository. The template uses a token generated at runtime by GitHub called
GITHUB_TOKEN to authenticate against the package repository. You’ll see shortly that this is just a temporary win, we will eventually need the App Service credentials in our webhook call to deploy the package.
NOTE: We did run into issues with the
GITHUB_TOKENafter a few days. It seemed like the auto-generated token lost permission scope or something, so we had to create a personal access token with the correct permissions until GitHub fixed it. Issue: denied: Resource not accessible by integration 3
main.yml ended up looking like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 name: Docker on: push: branches: - master tags: - v* env: IMAGE_NAME: mficore jobs: push: runs-on: ubuntu-latest if: github.event_name == 'push' steps: - uses: actions/checkout@v2 - name: Build image run: docker build . --file Dockerfile --tag image - name: Log into registry run: echo "$" | docker login docker.pkg.github.com -u $ --password-stdin - name: Push image run: | IMAGE_ID=docker.pkg.github.com/$/$IMAGE_NAME # Strip git ref prefix from version VERSION=$(echo "$" | sed -e 's,.*/\(.*\),\1,') # Strip "v" prefix from tag name [[ "$" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//') # Use Docker `latest` tag convention [ "$VERSION" == "master" ] && VERSION=latest echo IMAGE_ID=$IMAGE_ID echo VERSION=$VERSION docker tag image $IMAGE_ID:$VERSION docker push $IMAGE_ID:$VERSION
Once the action completed, we were able to see the package in our repo and also pull it down and run it locally.
Everything seemed easy breezy, but you could tell that GitHub Packages and Actions still have some kinks to be ironed out. As I mentioned above, we ran into an issue with the authentication token for our package repo. It also seems like we have no way of deleting old versions or packages, which we are still investigting. Despite these hiccups, we were happy enough with the way everything worked to set up a webhook call from GitHub and cut out ACR. Being a small nonprofit, it is always nice to save the money on our Azure for Nonprofits4 grant for running applications.
To configure your Azure App Service webhook endpoint, you need to go to the
Container settings section of your App Service and select the
Private Registry tab.
Server URLsould be
Loginshould be your GitHub account
Passwordwould be a GitHub Personal Access Token5
- creating-a-personal-access-token-for-the-command-line) with
Image and optional tagshould come from the pull instructions on your package repo
Continuous Deploymentshould be
Next, you will want to copy the WebHooks URL so that you can paste it into the GitHub webhook configuration.
Payload URLshould be the URL you copied from Azure App Service
Content Typeshould be
- No secret needed, credentials are in the
Let me select individual eventsand check the
Once everything is set up, you should be able to make a push or merge into the master branch and see your package update and the App Service pull the image shortly after.
Now that we have all of the pieces in place, our steps look like this:
|Publish Build||Github||Github Actions|
|Store Image||Github||Push from Github Action to Packages|
|Pull Image from ACR||Azure App Service||Github Webhook|
We no longer have to monitor Azure DevOps or pay for Azure Container Registry. We can make our GitHUb Actions as complicated as we like and add in tests for the builds.