I'm an intern migrating an internal tool from a physical lab server to Azure and would appreciate a sanity check on the architecture. The current setup consists of four Docker Compose containers: Open WebUI as the chat interface, Caddy for TLS and path-based routing, and two FastAPI services that perform separate tasks. One connects to internal systems over SSH and creates ZIP files, while the other generates certificate packages. The entire application must remain private and accessible only through our internal network or VPN.
I'm considering placing all four containers in a private Azure Container Apps environment connected to a VNET. Container Apps seems attractive because it can scale down when unused, which fits an internal tool with roughly 100 users who are active mainly during business hours. It also provides a shared private network similar to the current Compose setup.
The surrounding design includes private endpoints, private DNS so our internal domain resolves only within the network, Azure Key Vault for secrets currently stored in the Compose file, managed identity for passwordless access to Azure resources, Azure Files for persistent application data and generated files, and Azure Container Registry for private image storage and pulls. I measured the existing CPU and memory usage rather than estimating, and the projected cost is around $90–$100 per month, with the private endpoint accounting for much of that.
I'm unsure whether Caddy is still necessary if Azure can handle TLS and routing, whether Container Apps is a better choice than App Service for this workload, and whether there are any deployment or security issues I may be overlooking. I'd also like feedback on using Azure Files for the database and on the overall identity and networking design.
3 Answers
This is a thoughtful design and Container Apps sounds like a good fit, especially on the consumption plan. Make sure the storage account and Azure Container Registry also use private endpoints if they need to remain isolated, and grant the Container Apps managed identity permission to pull images from the registry. Key Vault with managed identity is the right approach for replacing secrets in the Compose file.
Your cost estimate could be reasonable, but monitor it closely after deployment. Azure usage and billing data can lag by a couple of days, so check the environment regularly during the first week for unexpected scaling or resource usage. I’d also deploy the whole setup with Bicep or Terraform, since the private endpoints, DNS zones, identities, and role assignments are much easier to reproduce and modify as code.
The identity model is worth documenting explicitly. Use Azure RBAC to control which members of the team can administer the resource group and its services. For service-to-service access, assign a managed identity to the Container Apps workloads and grant only the permissions each one needs—for example, reading specific secrets from Key Vault or pulling images from ACR. That avoids putting passwords or registry keys in configuration and keeps access scoped to the required resources.
I’d be careful with putting the database on Azure Files. It’s a reasonable place for generated files, but if the database is SQLite or another file-based database, network-share locking, latency, and failure behavior can become problems. Test concurrent access, restarts, disconnects, and backup recovery before committing to it. If the database workload grows, a managed database service may be safer.
Caddy may be unnecessary if Azure’s ingress features cover your TLS termination and path routing, but keep it if it provides behavior you would otherwise have to recreate. Removing it is beneficial only if Azure can replace its responsibilities cleanly; otherwise it may still be a useful single internal entry point.

That matches the approach we're taking. Team access is handled through Azure RBAC, while the containers use managed identities for Key Vault and ACR access, with permissions granted only to the relevant resources.