To streamline the development of new, quick, low-overhead Flask applications, I created a lightweight tool to monitor active Docker containers. The goal was to enable rapid iteration on local containers during development. Since this was internal infrastructure, I focused on building a solution that prioritized functionality and simplicity over aesthetics.
This post outlines the application’s functionality and shares the core code for anyone looking to replicate or adapt it.
The app provides a quick way to view all running Docker instances on a machine and includes direct links to access them. Built with Flask and some generated code, it’s designed to be flexible and easy to update. A single command generates the necessary data, which can then be pasted directly into place.

It’s nothing special, just some quick code generated to fill the purpose, but nice to get running in an hour. Maybe it could be useful to you!
from flask import Flask, request, jsonify, render_template
import os
import json
# Get the absolute path to the templates folder
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
TEMPLATES_DIR = os.path.join(BASE_DIR, "../templates")
app = Flask(__name__, template_folder=TEMPLATES_DIR)
# File path for storing the JSON data
STORED_JSON_PATH = "containers.json"
# Route for home page
def generate_url(hostname, port, container_name):
if hostname:
return f"https://{hostname}"
return f"http://localhost:{port}"
@app.route("/", methods=["GET", "POST"])
def home():
command_example = "docker ps --format '{{json .}}'"
containers = []
if request.method == "POST":
try:
json_data = request.form.get("json_data")
# Parse and validate JSON
lines = json_data.strip().split("\n")
data = [json.loads(line) for line in lines]
for container in data:
labels = container.get("Labels", "")
hostname = None
if labels:
# Extract custom.hostname if available
label_dict = dict(label.split("=") for label in labels.split(",") if "=" in label)
hostname = label_dict.get("custom.hostname")
ports = container.get("Ports", "").split(",")[0] # Use the first port entry
if "->" in ports:
port = ports.split("->")[0].split(":")[-1]
else:
port = None
name = container.get("Names", "").split(",")[0]
if name:
containers.append({
"url": generate_url(hostname, port, name),
"name": name
})
# Save the JSON data to a file
with open(STORED_JSON_PATH, "w") as file:
json.dump(data, file, indent=4)
except json.JSONDecodeError:
return render_template("index.html", error="Invalid JSON format.", command_example=command_example, containers=[]), 400
elif os.path.exists(STORED_JSON_PATH):
# Load the stored JSON
with open(STORED_JSON_PATH, "r") as file:
data = json.load(file)
for container in data:
labels = container.get("Labels", "")
hostname = None
if labels:
label_dict = dict(label.split("=") for label in labels.split(",") if "=" in label)
hostname = label_dict.get("custom.hostname")
ports = container.get("Ports", "").split(",")[0]
if "->" in ports:
port = ports.split("->")[0].split(":")[-1]
else:
port = None
name = container.get("Names", "").split(",")[0]
if name:
containers.append({
"url": generate_url(hostname, port, name),
"name": name
})
return render_template("index.html", command_example=command_example, containers=containers)
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0")
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Apps Home</title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@material/web@latest/dist/material-components-web.min.css" rel="stylesheet">
<style>
body {
font-family: Roboto, Arial, sans-serif;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #f5f5f5;
min-height: 100vh;
}
.container {
width: 80%;
max-width: 600px;
margin-top: 2rem;
padding: 1.5rem;
background: #ffffff;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.title {
text-align: center;
font-size: 1.5rem;
margin-bottom: 1rem;
}
ul {
list-style: none;
padding: 0;
}
li {
margin: 0.5rem 0;
}
a {
text-decoration: none;
color: #6200ee;
}
a:hover {
text-decoration: underline;
}
.error {
color: red;
margin-bottom: 1rem;
}
.command-example {
background: #e0f7fa;
padding: 1rem;
border-radius: 8px;
font-family: monospace;
margin-bottom: 1rem;
position: relative;
}
.command-example button {
position: absolute;
top: 10px;
right: 10px;
background: #6200ee;
color: white;
border: none;
border-radius: 4px;
padding: 5px 10px;
cursor: pointer;
}
.command-example button:hover {
background: #3700b3;
}
textarea {
width: 100%;
height: 150px;
padding: 10px;
margin-bottom: 1rem;
font-family: monospace;
font-size: 1rem;
}
button {
padding: 10px 20px;
background: #6200ee;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
}
button:hover {
background: #3700b3;
}
</style>
<script>
function copyCommand() {
const command = document.getElementById("command-example-text").innerText;
navigator.clipboard.writeText(command).then(() => {
alert("Command copied to clipboard!");
}).catch(err => {
console.error("Failed to copy command: ", err);
});
}
</script>
</head>
<body>
<div class="container">
<h1 class="title">Apps Home</h1>
{% if error %}
<p class="error">{{ error }}</p>
{% endif %}
<h2>Configured Apps</h2>
<ul>
{% for container in containers %}
<li><a href="{{ container.url }}" target="_blank">{{ container.name }}</a> ({{ container.url }})</li>
{% endfor %}
</ul>
<h2>Update Configured Apps</h2>
<div class="command-example">
<strong>Command Example:</strong>
<code id="command-example-text">{% raw %}docker ps --format '{{json .}}' | xclip -selection clipboard{% endraw %}</code>
<button onclick="copyCommand()">Copy</button>
</div>
<form action="/" method="post">
<label for="json_data">Enter Updated JSON (Newline-Separated):</label>
<textarea id="json_data" name="json_data" placeholder="Paste your JSON here..." required></textarea>
<button type="submit">Submit</button>
</form>
</div>
</body>
</html>