Merge pull request #6 from jcreek/4-add-docker-support

4 add docker support
This commit is contained in:
Josh Creek
2026-02-22 17:10:08 +00:00
committed by GitHub
12 changed files with 273 additions and 38 deletions
+13
View File
@@ -0,0 +1,13 @@
.git
.github
.svelte-kit
.vscode
node_modules
.pnpm-store
.DS_Store
Thumbs.db
coverage
dist
.env
.env.*
data/network.json
+56
View File
@@ -0,0 +1,56 @@
name: Docker
on:
pull_request:
branches:
- main
push:
branches:
- main
tags:
- "v*.*.*"
env:
IMAGE_NAME: jcreek23/open-network-diagram
jobs:
docker:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
if: github.event_name == 'push'
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: docker.io/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=sha,prefix=sha-
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
- name: Build (PR) / Build+Push (push)
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
push: ${{ github.event_name == 'push' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
+3
View File
@@ -18,6 +18,9 @@ Thumbs.db
!.env.example
!.env.test
# User-provided Docker data
data/network.json
# Vite
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
+38
View File
@@ -0,0 +1,38 @@
FROM node:20-alpine AS builder
WORKDIR /app
ENV PNPM_HOME=/pnpm
ENV PATH=$PNPM_HOME:$PATH
RUN corepack enable
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile --store-dir /pnpm/store
COPY . .
ENV DEPLOY_TARGET=docker
RUN pnpm run build:docker
FROM nginxinc/nginx-unprivileged:1.27-alpine AS runner
USER root
RUN apk add --no-cache libcap && \
setcap 'cap_net_bind_service=+ep' /usr/sbin/nginx
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/build /usr/share/nginx/html
RUN mkdir -p /usr/share/nginx/html/data && \
chown -R 101:101 /usr/share/nginx/html /var/cache/nginx /var/run /etc/nginx/conf.d
USER 101
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
CMD wget -qO- http://127.0.0.1/ > /dev/null || exit 1
CMD ["nginx", "-g", "daemon off;"]
+51 -33
View File
@@ -9,7 +9,7 @@
**Open Network Diagram** is an **open-source, self-hosted tool** for creating **interactive network and infrastructure diagrams** using a **declarative JSON format**.
**Fully self-hostable via Docker**
**JSON-based network structure** (editable in UI or manually)
**Docker-first deployment target** (Netlify optional for demo hosting)
**Interactive network visualisation**
**Simple file-based configuration**
**Lightweight Svelte**
@@ -20,25 +20,41 @@ Use it to **document your home lab, office network, or cloud infrastructure** wi
## **🚀 Quick Start (For Users)**
### **1️⃣ Run Open Network Diagram via Docker**
### **1️⃣ Create Your Runtime Data File**
Pull and run the latest image:
Copy the template and edit your own network data:
```bash
docker run -d -p 8080:3000 jcreek23/open-network-diagram
cp data/network.json.example data/network.json
```
- **`-p 8080:3000`** → Maps the app to `http://localhost:8080`
### **2️⃣ Run Open Network Diagram via Docker**
### **2️⃣ Open the Web UI**
From this repo:
```bash
docker compose up --build
```
Or pull and run directly:
```bash
docker run -d -p 8080:80 -v "$(pwd)/data:/usr/share/nginx/html/data:ro" jcreek23/open-network-diagram
```
- **`-p 8080:80`** → Maps the app to `http://localhost:8080`
- **`-v .../data:/usr/share/nginx/html/data:ro`** → Uses your local `data/network.json`
### **3️⃣ Open the Web UI**
Visit **`http://localhost:8080`** to view your network diagram.
### **3️⃣ Modify Your Network (JSON-Based)**
### **4️⃣ Modify Your Network (JSON-Based)**
- The app reads **`/data/network.json`** from static assets.
- In this repo, the default file is **`static/data/network.json`**.
- Update that file to change the diagram data.
- Docker runtime reads **`/data/network.json`** from the mounted volume.
- In this repo, your editable file is **`data/network.json`** (gitignored).
- Netlify demo builds use committed sample data at **`static/data/network.json`**.
- After editing JSON, click **Reload Default JSON** in the UI.
---
@@ -65,17 +81,28 @@ pnpm run dev
- Runs at `http://localhost:5173`
### **4️⃣ Build Targets**
```bash
pnpm run build # default (Docker/static target)
pnpm run build:docker # explicit Docker/static target
pnpm run build:netlify # explicit Netlify target
```
---
## **🛠️ Project Structure**
```
```text
open-network-diagram/
├── src/ # Svelte components
│ ├── package.json # Dependencies
── Dockerfile # Docker setup
── .github/workflows/ # CI/CD pipelines
── README.md # Documentation
├── src/ # Svelte app source
├── static/data/network.json # Demo dataset (Netlify/demo)
── data/network.json.example # User data template (Docker)
── Dockerfile # Docker build/runtime
── docker-compose.yml # Local Docker run with mounted data
├── netlify.toml # Netlify build config
├── .github/workflows/ # CI workflows (Docker image build/push)
└── README.md # Documentation
```
---
@@ -91,13 +118,14 @@ docker build -t open-network-diagram .
### **Run Locally**
```bash
docker run -p 8080:3000 open-network-diagram
docker run --rm -p 8080:80 -v "$(pwd)/data:/usr/share/nginx/html/data:ro" open-network-diagram
```
### **CI/CD (GitHub Actions)**
### **CI/CD (GitHub Actions + Netlify)**
- Automatic Docker builds when changes are pushed to `main`.
- Pushes the latest image to **Docker Hub**.
- GitHub Actions workflow (`.github/workflows/docker.yml`) builds Docker on PRs.
- Pushes to `main` publish Docker images to **Docker Hub** (`jcreek23/open-network-diagram`).
- Netlify uses its own CI/CD pipeline with `netlify.toml` (`pnpm run build:netlify`).
---
@@ -114,10 +142,7 @@ Define your network using **`network.json`**:
"role": "Hypervisor",
"operatingSystem": "Proxmox",
"software": {
"vms": [
{ "name": "OpnSense", "role": "Router", "ipAddress": "10.0.0.4" },
{ "name": "PiVPN", "role": "VPN Server", "ipAddress": "10.0.0.5" }
]
"vms": [{ "name": "OpnSense", "role": "Router", "ipAddress": "10.0.0.4" }]
},
"hardware": {
"cpu": "Intel N100",
@@ -125,7 +150,8 @@ Define your network using **`network.json`**:
"networkPorts": 4
}
}
]
],
"devices": [{ "name": "Switch", "ipAddress": "10.0.0.2", "type": "Nintendo Switch" }]
}
```
@@ -163,11 +189,3 @@ We welcome contributions! To contribute:
**Author:** [Joshua Creek](https://github.com/jcreek)
**Project Repo:** [GitHub](https://github.com/jcreek/OpenNetworkDiagram)
---
### **🔥 Next Steps**
**Set up GitHub Repo**
**Push initial project structure**
**Add CI/CD for automated Docker builds**
+54
View File
@@ -0,0 +1,54 @@
{
"machines": [
{
"machineName": "Example Host",
"ipAddress": "192.168.1.10",
"role": "Hypervisor",
"operatingSystem": "Linux",
"ports": [
{
"portName": "eth0",
"speedGbps": 1,
"connectedTo": {
"device": "Example Switch",
"port": "1"
}
}
],
"software": {
"vms": [
{
"name": "Example VM",
"role": "Service",
"ipAddress": "192.168.1.20"
}
]
},
"hardware": {
"cpu": "CPU model",
"ram": "16GB",
"networkPorts": 1,
"networkPortSpeedGbps": 1,
"gpu": "Optional GPU"
}
}
],
"devices": [
{
"name": "Example Switch",
"ipAddress": "192.168.1.2",
"type": "Network Switch",
"notes": "Optional notes",
"ports": [
{
"portName": "1",
"speedGbps": 1,
"connectedTo": {
"device": "Example Host",
"port": "eth0"
}
}
]
}
]
}
+11
View File
@@ -0,0 +1,11 @@
services:
open-network-diagram:
build:
context: .
dockerfile: Dockerfile
image: open-network-diagram:local
ports:
- "8080:80"
volumes:
- ./data:/usr/share/nginx/html/data:ro
restart: unless-stopped
+5
View File
@@ -0,0 +1,5 @@
[build]
command = "pnpm run build:netlify"
[build.environment]
DEPLOY_TARGET = "netlify"
+16
View File
@@ -0,0 +1,16 @@
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
location /data/ {
try_files $uri =404;
add_header Cache-Control "no-cache";
}
location / {
try_files $uri $uri/ /index.html;
}
}
+3
View File
@@ -6,6 +6,8 @@
"scripts": {
"dev": "vite dev",
"build": "vite build",
"build:docker": "DEPLOY_TARGET=docker vite build",
"build:netlify": "DEPLOY_TARGET=netlify vite build",
"preview": "vite preview",
"prepare": "svelte-kit sync || echo ''",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
@@ -19,6 +21,7 @@
"@eslint/js": "^8.57.1",
"@sveltejs/adapter-auto": "^4.0.0",
"@sveltejs/adapter-netlify": "^5.0.0",
"@sveltejs/adapter-static": "^3.0.10",
"@sveltejs/kit": "^2.16.0",
"@sveltejs/vite-plugin-svelte": "^5.0.0",
"@tailwindcss/typography": "^0.5.15",
+12
View File
@@ -30,6 +30,9 @@ importers:
'@sveltejs/adapter-netlify':
specifier: ^5.0.0
version: 5.0.0(@sveltejs/kit@2.20.4(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.8)(vite@6.2.5(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.25.8)(vite@6.2.5(jiti@2.4.2)(lightningcss@1.29.2)))
'@sveltejs/adapter-static':
specifier: ^3.0.10
version: 3.0.10(@sveltejs/kit@2.20.4(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.8)(vite@6.2.5(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.25.8)(vite@6.2.5(jiti@2.4.2)(lightningcss@1.29.2)))
'@sveltejs/kit':
specifier: ^2.16.0
version: 2.20.4(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.8)(vite@6.2.5(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.25.8)(vite@6.2.5(jiti@2.4.2)(lightningcss@1.29.2))
@@ -595,6 +598,11 @@ packages:
peerDependencies:
'@sveltejs/kit': ^2.4.0
'@sveltejs/adapter-static@3.0.10':
resolution: {integrity: sha512-7D9lYFWJmB7zxZyTE/qxjksvMqzMuYrrsyh1f4AlZqeZeACPRySjbC3aFiY55wb1tWUaKOQG9PVbm74JcN2Iew==}
peerDependencies:
'@sveltejs/kit': ^2.0.0
'@sveltejs/kit@2.20.4':
resolution: {integrity: sha512-B3Y1mb1Qjt57zXLVch5tfqsK/ebHe6uYTcFSnGFNwRpId3+fplLgQK6Z2zhDVBezSsPuhDq6Pry+9PA88ocN6Q==}
engines: {node: '>=18.13'}
@@ -2420,6 +2428,10 @@ snapshots:
esbuild: 0.24.2
set-cookie-parser: 2.7.1
'@sveltejs/adapter-static@3.0.10(@sveltejs/kit@2.20.4(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.8)(vite@6.2.5(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.25.8)(vite@6.2.5(jiti@2.4.2)(lightningcss@1.29.2)))':
dependencies:
'@sveltejs/kit': 2.20.4(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.8)(vite@6.2.5(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.25.8)(vite@6.2.5(jiti@2.4.2)(lightningcss@1.29.2))
'@sveltejs/kit@2.20.4(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.8)(vite@6.2.5(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.25.8)(vite@6.2.5(jiti@2.4.2)(lightningcss@1.29.2))':
dependencies:
'@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.25.8)(vite@6.2.5(jiti@2.4.2)(lightningcss@1.29.2))
+11 -5
View File
@@ -1,6 +1,15 @@
import adapter from '@sveltejs/adapter-netlify';
import netlifyAdapter from '@sveltejs/adapter-netlify';
import staticAdapter from '@sveltejs/adapter-static';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
const deployTarget = (process.env.DEPLOY_TARGET ?? 'docker').toLowerCase();
const adapter = deployTarget === 'netlify'
? netlifyAdapter()
: staticAdapter({
fallback: 'index.html',
strict: false
});
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://svelte.dev/docs/kit/integrations
@@ -8,10 +17,7 @@ const config = {
preprocess: vitePreprocess(),
kit: {
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
adapter: adapter()
adapter
}
};