Docker
Ship your audio server in a container. Same code, anywhere. 🐳
Docker: Because Production Should Just Work
Look, we've all been there. You spend hours getting NodeLink running perfectly on your laptop. Everything works. Audio is crisp. No crashes. Life is good.
Then you deploy to production and... it doesn't work. Wrong Node version. Missing dependencies. Something about native modules. Your weekend is gone.
Docker fixes this. It's not magic. It's just consistency. Same environment, same dependencies, same behavior—whether you're running on your gaming PC, a $5 VPS, or an enterprise Kubernetes cluster.
What Docker Actually Does
Docker wraps your application with everything it needs (Node.js, system libraries, native modules) into an image. That image runs the same way everywhere. No surprises. No "works on my machine" excuses.
Why Bother With Containers?
Because you have better things to do than fight with package managers at 3 AM trying to get sodium-native to compile.
Docker gives you instant setup where you don't need to manually install Node.js v22+. No hunting down build tools for native modules. No dependency resolution nightmares. Just pull the image and run. Your NodeLink instance lives in perfect isolation, in its own world where it can't interfere with your system and nothing can interfere with it. Clean slate every time you start it.
Updates become trivial. New version? Just docker compose pull && docker compose up -d and you're done. Need to rollback? Same commands, different tag. The portability is real too—it runs on Linux, Windows, macOS, ARM, x86, cloud, bare metal. If Docker exists there, NodeLink runs there.
Zero Native Build Issues
Native modules like sodium-native for encryption are already compiled in the image. No gcc, no python, no build-essential needed.
Worker Architecture Ready
The image is optimized for NodeLink's worker-based architecture. Cluster mode works out of the box without manual configuration.
Production Hardened
Health checks, restart policies, and security best practices are configured. Not something you cobbled together from a tutorial.
True Portability
The same image that runs on your laptop runs in production. No environment-specific bugs. No surprise differences.
The Setup Is Already Done
The NodeLink repository includes a production-ready Docker setup. No assembly required.
We already built a multi-stage Dockerfile that compiles native modules in a build stage and copies only what's needed to the runtime stage. The result is a lean image optimized for size and security. The docker-compose.yml includes every single configuration option NodeLink supports, all documented inline with examples. Health checks verify NodeLink is actually responding, not just that the container is running. Restart policies ensure it comes back up automatically if it crashes. Volume mounts are configured for local music files and log persistence.
You don't need to piece this together yourself. You don't need to understand Docker internals. Just clone the repo, adjust the handful of settings that matter to you, and launch.
Getting Started
Install Docker
You need Docker and Docker Compose. If you don't have them yet, get them from the official sources.
For Ubuntu/Debian, use the official Docker repository for the latest version:
# Add Docker's official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# Add Docker repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker Engine
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-pluginFor other distributions, check the official installation guide.
Download and install Docker Desktop for Windows from docker.com.
Docker Desktop includes both Docker Engine and Docker Compose. After installation, you'll need to restart your computer.
Make sure WSL2 is enabled if you're on Windows 10/11. Docker Desktop will prompt you to install it if needed.
Download and install Docker Desktop for Mac from docker.com.
Docker Desktop includes both Docker Engine and Docker Compose. Works on both Intel and Apple Silicon Macs.
Verify everything is working:
docker --version
docker compose versionIf both commands output version numbers, you're ready.
Clone NodeLink
Get the repository to your machine:
git clone https://github.com/PerformanC/NodeLink.git
cd NodeLinkYou now have everything. The Dockerfile, the docker-compose.yml, all of it.
Configure Your Instance
Open docker-compose.yml in your editor. You'll see a massive file with every configuration option documented. Most of it you can leave as-is. Here's what you must change:
environment:
NODELINK_SERVER_PASSWORD: "youshallnotpass" # ⚠️ CHANGE THIS NOWDon't Skip This
Using the default password in production is like leaving your front door open with a sign that says "free stuff inside." Change it. Use something long and random.
Optional but recommended configurations depend on what you need:
If you want Spotify support, you'll need credentials from the Spotify Developer Dashboard:
NODELINK_SOURCES_SPOTIFY_ENABLED: "true"
NODELINK_SOURCES_SPOTIFY_CLIENTID: "your_actual_spotify_client_id"
NODELINK_SOURCES_SPOTIFY_CLIENTSECRET: "your_actual_spotify_client_secret"If you want better YouTube support (helps with age-restricted and some region-locked content), get a token from cipher.kikkia.dev:
NODELINK_SOURCES_YOUTUBE_CIPHER_TOKEN: "your_cipher_token"If you want to use all your CPU cores for better performance under load, enable cluster mode:
NODELINK_CLUSTER_ENABLED: "true"
NODELINK_CLUSTER_WORKERS: "0" # 0 means use all available CPU coresEverything else has sensible defaults. You can explore the 200+ other options in the file when you need them.
Launch It
One command:
docker compose up -dDocker will build the NodeLink image from the Dockerfile, compile native modules, install dependencies, and start the server. The -d flag runs it in detached mode (background).
This takes a few minutes the first time while it builds the image. Subsequent starts are instant.
Verify It's Alive
Check if NodeLink is responding:
curl http://localhost:2333/versionYou should see version information. If you do, NodeLink is running and ready to connect to your Discord bot.
If something went wrong, check the logs:
docker compose logs -f nodelinkThe -f flag follows the logs in real-time. Press Ctrl+C to exit.
Understanding the Configuration
The docker-compose.yml file is massive because it exposes every single configuration option NodeLink supports as environment variables. Most of them you'll never touch. Here's what's actually in there:
Common Operations
Commands you'll use regularly:
# Start NodeLink in background
docker compose up -d
# Stop NodeLink
docker compose down
# Restart NodeLink (reload config changes)
docker compose restart
# Check if running
docker compose ps# View logs (follow mode)
docker compose logs -f nodelink
# View last 100 lines
docker compose logs --tail=100 nodelink
# View logs from specific time
docker compose logs --since 30m nodelink# Update to latest version
cd NodeLink
git pull
docker compose up -d --build
# Or using Docker Hub images
docker compose pull
docker compose up -d# Access container shell
docker compose exec nodelink sh
# Run commands inside container
docker compose exec nodelink npm run --versionUsing Pre-built Images
Don't want to build from source every time? Use the pre-built images from Docker Hub:
services:
nodelink:
image: performanc/nodelink:latest
# ... rest of your config ...Available tags:
latest
Most recent stable release. Updated with each new version. Safe for production.
v3.1.1
Specific version tags. Pin to a version for consistency. Useful when you want predictable behavior.
dev
Bleeding edge from main branch. Gets new features first. May break occasionally. Not for production.
Using pre-built images means faster deployments. No compile time. Just pull and run. The tradeoff is slightly larger images since they're built for multiple architectures.
Local Music Files
Want to play music from your server's hard drive? NodeLink's local source lets you stream files directly from the filesystem.
Create Music Directory
Make a folder for your music files:
mkdir local-musicPut your audio files there. NodeLink supports common formats like MP3, FLAC, WAV, OGG, M4A, and more.
Mount Volume
Edit your docker-compose.yml to mount the directory:
services:
nodelink:
volumes:
- ./local-music:/app/music
environment:
NODELINK_SOURCES_LOCAL_ENABLED: "true"
NODELINK_SOURCES_LOCAL_BASEPATH: "/app/music/"The volume mount makes your local-music folder appear inside the container at /app/music. The basepath tells NodeLink where to look for files.
Load Tracks
Restart NodeLink to apply changes:
docker compose restartNow you can load tracks using the file:// protocol:
file:///app/music/song.mp3
file:///app/music/albums/album1/track.flacThe path must start with the basepath you configured. NodeLink resolves the file and streams it like any other source.
Security Note
Local file access is powerful but requires careful configuration. NodeLink validates paths to prevent directory traversal attacks. Still, only enable this if you control the filesystem and know who can access the API.
Production Deployment
Running NodeLink in production requires a few extra considerations beyond just starting the container.
Reverse Proxy Setup
NodeLink should sit behind a reverse proxy in production for SSL termination and security. Here's an Nginx example:
server {
listen 80;
server_name audio.yourdomain.com;
# Redirect HTTP to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name audio.yourdomain.com;
# SSL certificates (use certbot for Let's Encrypt)
ssl_certificate /etc/letsencrypt/live/audio.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/audio.yourdomain.com/privkey.pem;
location / {
proxy_pass http://localhost:2333;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support
proxy_read_timeout 86400;
}
}This configuration handles HTTPS, WebSocket upgrades, and proper header forwarding. Get SSL certificates from Let's Encrypt using certbot. It's free and automated.
Resource Limits
Prevent NodeLink from consuming all system resources if something goes wrong:
services:
nodelink:
deploy:
resources:
limits:
cpus: '2.0' # Max 2 CPU cores
memory: 2G # Max 2GB RAM
reservations:
cpus: '0.5' # Reserve half a core
memory: 512M # Reserve 512MB RAMThese limits depend on your player count. More simultaneous players need more resources. Monitor actual usage and adjust accordingly.
Health Checks
Docker can monitor if NodeLink is actually responding, not just that the container is running:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:2333/version"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40sIf the health check fails three times, Docker marks the container as unhealthy. Combined with restart policies, this provides automatic recovery from crashes or hangs.
Firewall Configuration
If NodeLink runs on a remote server, allow incoming connections:
# UFW (Ubuntu/Debian)
sudo ufw allow 2333/tcp
# firewalld (CentOS/RHEL)
sudo firewall-cmd --add-port=2333/tcp --permanent
sudo firewall-cmd --reloadOnly open ports you actually use. If NodeLink is behind a reverse proxy, you might only need to open 80/443 for the proxy and keep 2333 local-only.
Security Checklist
Before going live, verify these points:
Troubleshooting
Container Won't Start
Check the logs for specific errors:
docker compose logs nodelinkCommon problems and fixes:
Port already in use: Something else is listening on 2333. Either stop that process or change NodeLink's port in docker-compose.yml:
ports:
- "2334:2333" # Use 2334 externally, 2333 internallyPermission denied: Docker doesn't have permission to bind the port or access volumes. On Linux, add your user to the docker group:
sudo usermod -aG docker $USERLog out and back in for the change to take effect.
Invalid configuration: Check for typos in docker-compose.yml. YAML is whitespace-sensitive. Use a validator if unsure.
Can't Connect from Discord Bot
First, verify NodeLink is accessible from outside the container:
curl http://your-server-ip:2333/versionIf this fails, check your firewall rules. If it succeeds but your bot still can't connect, verify the password matches between your bot config and docker-compose.yml.
For remote servers, ensure the firewall allows incoming connections:
sudo ufw statusThe port (default 2333) should be listed as allowed.
High CPU Usage
Check how many players are active:
curl http://localhost:2333/v4/stats -H "Authorization: yourPassword"Look at the players and playingPlayers counts. High CPU with many players is normal. If CPU is high with few players, enable cluster mode:
NODELINK_CLUSTER_ENABLED: "true"
NODELINK_CLUSTER_WORKERS: "0" # Use all coresRestart after changing the config.
Audio Cutting Out
This usually indicates network issues or event loop blocking. Check frame statistics in the stats endpoint:
curl http://localhost:2333/v4/stats -H "Authorization: yourPassword"Look at frameStats. If deficit is positive or nulled is increasing, audio is being dropped. Try increasing the update interval:
NODELINK_PLAYERUPDATEINTERVAL: "1000"Also check network latency between your server and Discord voice servers. High latency causes problems.
Memory Growing Over Time
External memory grows with active players. This is normal. Each player holds audio buffers for smooth playback. Memory should stabilize once player count is constant. If memory keeps growing even without new players, that might indicate a leak. Report it with logs and reproduction steps.
The Real Talk
Docker makes deploying NodeLink almost trivial. You don't need to be a DevOps expert. You don't need to understand multi-stage builds or image layers or any of that.
The repository already has everything configured. A production-ready Dockerfile optimized for NodeLink's native modules and worker architecture. A comprehensive docker-compose.yml with every option documented. Health checks and restart policies. Security features enabled by default.
Just clone it, change the password, and run docker compose up -d. That's literally the deployment process.
Everything else in this document is optional. The defaults work. The configuration makes sense. The security is reasonable. You can deploy NodeLink to production with a handful of environment variables and be confident it'll run reliably.
You can go from zero to streaming audio in about 5 minutes.
What's Next?
Now that NodeLink is containerized and running:
Connect Your Bot
Point your Discord bot at your NodeLink instance. Use the WebSocket API to manage players.
Configure Sources
Enable Spotify, Apple Music, or other sources. Configure API keys and credentials.
Set Up Monitoring
Add Prometheus metrics and Grafana dashboards. Know exactly how your instance is performing.
Explore Features
Try lyrics support, chapter markers, direct streaming, and NodeLink-exclusive filters.
The code is open. The configs are documented. The community is active. Go build something cool with it. 💙