Metals Simple Deploy · Project Tutorials

Learning This Project

This project has six moving parts that work together: a small web API, a database the API reads and writes, a browser-based UI that calls the API, Docker images that package the API and UI so they run identically everywhere, Terraform to create the cloud infrastructure they run on, and the deployment pipeline that ships new versions. Codey the Sr. Developer will be your guide through this tutorial series, one part at a time.

Codey the Sr Developer, standing with a pointer, ready to walk through the tutorials
Cloud provider → Microsoft Azure Infrastructure tool → Terraform App language → Python (Flask) Database → PostgreSQL UI → vanilla JS, served by Nginx Packaging → Docker, 2 images

What this project is start here

metals-simple-deploy is a small, complete application: a Python API backed by a PostgreSQL database, with a browser UI in front of it, all running in Azure. “Complete” means it isn't just application code — it also includes everything needed to package that code into containers, stand up the cloud resources they run on, and deploy changes to both safely and repeatably.

Codey typing on a laptop
six parts, one project

The six parts of this project overview

Each part has a narrow, distinct job, and every one has its own tutorial. The first three are the application itself, the fourth is how it gets packaged, and the last two are two different routes for getting that package running in Azure.

Part 1

The API

A Python web application (built with Flask) that answers requests over the internet — for example, looking up or saving metals-pricing data. It contains the actual business logic of the app: what happens when someone calls a given endpoint, and who's allowed to call it.

PythonFlaskJWTGunicorn

Start the Metals API tutorial →

Part 2

The Database

A PostgreSQL database that stores the application's data persistently. The API connects to it to read and write records, so the data survives even if the API itself restarts or redeploys.

PostgreSQLDocker ComposeAzure Flexible Server

Start the Database tutorial →

Part 3

The UI

A framework-free browser app that calls the API. Anyone can view the landing page, but the catalog itself is visible only once logged in, and only accounts with the Admin role can add, edit, or delete anything.

Vanilla JSHash routingNginx

Start the Metals UI tutorial →

Part 4

Docker

The packaging layer. Three Dockerfiles turn the API, the UI, and this tutorial site into self-contained images holding their code, runtime, and dependencies — and one Compose file runs them all, plus a database, on your machine with a single command.

DockerComposeNginxACR

Start the Docker tutorial →

Part 5

Manual Deployment

Building the whole Azure environment by hand, one az command at a time, with the scripts in utility_scripts/. No preview, no state file — which makes it the clearest way to see exactly which Azure calls a deployment really makes.

Azure CLIPowerShellBash

Start the Manual Deployment tutorial →

Part 6

Automated Deployment — With Terraform

The same environment, declared as code instead of typed: Terraform creates and updates the infrastructure with a preview before every change, and GitHub Actions builds and ships the two container images whenever a pull request is merged.

TerraformGitHub ActionsOIDC

Start the Automated Deployment tutorial →

Straight to the Terraform tutorial →

Parts 5 and 6 build the same Azure environment — a resource group, a PostgreSQL server, a container registry, and two container web apps. Reading both is one of the best ways to understand what the automation is actually doing underneath, so start with whichever suits how you learn.

Running the entire application in development quickstart

All three application pieces — database, API, and UI — start together with one command. Docker Compose builds the images, starts PostgreSQL alongside them, and waits for each service to report healthy before starting the next. No local Python or PostgreSQL installation is needed.

Codey holding up a sticky note
one command, three containers
StepWhat it doesCommand
1One-time setup: create the environment file Compose requiresCopy .env.example to .env and set JWT_SECRET_KEY to any long random string
2Build the images and start every servicedocker compose up -d --build
3Confirm everything came up healthydocker compose ps
4When you're done, stop it all (keeping your data)docker compose down

Once all three are healthy, open http://localhost:8888 and log in with one of the seed accounts (admin or customer, password password for both — see the database tutorial). The API is also reachable directly at http://localhost:5000. Step 1 is genuinely required: Compose refuses to start without JWT_SECRET_KEY rather than starting an API that can't issue tokens. Full detail on the Compose file is in the Docker tutorial.

How the six parts fit together the big picture

Infrastructure comes first — whether you build it by hand (part 5) or declare it in Terraform (part 6), the result is the same empty, configured Azure environment: the database server, the container registry, and the two web app hosting slots, along with the identities that let them talk to each other. Only once that exists does it make sense to build the Docker images, push them to the registry, and have the web apps pull them. The UI is no longer a folder of files you serve yourself; it's an Nginx container that serves the pages and forwards /api/ requests on to the API, so the browser only ever talks to one address. Change the infrastructure through whichever path you picked, change the application by building a new image — the two move independently, but neither works without the other underneath.

Codey pointing to the right
infrastructure, then images, then traffic
Codey giving a thumbs up

New here? Read the parts in order — or jump straight to Docker if you just want to get the project running locally.