Overview
Alluvial supports embedding containerized applications built with frameworks such as RShiny, Streamlit, Angular, and others.
Project administrators can add containerized apps directly to a project. This lets teams deliver custom tools (for example, analytics dashboards or modeling apps) alongside reports and dashboards, all within the same secure, role-based interface.
What is a container application?
A container application packages an app together with its runtime and dependencies into a portable, isolated unit called a container. Alluvial lets authorized users run and interact with these apps inside a project.
Key Features of Container Applications
- Portability – Run consistently across environments (development, testing, production).
- Scalability – Easily deploy multiple instances to handle increased workloads.
- Flexibility – Support applications built with frameworks such as RShiny, Streamlit, Angular, and more.
- Isolation – Each app runs in its own container, minimizing conflicts with other applications.
- Efficiency – Containers are lightweight compared to traditional virtual machines.
When developing locally, use Docker or Podman to run and test your container before deployment.
Adding a Containerized Application
Access Containerized Apps
- Navigate to the administration page in your Alluvial project.
- Select Containerized Apps to open the project’s containerized apps search page.

Create a New Containerized Apps Entry
- If containers are already configured, they will be listed on the search page.
- To add a new containerized application, click CREATE NEW.

- Name - Display name shown in the project side bar.
- Child Domain Name - Subdomain shown when the app is opened in a full window (for example, CHILD-DOMAIN-NAME.alluvial.app).
- Image - Auto-generated image name. Use this exact name when tagging and pushing your image to the Alluvial registry.
- Set Status - Used during deployment.
- Current Status - Deployment state: draft, creating, or operational.
- Description - Short description of the app.
- Port - The port your app exposes (must match the container configuration).
IMPORTANT: You cannot change the auto-generated image name, and you must push images to your organization's Alluvial container registry (not a personal registry). Contact your Alluvial Platform Administrator for registry details and pre-configured workflows.
After entering Name, Child Domain Name, and Port, click SAVE AND RETURN. The entry will appear in the search page with a status of draft.

Click SAVE AND RETURN to finalize your changes. This must be done prior to further configuration.
You will be navigated back to the Containerized Apps search page. You should see an entry for your deployment with its Status set to draft.

Select this entry to enter the form again. Make note of the auto-generated value in the Image field.

If your application uses environment variables, configure them on the form. Hover over the Environmental Variables bar to display the add icon, then click it to create a new variable.

Hover over the box that appears with your cursor and click the drop-down arrow that appears.

Enter in the Name and associated Value for your variable.
IMPORTANT: The way these variables are accessed depends on the language your application uses. For example:
- Python: os.environ.get("AZURE_SQL_USERNAME")
- R: Sys.getenv("AZURE_SQL_USERNAME")
- C#: Environment.GetEnvironmentVariable("AZURE_SQL_USERNAME");

Repeat this process for each variable used in your application.
IMPORTANT: Project Owners and Administrators should be cautious when granting administrative privileges related to containers. Environment variables may be visible to users with sufficient project access.
Scroll down the form further to configure other options, such as Menu Groups, Custom Roles, and Dashboard Tiles.
The Open As field will let you set how your application will open when a user selects it in the Alluvial project. The iframe value will open the application directly in Alluvial. The new-window option will open a new browser window and display the application using the Child Domain Name that was previously set.

Click SAVE AND RETURN to finalize your changes.
Deploying the Application
In most cases, your organizations Alluvial Platform Administrator will have templates that include pre-configured workflows that will automatically push your application into the designated image Alluvial repository.
For example, your organization may be using GitHub to push your application code into an image repository. It's common to have a Shared Workflow in place that will be called by another workflow located within your own applications repository.
A shared workflow might look like this:
name: Deploy to ACR
on:
workflow_call:
inputs:
image_name:
description: "Image name to tag and push"
required: true
type: string
dockerfile:
description: "Path to the Dockerfile"
required: true
type: string
secrets:
ALLUVIAL_CA_SERVER:
required: true
ALLUVIAL_CA_USERNAME:
required: true
ALLUVIAL_CA_PASSWORD:
required: true
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Docker Login
uses: azure/docker-login@v2
with:
login-server: ${{ secrets.ALLUVIAL_CA_SERVER }}
username: ${{ secrets.ALLUVIAL_CA_USERNAME }}
password: ${{ secrets.ALLUVIAL_CA_PASSWORD }}
- name: Get timestamp
id: timestamp
run: echo "timestamp=$(date +'%Y%m%d-%H%M%S')" >> $GITHUB_ENV
- name: Build and push image
run: |
docker build . -f ${{ inputs.dockerfile }} \
-t ${{ secrets.ALLUVIAL_CA_SERVER }}/${{ inputs.image_name }}
docker push ${{ secrets.ALLUVIAL_CA_SERVER }}/${{ inputs.image_name }}
Which would then be called by another workflow in your own repository, which could look like this:
name: Deploy to ACR
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: read
jobs:
reusable_workflow_job:
uses: My-Organization/Shared-Workflows/.github/workflows/deploy-to-aca.yml@main
with:
image_name: gelij818sw2r:latest
dockerfile: Dockerfile
secrets:
ALLUVIAL_CA_SERVER: ${{ secrets.ALLUVIAL_CA_SERVER }}
ALLUVIAL_CA_USERNAME: ${{ secrets.ALLUVIAL_CA_USERNAME }}
ALLUVIAL_CA_PASSWORD: ${{ secrets.ALLUVIAL_CA_PASSWORD }}
In the workflow text above, you will notice the image_name: gelij818sw2r:latest corresponds with the auto-generated image name created earlier.

Once you push a change to your application repository, the workflow will start if it is configured correctly.



Your image should build and be pushed to the image registry. After a successful push, return to the Containerized Apps entry in Alluvial, set the status to operational, and click SAVE AND RETURN.

The status of the entry will change to creating.

When your application is ready, the status will change to operational. Refresh the page to observe the change when it occurs.

If you navigate back to your project Dashboard page, you may notice that your application is not visible immediately. Do not worry, the application is still starting up.

After a short while, your application should become visible. The time it takes for an application to start will depend on the size and complexity of the application itself.

IMPORTANT: Your application will stop after five minutes of inactivity. It will require time to start again when users return. This behavior cannot be overridden.
Updating or Restarting the Application
Updating and restarting are related. To update an application, change the code in your repository and run your continuous integration workflow to build and push a new image.
If the app is idle, the new image will be used the next time it starts. If the app is active and you need the update immediately, trigger a restart from the Containerized Apps search page entry.

IMPORTANT: Triggering a restart while your application is actively being used may disrupt current users.
Container Development
Reach out to your organization's Alluvial Platform Administrator for application templates and pre-configured workflows to assist with development and deployment.
Please submit a request through the support site to contact your organization's Alluvial Platform Administrator.
Connecting Containers to File Management
Before you get started, you will need to upload data to your project through the File Management module. The following information demonstrates how to connect a container application to this data.
While this uses the R Shiny framework in the example, the underlying logic can be used regardless of your chosen development framework.
Copying a SAS Token URL
After uploading files to the File Management module, navigate to the desired directory. Hover over the folder name to display the tooltip “Read/Write Access Token Folder Level”, then copy the Read Access Token for that folder.
IMPORTANT: Copying the token at the file level will only grant access to that file, not the entire directory.

The generated URL will resemble:
https://<STORAGE_ACCOUNT>.blob.core.windows.net/appstor/<PROJECT_ID>/fileManagement/data?sv=2025-01-05&st=2025-06-08T16%3A04%3A32Z&se=2025-09-07T16%3A04%3A32Z&sr=d&sp=racwdlme&sdd=3&sig=PBMaYisrg6T77TLJ1sx%2F0itEvB9Vo6TJii85YbN8OZg%3D
The key URL components are:
- Azure Storage URL:
https://<STORAGE_ACCOUNT>.blob.core.windows.net
- Azure Container Name:
appstor
- Alluvial Directory Path:
<PROJECT_ID>/fileManagement/data
- SAS Token:
sv=...&sig=...
The SAS token is temporary and should be treated securely:
- Do not commit it to source control (e.g., Git).
- Store it locally in a gitignored
.env
file. - In GitHub, store it as a repository secret.
- In production, use an environment variable in the Azure Web App.
For more details on SAS token structure and usage, refer to Create a service SAS - Azure Storage.
Connecting an R Shiny Application
Use the following R code to connect your R Shiny application to the Azure storage directory:
az_endpoint <- AzureStor::storage_endpoint(
"https://<STORAGE_ACCOUNT>.blob.core.windows.net",
sas = Sys.getenv("AZ_SAS_TOKEN")
)
az_container <- AzureStor::storage_container(az_endpoint, "appstor")
AzureStor::list_blobs(az_container, "<PROJECT_ID>/fileManagement/data")
This returns a list of blobs in the specified directory. Typical usage includes AzureStor::(multi)download_blob
and AzureStor::(multi)upload_blob
for transferring files. Using smaller files will generally result in a faster user experience.