Skip to main content

· 2 min read

If you're a Rust developer who's just getting started with Azure, this post is for you. In this guide, I'll explore an templated repository you can use that makes deploying your Rust application to Azure Container Apps a breeze. With easy-to-use CLI tools and an automated GitHub Action workflow, deploying your app is as simple as pushing your changes to the main branch!

What's in the Repo?

This repository contains a simple Rust application built using the Axum web server. It includes:

  • A root route that returns HTML.
  • An /api/users endpoint returning JSON data.
  • Example configuration for environment secrets:
    • PORT=3000
    • MY_SECRET=1234

Easy, CLI-Powered provisioning and deployment

1. Provision Your Azure Environment

The repo ships with a set of bash scripts that take care of provisioning Azure resources. These scripts leverage:

  • Azure CLI – Use it to interact with and manage your Azure resources.
  • Azure Developer CLI (azd) – Provision and configure resources using Bicep templates.
  • GitHub CLI – Configure the deployment secrets necessary for GitHub Actions.

Running these scripts sets up everything from an Azure Container Registry to Application Insights in just a few commands.

2. Push-to-Main Deployments

After setting up your environment, subsequent deployments are incredibly simple:

  • Automated Workflow: Every push to the main branch triggers a GitHub Action that builds your Rust application and deploys it to Azure Container Apps.
  • Continuous Deployment: With the automation in place, you no longer need to manually deploy your app. Just push your changes—and your app is live!

3. Real-Time Monitoring and Logs

The repository includes a script (stream-logs.sh) that streams live logs from your Rust Axum server directly to your terminal. This makes it easy to:

  • Monitor live application activity.
  • Debug issues in real time.
  • Gain immediate insights into your app’s behavior.

Simple Rust migration to Azure

For developers new to Azure but familiar with Rust, this repository exemplifies how modern dev tools combine to simplify cloud deployments. Instead of wrestling with complex setups, you get:

  • A straightforward CLI-driven process.
  • Seamless integration with GitHub Actions.
  • An efficient, automated deployment pipeline that gets your app live with minimal hassle.

Repository template

https://github.com/dfberry/rust-on-azure-container-apps

· 4 min read

Azure Functions apps can be locally deployed from Visual Studio Code using the Azure Functions extension or when you create the resource in the portal, you can configure deployment. These are straightforward when your app is the only thing in the repo but become a little more challenging in monorepos.

Single versus monorepo repositories

When you have a single function in a repo, the Azure Functions app is build and run from the root level package.json which is where hosting platforms look for those files.

- package.json
- package-lock.json
- src
- functions
- hello-world.js

In a monorepos, all these files are pushed down a level or two and there may or may not be a root-level package.json.

- package.json
- packages
- products
- package.json
- package-lock.json
- src
- functions
- product.js
- sales
- package.json
- package-lock.json
- src
- functions
- sales.js

If there is a root-level package.json, it may control developer tooling across all packages. While you can deploy the entire repo to a hosting platform and configure which package is launched, this isn't necessary and may lead to problems.

Monorepo repositories as a single source of truth

Monorepo repositories allow you to collect all source code or at least all source code for a project into a single place. This is ideal for microservices or full-stack apps. There is an extra layer of team education and repository management in order to efficiently operationalize this type of repository.

When starting the monorepo, you need to select the workspace management. I use npm workspaces but others exist. This requires a root-level package.json with the packages (source code projects) noted.

The syntax for npm workspaces allows you to select what is a package as well as what is not a package.

snippets/2024-04-07-functions-monorepo/package-workspaces.json
loading...

Azure Functions apps with Visual Studio Code

When you create a Functions app with Visual Studio Code with the Azure Functions extension you can select it to be created at the root, or in a package. As part of that creation process, a .vscode folder is created with files to help find and debug the app.

  • extensions.json: all Visual Studio Code extensions
  • launch.json: debug
  • settings.json: settings for extensions
  • tasks.json: tasks for launch.json

The settings.json includes azureFunctions.deploySubpath and azureFunctions.projectSubpath properties which tells Azure Functions where to find the source code. For a monorepo, the value of these settings may depend on the version of the extension you use.

As of March 2024, setting the exact path has worked for me, such as packages/sales/.

If you don't set the correct path for these values, the correct package may not be used with the extension or the hosting platform won't find the correct package.json to launch the Node.js Functions app.

  • During development: set the azureFunctions.projectSubpath to the single package path you are developing.
  • During deployment: set the azureFunctions.deploySubpath to the single package path so the hosting platform has the correct path to launch the app.

GitHub actions workflow file for Azure Functions monorepo app

When you create a Azure Functions app in the Azure portal and configure the deployment, the default (and not editable) workflow file is built for a monorepo where the app's package.json is at the root of the repository.

Yaml

snippets/2024-04-07-functions-monorepo/single-app-workflow.yml
loading...

This worklow sets the AZURE_FUNCTIONAPP_PACKAGE_PATH as the root of the project then pushes, pushd './${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}', into that path to build. The zip, zip release.zip ./* -r, packages up everything as the root. To use a monorepo, these need to be altered.

  1. Change the name of the workflow to indicate the package and project.

    name: Build & deploy Azure Function - sales
  2. Create a new global env parameter that sets the package location for the subdirectory source code.

    PACKAGE_PATH: 'packages/sales' 
  3. Change the Resolve Project Dependencies Using Npm to include the new environment variable.

    pushd './${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}/${{ PACKAGE_PATH }}'

    The pushd commands moves the context into that sales subdirectory.

  4. Change the Zip artifact for deployment to use pushd and popd and include the new environment variable. The popd command returns the context to the root of the project.

    Using the pushd command, change the location of the generated zip file to be in root directory.

    The result is that the zip file's file structure looks like:

    - package.json
    - src
    - functions
    - sales.js

  5. The final workflow file for a monorepo repository with an Azure functions package is:

snippets/2024-04-07-functions-monorepo/mono-app-workflow.yml
loading...

· One min read

My GitHub site is built with Docusaurus 2 and usually shows code snippets. Since I build to my GitHub site but want to repost to Dev.to and other platforms from RSS feeds, I need the code snippets to work with the minimal amount of manual intervention and corrections after I import the blog post into Dev.to.

If the code snippet is inside the blog post as text, the Dev.to rss feed import mangles the code snippet syntax, which requires manual fix up which is time-consuming and a step I have to remember.

Using @saucelabs/theme-github-codeblock

I found the saucelabs code block on the unofficial Docusaurus features.

JavaScript reference: js

client-end/src/index.js
loading...

Json reference: json

package.json
loading...

Bash reference: bash

scripts/addition.sh
loading...

Text reference: text

notes/Learning-DataLake/Neal.txt
loading...

Rust: reference: rs

src/main.rs
loading...

Yaml

examples/mono-app-workflow.yml
loading...