A Discord music bot powered by Lavalink. Simple to deploy, easy to use.
- Features
- Quick Start
- Commands
- Configuration
- Managing the Bot
- Troubleshooting
- Built With
- Contributing
- Links
- License
- Play music from YouTube, SoundCloud, Bandcamp, Twitch, and Vimeo
- Optional Spotify support (search and resolve via YouTube)
- Autoplay mode for continuous music playback
- Queue management with shuffle, loop, and play-next
- Interactive search with track selection
- Multi-language support (English, Spanish, Turkish, Italian, Brazilian Portuguese)
- Role-based access control
- Runs entirely in Docker, no host dependencies
- Works without a self-hosted Lavalink server (automatic public server fallback)
- A Discord bot token from the Developer Portal
- Docker installed
When creating your bot, enable all 3 Privileged Gateway Intents (Presence, Server Members, Message Content).
Uses the pre-built GHCR image, no cloning needed.
1. Create a project directory:
mkdir beatdock && cd beatdock2. Create .env:
TOKEN=your_discord_bot_token3. Create docker-compose.yml:
services:
bot:
container_name: beatdock
image: ghcr.io/lazaroagomez/beatdock:latest
depends_on:
lavalink:
condition: service_healthy
networks:
- beatdock-network
env_file: .env
lavalink:
container_name: beatdock-lavalink
image: ghcr.io/lavalink-devs/lavalink:4
ports:
- "2333:2333"
networks:
- beatdock-network
volumes:
- ./application.yml:/opt/Lavalink/application.yml
environment:
- LAVALINK_PASSWORD=${LAVALINK_PASSWORD:-youshallnotpass}
- SPOTIFY_ENABLED=${SPOTIFY_ENABLED:-false}
- SPOTIFY_CLIENT_ID=${SPOTIFY_CLIENT_ID:-}
- SPOTIFY_CLIENT_SECRET=${SPOTIFY_CLIENT_SECRET:-}
healthcheck:
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/2333'"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
networks:
beatdock-network:
name: beatdock_network4. Create application.yml:
server:
port: 2333
address: 0.0.0.0
plugins:
youtube:
enabled: true
allowSearch: true
allowDirectVideoIds: true
allowDirectPlaylistIds: true
clients:
- MUSIC
- WEB
- ANDROID_VR
lavalink:
plugins:
- dependency: "dev.lavalink.youtube:youtube-plugin:1.16.0"
snapshot: false
server:
password: "${LAVALINK_PASSWORD:youshallnotpass}"
sources:
youtube: false
soundcloud: true
bandcamp: true
twitch: true
vimeo: true
http: true
local: false
bufferDurationMs: 200
frameBufferDurationMs: 1000
youtubePlaylistLoadLimit: 3
playerUpdateInterval: 2
trackStuckThresholdMs: 5000
useSeekGhosting: true
youtubeSearchEnabled: true
logging:
level:
root: INFO
lavalink: INFO5. Deploy:
docker compose up -dgit clone https://github.com/lazaroagomez/BeatDock.git
cd BeatDockCreate .env with your credentials (see .env.example for all options):
TOKEN=your_discord_bot_tokendocker compose up -dBeatDock can run without a self-hosted Lavalink server. If LAVALINK_HOST, LAVALINK_PORT, and LAVALINK_PASSWORD are not set, the bot automatically fetches free public Lavalink v4 servers and connects to one. If a public server goes down, it rotates to the next available node.
To use public servers, simply comment out the Lavalink variables in your .env:
# LAVALINK_HOST=lavalink
# LAVALINK_PORT=2333
# LAVALINK_PASSWORD=youshallnotpass| Command | Description |
|---|---|
/play <query> [next] |
Play a song (optionally add to front of queue) |
/search <query> |
Search and select tracks |
/pause |
Pause/resume |
/skip |
Skip track |
/back |
Previous track |
/stop |
Stop and disconnect |
/queue |
Show queue |
/shuffle |
Shuffle queue |
/autoplay |
Toggle autoplay mode |
/loop |
Toggle loop mode |
/clear |
Clear queue |
/volume <1-100> |
Set volume |
/lyrics |
Show lyrics for the current song |
/filter |
Apply audio effects and EQ presets |
/nowplaying |
Current track info |
/invite |
Get bot invite link |
/about |
Bot info |
All configuration is done through the .env file. Only TOKEN is required.
| Variable | Default | Description |
|---|---|---|
TOKEN |
- | Discord bot token (required) |
SPOTIFY_ENABLED |
false |
Enable Spotify search support |
SPOTIFY_CLIENT_ID |
- | Spotify app client ID |
SPOTIFY_CLIENT_SECRET |
- | Spotify app client secret |
DEFAULT_LANGUAGE |
en |
Bot language (en, es, tr, it, pt-BR) |
DEFAULT_VOLUME |
80 |
Default playback volume (0-100) |
AUTOPLAY_DEFAULT |
false |
Enable autoplay by default when music starts |
ALLOWED_ROLES |
- | Comma-separated role IDs to restrict access |
DEFAULT_SEARCH_PLATFORM |
ytmsearch |
Default search platform for user queries |
LAVALINK_PASSWORD |
youshallnotpass |
Lavalink server password |
QUEUE_EMPTY_DESTROY_MS |
30000 |
Disconnect after queue empties (ms) |
EMPTY_CHANNEL_DESTROY_MS |
60000 |
Disconnect from empty channel (ms) |
docker compose logs -f # View logs
docker compose restart # Restart
docker compose down # Stop
docker compose pull && docker compose up -d # UpdateRaspberry Pi 5 (Debian 13) may use a 16KB memory page size, which is incompatible with Lavalink's DAVE encryption library. Check with:
getconf PAGE_SIZEIf the result is not 4096, add kernel=kernel8.img under the [all] section in /boot/firmware/config.txt, then reboot and restart the containers. See #109 for details.
- discord.js - Discord API client
- Lavalink - Audio player server
- lavalink-client - Lavalink client library
- Docker - Containerized deployment
- Node.js 22+ - Runtime
Contributions are welcome. Bug fixes, new features, translations, docs - all good. Check the guide below to get started.
See CONTRIBUTING.md for setup instructions and guidelines.