DOCKER-STREAMING.org
1 #+TITLE: Asteroid Radio - Docker Streaming Setup 2 #+AUTHOR: Asteroid Radio Development Team 3 #+DATE: 2025-10-26 4 5 * Docker Streaming Overview 6 7 This guide covers the complete Docker-based streaming setup for Asteroid Radio using Icecast2 and Liquidsoap containers. This approach provides a containerized, portable streaming infrastructure that's easy to deploy and maintain. 8 9 #+BEGIN_QUOTE 10 *Note on Package Managers*: Examples use =apt= (Debian/Ubuntu). Replace with your distribution's package manager (=dnf=, =pacman=, =zypper=, =apk=, etc.). 11 #+END_QUOTE 12 13 * Architecture 14 15 ** Container Stack 16 - *Icecast2 Container*: Streaming server handling client connections 17 - *Liquidsoap Container*: Audio processing and stream generation 18 - *Shared Volumes*: Music library and configuration sharing 19 20 ** Stream Formats 21 - *High Quality MP3*: 128kbps MP3 stream at /asteroid.mp3 22 - *High Quality AAC*: 96kbps AAC stream at /asteroid.aac (better efficiency than MP3) 23 - *Low Quality MP3*: 64kbps MP3 stream at /asteroid-low.mp3 (compatibility) 24 25 ** Network Configuration 26 - *Icecast2*: Port 8000 (streaming and admin) 27 - *Liquidsoap Telnet*: Port 1234 (remote control) 28 - *Internal Network*: Container-to-container communication 29 30 * Quick Start 31 32 ** Prerequisites 33 #+BEGIN_SRC bash 34 # Install Docker and Docker Compose 35 sudo apt update 36 sudo apt install docker.io docker compose 37 sudo usermod -a -G docker $USER 38 # Log out and back in for group changes 39 #+END_SRC 40 41 ** One-Command Setup 42 #+BEGIN_SRC bash 43 # Clone and start 44 git clone https://github.com/fade/asteroid asteroid-radio 45 cd asteroid-radio/docker 46 docker compose up -d 47 #+END_SRC 48 49 ** Verify Setup 50 #+BEGIN_SRC bash 51 # Check container status 52 docker compose ps 53 54 # Test streaming (all three formats) 55 curl -I http://localhost:8000/asteroid.mp3 # 128kbps MP3 56 curl -I http://localhost:8000/asteroid.aac # 96kbps AAC 57 curl -I http://localhost:8000/asteroid-low.mp3 # 64kbps MP3 58 #+END_SRC 59 60 * Docker Compose Configuration 61 62 ** Complete docker-compose.yml 63 #+BEGIN_SRC yaml 64 version: '3.8' 65 66 services: 67 icecast: 68 image: infiniteproject/icecast:latest 69 container_name: asteroid-icecast 70 ports: 71 - "8000:8000" 72 volumes: 73 - ./icecast.xml:/etc/icecast.xml 74 environment: 75 - ICECAST_SOURCE_PASSWORD=H1tn31EhsyLrfRmo 76 - ICECAST_ADMIN_PASSWORD=asteroid_admin_2024 77 - ICECAST_RELAY_PASSWORD=asteroid_relay_2024 78 restart: unless-stopped 79 networks: 80 - asteroid-network 81 82 liquidsoap: 83 build: 84 context: . 85 dockerfile: Dockerfile.liquidsoap 86 container_name: asteroid-liquidsoap 87 ports: 88 - "1234:1234" # Telnet control port 89 depends_on: 90 - icecast 91 volumes: 92 - ./music:/app/music:ro 93 - ./asteroid-radio-docker.liq:/app/asteroid-radio.liq:ro 94 restart: unless-stopped 95 networks: 96 - asteroid-network 97 98 networks: 99 asteroid-network: 100 driver: bridge 101 #+END_SRC 102 103 * Container Configurations 104 105 ** Icecast2 Container Setup 106 107 *** Custom Icecast Configuration (icecast.xml) 108 #+BEGIN_SRC xml 109 <icecast> 110 <location>Asteroid Radio Docker</location> 111 <admin>admin@asteroid-radio.docker</admin> 112 113 <limits> 114 <clients>100</clients> 115 <sources>10</sources> 116 <queue-size>524288</queue-size> 117 <client-timeout>30</client-timeout> 118 <header-timeout>15</header-timeout> 119 <source-timeout>10</source-timeout> 120 <burst-on-connect>1</burst-on-connect> 121 </limits> 122 123 <authentication> 124 <source-password>H1tn31EhsyLrfRmo</source-password> 125 <relay-password>asteroid_relay_2024</relay-password> 126 <admin-user>admin</admin-user> 127 <admin-password>asteroid_admin_2024</admin-password> 128 </authentication> 129 130 <hostname>icecast</hostname> 131 <listen-socket> 132 <port>8000</port> 133 <bind-address>0.0.0.0</bind-address> 134 </listen-socket> 135 136 <!-- High Quality Stream --> 137 <mount type="normal"> 138 <mount-name>/asteroid.mp3</mount-name> 139 <username>source</username> 140 <password>H1tn31EhsyLrfRmo</password> 141 <max-listeners>50</max-listeners> 142 <public>1</public> 143 <stream-name>Asteroid Radio - High Quality</stream-name> 144 <stream-url>http://localhost:8080/asteroid/</stream-url> 145 <genre>Electronic/Alternative</genre> 146 <bitrate>128</bitrate> 147 </mount> 148 149 <!-- AAC High Quality Stream --> 150 <mount type="normal"> 151 <mount-name>/asteroid.aac</mount-name> 152 <username>source</username> 153 <password>H1tn31EhsyLrfRmo</password> 154 <max-listeners>50</max-listeners> 155 <public>1</public> 156 <stream-name>Asteroid Radio - AAC</stream-name> 157 <stream-description>Music for Hackers - 96kbps AAC</stream-description> 158 <stream-url>http://localhost:8080/asteroid/</stream-url> 159 <genre>Electronic/Alternative</genre> 160 <bitrate>96</bitrate> 161 </mount> 162 163 <!-- Low Quality Stream --> 164 <mount type="normal"> 165 <mount-name>/asteroid-low.mp3</mount-name> 166 <username>source</username> 167 <password>H1tn31EhsyLrfRmo</password> 168 <max-listeners>100</max-listeners> 169 <public>1</public> 170 <stream-name>Asteroid Radio - Low Quality</stream-name> 171 <stream-description>Music for Hackers - 64kbps</stream-description> 172 <stream-url>http://localhost:8080/asteroid/</stream-url> 173 <genre>Electronic/Alternative</genre> 174 <bitrate>64</bitrate> 175 </mount> 176 177 <fileserve>1</fileserve> 178 <paths> 179 <basedir>/usr/share/icecast2</basedir> 180 <logdir>/var/log/icecast2</logdir> 181 <webroot>/usr/share/icecast2/web</webroot> 182 <adminroot>/usr/share/icecast2/admin</adminroot> 183 <alias source="/" destination="/status.xsl"/> 184 </paths> 185 186 <logging> 187 <accesslog>access.log</accesslog> 188 <errorlog>error.log</errorlog> 189 <loglevel>3</loglevel> 190 <logsize>10000</logsize> 191 </logging> 192 </icecast> 193 #+END_SRC 194 195 ** Liquidsoap Container Setup 196 197 *** Liquidsoap Configuration (asteroid-radio-docker.liq) 198 #+BEGIN_SRC liquidsoap 199 #!/usr/bin/liquidsoap 200 201 # Asteroid Radio - Docker streaming script 202 # Streams music library continuously to Icecast2 running in Docker 203 204 # Allow running as root in Docker 205 set("init.allow_root", true) 206 207 # Set log level for debugging 208 log.level.set(4) 209 210 # Enable telnet server for remote control 211 settings.server.telnet.set(true) 212 settings.server.telnet.port.set(1234) 213 settings.server.telnet.bind_addr.set("0.0.0.0") 214 215 # Create playlist source from mounted music directory 216 radio = playlist( 217 mode="randomize", 218 reload=3600, 219 reload_mode="watch", 220 "/app/music/" 221 ) 222 223 # Add some audio processing 224 radio = amplify(1.0, radio) 225 radio = normalize(radio) 226 227 # Add crossfade between tracks 228 radio = crossfade(radio) 229 230 # Create a fallback with emergency content 231 emergency = sine(440.0) 232 emergency = amplify(0.1, emergency) 233 234 # Make source safe with fallback 235 radio = fallback(track_sensitive=false, [radio, emergency]) 236 237 # Add metadata 238 radio = map_metadata(fun(m) -> 239 [("title", m["title"] ?? "Unknown Track"), 240 ("artist", m["artist"] ?? "Unknown Artist"), 241 ("album", m["album"] ?? "Unknown Album")], radio) 242 243 # High Quality MP3 Stream (128kbps) 244 output.icecast( 245 %mp3(bitrate=128), 246 host="icecast", # Docker service name 247 port=8000, 248 password="H1tn31EhsyLrfRmo", 249 mount="asteroid.mp3", 250 name="Asteroid Radio", 251 description="Music for Hackers - Streaming from the Asteroid", 252 genre="Electronic/Alternative", 253 url="http://localhost:8080/asteroid/", 254 public=true, 255 radio 256 ) 257 258 # AAC High Quality Stream (96kbps - better quality than 128kbps MP3) 259 output.icecast( 260 %fdkaac(bitrate=96), 261 host="icecast", 262 port=8000, 263 password="H1tn31EhsyLrfRmo", 264 mount="asteroid.aac", 265 name="Asteroid Radio (AAC)", 266 description="Music for Hackers - High efficiency AAC stream", 267 genre="Electronic/Alternative", 268 url="http://localhost:8080/asteroid/", 269 public=true, 270 radio 271 ) 272 273 # Low Quality MP3 Stream (for compatibility) 274 output.icecast( 275 %mp3(bitrate=64), 276 host="icecast", 277 port=8000, 278 password="H1tn31EhsyLrfRmo", 279 mount="asteroid-low.mp3", 280 name="Asteroid Radio (Low Quality)", 281 description="Music for Hackers - Low bandwidth stream", 282 genre="Electronic/Alternative", 283 url="http://localhost:8080/asteroid/", 284 public=true, 285 radio 286 ) 287 288 print("๐ต Asteroid Radio Docker streaming started!") 289 print("High Quality MP3: http://localhost:8000/asteroid.mp3") 290 print("High Quality AAC: http://localhost:8000/asteroid.aac") 291 print("Low Quality MP3: http://localhost:8000/asteroid-low.mp3") 292 print("Icecast Admin: http://localhost:8000/admin/") 293 print("Telnet control: telnet localhost 1234") 294 #+END_SRC 295 296 297 * Management Scripts 298 299 ** Start Script (start-streaming.sh) 300 #+BEGIN_SRC bash 301 #!/bin/bash 302 303 # Asteroid Radio Docker Streaming Startup Script 304 305 set -e 306 307 echo "๐ Starting Asteroid Radio Docker Streaming..." 308 309 # Check if Docker is running 310 if ! docker info > /dev/null 2>&1; then 311 echo "โ Docker is not running. Please start Docker first." 312 exit 1 313 fi 314 315 # Create required directories 316 mkdir -p music/incoming music/library logs 317 318 # Set permissions 319 chmod 755 music/incoming music/library 320 chmod 777 logs 321 322 # Pull latest images 323 echo "๐ฆ Pulling latest Docker images..." 324 docker compose pull 325 326 # Start services 327 echo "๐ต Starting streaming services..." 328 docker compose up -d 329 330 # Wait for services to be ready 331 echo "โณ Waiting for services to start..." 332 sleep 10 333 334 # Check service status 335 echo "๐ Checking service status..." 336 docker compose ps 337 338 # Test connectivity 339 echo "๐ Testing streaming connectivity..." 340 if curl -s -I http://localhost:8000/asteroid.mp3 | grep -q "200 OK"; then 341 echo "โ High quality stream is working" 342 else 343 echo "โ ๏ธ High quality stream may not be ready yet" 344 fi 345 346 if curl -s -I http://localhost:8000/asteroid-low.mp3 | grep -q "200 OK"; then 347 echo "โ Low quality MP3 stream is working" 348 else 349 echo "โ ๏ธ Low quality MP3 stream may not be ready yet" 350 fi 351 352 if curl -s -I http://localhost:8000/asteroid.aac | grep -q "200 OK"; then 353 echo "โ AAC stream is working" 354 else 355 echo "โ ๏ธ AAC stream may not be ready yet" 356 fi 357 358 echo "" 359 echo "๐ Asteroid Radio Docker setup complete!" 360 echo "" 361 echo "๐ป Stream URLs:" 362 echo " High Quality MP3: http://localhost:8000/asteroid.mp3 (128kbps)" 363 echo " High Quality AAC: http://localhost:8000/asteroid.aac (96kbps)" 364 echo " Low Quality MP3: http://localhost:8000/asteroid-low.mp3 (64kbps)" 365 echo "" 366 echo "๐ง Admin Interfaces:" 367 echo " Icecast: http://localhost:8000/admin/ (admin/asteroid_admin_2024)" 368 echo " Telnet: telnet localhost 1234" 369 echo "" 370 echo "๐ Add music files to: ./music/" 371 echo " Files are automatically detected and streamed." 372 #+END_SRC 373 374 ** Stop Script (stop-streaming.sh) 375 #+BEGIN_SRC bash 376 #!/bin/bash 377 378 # Asteroid Radio Docker Streaming Stop Script 379 380 echo "๐ Stopping Asteroid Radio Docker Streaming..." 381 382 # Stop all services 383 docker compose down 384 385 # Optional: Remove volumes (uncomment to clean up completely) 386 # docker compose down -v 387 388 echo "โ All services stopped." 389 #+END_SRC 390 391 ** Test Script (test-streaming.sh) 392 #+BEGIN_SRC bash 393 #!/bin/bash 394 395 # Asteroid Radio Docker Streaming Test Script 396 397 echo "๐งช Testing Asteroid Radio Docker Setup..." 398 399 # Test container status 400 echo "๐ Container Status:" 401 docker compose ps 402 403 echo "" 404 echo "๐ Testing Connectivity:" 405 406 # Test Icecast2 407 if curl -s -I http://localhost:8000/ | grep -q "200 OK"; then 408 echo "โ Icecast2 server is responding" 409 else 410 echo "โ Icecast2 server is not responding" 411 fi 412 413 # Test high quality stream 414 if curl -s -I http://localhost:8000/asteroid.mp3 | grep -q "200 OK"; then 415 echo "โ High quality stream is available" 416 else 417 echo "โ High quality stream is not available" 418 fi 419 420 # Test low quality stream 421 if curl -s -I http://localhost:8000/asteroid-low.mp3 | grep -q "200 OK"; then 422 echo "โ Low quality MP3 stream is available" 423 else 424 echo "โ Low quality MP3 stream is not available" 425 fi 426 427 # Test AAC stream 428 if curl -s -I http://localhost:8000/asteroid.aac | grep -q "200 OK"; then 429 echo "โ AAC stream is available" 430 else 431 echo "โ AAC stream is not available" 432 fi 433 434 echo "" 435 echo "๐ Service Logs (last 10 lines):" 436 echo "--- Icecast2 ---" 437 docker compose logs --tail=10 icecast 438 439 echo "--- Liquidsoap ---" 440 docker compose logs --tail=10 liquidsoap 441 442 #+END_SRC 443 444 * Volume Management 445 446 ** Music Library Setup 447 #+BEGIN_SRC bash 448 # Music directory already exists in repository 449 # Copy sample music directly to the music directory 450 cp ~/path/to/music/*.mp3 docker/music/ 451 452 # Set permissions 453 chmod 755 docker/music/ 454 sudo chown -R $USER:$USER docker/music/ 455 #+END_SRC 456 457 ** Persistent Data 458 - *Music Library*: =./music/= - Mounted as volume 459 - *Logs*: =./logs/= - Container logs and streaming logs 460 - *Configuration*: =./liquidsoap/= and =./icecast.xml= - Read-only configs 461 462 * Networking 463 464 ** Internal Container Network 465 - Containers communicate via =asteroid-network= bridge 466 - Liquidsoap connects to Icecast using hostname =icecast= 467 - Telnet control available on port 1234 for Liquidsoap management 468 469 ** External Access 470 - *Port 8000*: Icecast2 streaming and admin interface 471 - *Port 1234*: Liquidsoap telnet control interface 472 - All services bind to =0.0.0.0= for external access 473 474 ** WSL Compatibility 475 #+BEGIN_SRC bash 476 # Find WSL IP for external access 477 ip addr show eth0 | grep inet 478 479 # Access from Windows host 480 # http://[IP-ADDRESS]:8000/asteroid.mp3 # 128kbps MP3 481 # http://[IP-ADDRESS]:8000/asteroid.aac # 96kbps AAC 482 # http://[IP-ADDRESS]:8000/asteroid-low.mp3 # 64kbps MP3 483 #+END_SRC 484 485 * Production Deployment 486 487 ** Docker Swarm Setup 488 #+BEGIN_SRC yaml 489 # docker compose.prod.yml 490 version: '3.8' 491 492 services: 493 icecast: 494 image: moul/icecast 495 deploy: 496 replicas: 1 497 restart_policy: 498 condition: on-failure 499 # ... rest of configuration 500 501 liquidsoap: 502 image: savonet/liquidsoap:v2.2.x 503 deploy: 504 replicas: 1 505 restart_policy: 506 condition: on-failure 507 # ... rest of configuration 508 #+END_SRC 509 510 ** Environment Variables 511 #+BEGIN_SRC bash 512 # Production environment 513 export ASTEROID_ENV=production 514 export ASTEROID_STREAM_QUALITY=high 515 export ASTEROID_MAX_LISTENERS=200 516 export ICECAST_ADMIN_PASSWORD=secure_password_here 517 #+END_SRC 518 519 ** SSL/TLS Setup 520 Use reverse proxy (nginx/traefik) for HTTPS termination: 521 #+BEGIN_SRC yaml 522 # Add to docker-compose.yml 523 nginx: 524 image: nginx:alpine 525 ports: 526 - "80:80" 527 - "443:443" 528 volumes: 529 - ./nginx.conf:/etc/nginx/nginx.conf:ro 530 - ./ssl:/etc/ssl:ro 531 #+END_SRC 532 533 * Monitoring and Logging 534 535 ** Container Health Checks 536 #+BEGIN_SRC bash 537 # Check container health 538 docker compose exec icecast curl -f http://localhost:8000/status.xsl 539 docker compose exec liquidsoap ps aux | grep liquidsoap 540 541 # Test telnet control interface 542 echo "help" | nc localhost 1234 543 #+END_SRC 544 545 ** Log Management 546 #+BEGIN_SRC bash 547 # View real-time logs 548 docker compose logs -f 549 550 # View specific service logs 551 docker compose logs -f icecast 552 docker compose logs -f liquidsoap 553 554 # Log rotation setup 555 docker run --log-driver=json-file --log-opt max-size=10m --log-opt max-file=3 556 #+END_SRC 557 558 * Troubleshooting 559 560 ** Common Docker Issues 561 562 *** Container Won't Start 563 #+BEGIN_SRC bash 564 # Check container logs 565 docker compose logs [service-name] 566 567 # Check resource usage 568 docker stats 569 570 # Verify configuration files 571 docker compose config 572 #+END_SRC 573 574 *** Streaming Issues 575 #+BEGIN_SRC bash 576 # Test internal connectivity 577 docker compose exec liquidsoap ping icecast 578 579 # Check Liquidsoap connection and logs 580 docker compose logs liquidsoap 581 582 # Test telnet interface 583 echo "request.queue" | nc localhost 1234 584 #+END_SRC 585 586 *** Permission Issues 587 #+BEGIN_SRC bash 588 # Fix music directory permissions 589 sudo chown -R $USER:$USER docker/music/ 590 chmod 755 docker/music/ 591 #+END_SRC 592 593 ** Performance Tuning 594 595 *** Resource Limits 596 #+BEGIN_SRC yaml 597 # Add to services in docker-compose.yml 598 deploy: 599 resources: 600 limits: 601 memory: 512M 602 cpus: '0.5' 603 reservations: 604 memory: 256M 605 cpus: '0.25' 606 #+END_SRC 607 608 *** Network Optimization 609 #+BEGIN_SRC yaml 610 # Optimize network settings 611 networks: 612 asteroid-network: 613 driver: bridge 614 driver_opts: 615 com.docker.network.driver.mtu: 1500 616 #+END_SRC 617 618 This Docker streaming setup provides a complete containerized solution for Asteroid Radio with professional streaming capabilities and easy deployment.