A web interface for browsing and downloading files from any public Azure Blob Storage container.
1.5K
A self-hosted web interface for browsing and downloading files from any public Azure Blob Storage container.
You can run Blob Explorer two ways:
Create a docker-compose.yaml:
services:
blob-explorer:
image: joshooaj/blobexplorer:latest
container_name: blob-explorer
ports:
- "8080:8080"
volumes:
- ./config:/config
- blob-cache:/cache
environment:
- BASE_URL=https://myaccount.blob.core.windows.net/mycontainer
restart: unless-stopped
volumes:
blob-cache:
docker compose up -d
git clone https://github.com/joshooaj/blobexplorer.git
cd blobexplorer
Set your BASE_URL in a docker-compose.override.yaml:
services:
blob-explorer:
ports:
- "8080:8080"
environment:
- BASE_URL=https://myaccount.blob.core.windows.net/mycontainer
docker compose up -d --build
Then open http://localhost:8080 in your browser.
| Variable | Required | Default | Description |
|---|---|---|---|
BASE_URL | Yes | — | Azure Blob Storage container URL |
DOWNLOAD_BASE | No | Same as BASE_URL | Alternative download URL (e.g., CDN or Front Door) |
SITE_TITLE | No | Blob Explorer | Title shown in header and browser tab |
SITE_DESCRIPTION | No | Browse and download files... | Meta description |
LOGO_URL | No | Default logo | URL to a custom logo image |
LOGO_FILE | No | — | Path to a logo file relative to /config (e.g., my-logo.svg) |
UPDATE_INTERVAL | No | 86400 | Seconds between blob list refreshes (default: 24h) |
ALLOW_CUSTOM_URL | No | false | Allow users to browse any blob storage URL via settings |
TZ | No | UTC | Timezone for timestamps |
On first run, a default config.json is created in your /config volume. Edit it to customize favorites, analytics, and more. Environment variables take precedence over config file values.
{
"$schema": "./config.schema.json",
"siteTitle": "My Downloads",
"siteDescription": "Browse and download files",
"logoUrl": "",
"analyticsScript": "analytics.html",
"favorites": [
{
"label": "Recent Releases",
"type": "folder",
"path": "releases/2024"
},
{
"label": "Documentation",
"type": "search",
"query": "\\.pdf$"
},
{
"label": "Latest Versions",
"type": "pattern",
"pattern": "^v\\d+\\.\\d+",
"limit": 3,
"sortOrder": "desc"
}
]
}
A config.schema.json is included for editor autocompletion and validation.
| Type | Description | Required Fields |
|---|---|---|
folder | Navigate to a folder path | path |
search | Run a regex search query | query |
pattern | Auto-match folders by regex | pattern, optional limit and sortOrder |
services:
blob-explorer:
# ... other config ...
networks:
- web
labels:
- "traefik.enable=true"
- "traefik.http.routers.blob-explorer.entrypoints=https"
- "traefik.http.routers.blob-explorer.rule=Host(`downloads.example.com`)"
- "traefik.http.services.blob-explorer.loadbalancer.server.port=8080"
networks:
web:
external: true
Blob Explorer dispatches custom events that you can hook into with any analytics provider.
config.json:{ "analyticsScript": "analytics.html" }
File formats:
.js — plain JavaScript, auto-wrapped in <script> tags.html — injected as-is (use when loading external scripts via <script src="...">)| Event | Detail Properties |
|---|---|
blob-explorer:page-view | path, url, timestamp |
blob-explorer:search | query, resultCount, timestamp |
blob-explorer:download | fileName, filePath, fileSize, fileType, timestamp |
blob-explorer:copy-link | fileName, filePath, timestamp |
blob-explorer:folder-navigate | folderPath, folderName, timestamp |
blob-explorer:filter-change | activeFilters, totalFilters, timestamp |
blob-explorer:theme-change | theme, timestamp |
blob-explorer:favorite-add / favorite-remove | label, type, path, timestamp |
Create ./config/analytics.html:
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
document.addEventListener('blob-explorer:download', (e) => {
gtag('event', 'download', {
file_name: e.detail.fileName,
file_type: e.detail.fileType,
file_size: e.detail.fileSize
});
});
document.addEventListener('blob-explorer:search', (e) => {
gtag('event', 'search', { search_term: e.detail.query });
});
</script>
{ "analyticsScript": "analytics.html" }
Create ./config/analytics.html:
<script async src="https://plausible.io/js/script.js"></script>
<script>
window.plausible = window.plausible || function() { (plausible.q = plausible.q || []).push(arguments) };
document.addEventListener('blob-explorer:download', (e) => {
plausible('Download', { props: { file: e.detail.fileName, type: e.detail.fileType } });
});
document.addEventListener('blob-explorer:search', (e) => {
plausible('Search', { props: { query: e.detail.query, results: String(e.detail.resultCount) } });
});
document.addEventListener('blob-explorer:folder-navigate', (e) => {
const baseUrl = window.location.protocol + '//' + window.location.hostname;
const segments = e.detail.folderPath.split('/').filter(Boolean).map(encodeURIComponent);
const virtualPath = segments.length ? '/folder/' + segments.join('/') + '/' : '/';
plausible('pageview', { u: baseUrl + virtualPath });
});
</script>
{ "analyticsScript": "analytics.html" }
Create ./config/analytics.js:
document.addEventListener('blob-explorer:download', (e) => {
console.log('Download:', e.detail.fileName, e.detail.fileSize);
});
document.addEventListener('blob-explorer:search', (e) => {
console.log('Search:', e.detail.query, 'Results:', e.detail.resultCount);
});
Plain .js files are automatically wrapped in <script> tags.
Blob Explorer runs as a single Docker container:
config.json + environment variables at startup/cache enables instant startup on container restart| Mount Point | Purpose |
|---|---|
/config | Configuration (config.json, logos, analytics scripts) |
/cache | Blob data cache for fast startup |
/config/config.json from defaults if missing/cache is served immediately while stale data refreshes in the backgroundUPDATE_INTERVALMIT
Content type
Image
Digest
sha256:5a725964d…
Size
39.7 MB
Last updated
7 months ago
docker pull joshooaj/blobexplorer