SSD Nodes Learn Hosting plans →
Panduan Matt ConnorOleh Matt Connor · Dikemas kini 2026-08-28

Cara Setup Docker Compose untuk Prowlarr, Sonarr & Radarr

Gunakan fail Docker Compose tunggal untuk Prowlarr, Sonarr, Radarr dan qBittorrent. Panduan ini menunjukkan konfigurasi PUID, PGID dan volum yang betul agar hardlink berfungsi.

Apa yang anda bina

Susunan Docker Compose arr terdiri daripada empat kontena yang mengurus pustaka media: Prowlarr untuk tetapan pengindeks, Sonarr untuk siri TV, Radarr untuk filem, dan qBittorrent sebagai klien muat turun. Kontena-kontena ini berkomunikasi antara satu sama lain melalui rangkaian Compose menggunakan nama servis, dan mereka berkongsi satu struktur folder pada hos. Proses pemasangannya singkat. Bahagian yang menentukan sama ada susunan ini berfungsi untuk jangka masa panjang atau menimbulkan masalah setiap minggu ialah susunan volum, jadi sebahagian besar panduan ini tertumpu pada perkara tersebut.

Susunan ini tidak mencari kandungan untuk anda. Prowlarr menyimpan sebarang pengindeks yang anda tambah, dan pengindeks yang anda gunakan adalah keputusan serta tanggungjawab undang-undang anda sendiri. Panduan ini merangkumi aspek teknikal: pengguna, laluan, keizinan, rangkaian kontena, dan pemeriksaan untuk memastikan semuanya berfungsi.

Jika anda belum pernah menulis fail Compose, baca asas Docker Compose untuk VPS terlebih dahulu. Catatan ini mengandaikan docker compose version sudah memaparkan output pada pelayan anda.

Apabila Sonarr selesai memuat turun, ia mengimport fail tersebut ke dalam pustaka anda. Jika folder muat turun dan folder pustaka berada pada sistem fail yang sama, proses import tersebut adalah hardlink: nama kedua yang menunjuk kepada data yang sama pada cakera. Ia tidak mengambil ruang tambahan dan tidak mengambil masa. Torrent terus melakukan seeding daripada nama lama sementara pelayan media anda membaca daripada nama baharu.

Jika kedua-dua folder berada pada sistem fail yang berbeza, kernel tidak boleh membuat pautan tersebut. Sonarr akan beralih kepada proses salinan (copy). Satu musim bersaiz 40 GB kini mengambil 80 GB ruang cakera dan mengambil masa beberapa minit untuk proses input dan output, dan log import akan merekodkan bahawa hardlink gagal dan fail disalin sebagai ganti. Pada VPS dengan had cakera tetap, inilah punca ruang storan habis dalam masa seminggu.

Inilah perangkapnya. Di dalam kontena, bind mount merupakan sempadan sistem fail. Mount /mnt/data/torrents sebagai /downloads dan /mnt/data/media sebagai /tv, dan walaupun kedua-duanya berada pada satu cakera hos yang sama, Sonarr melihat dua mount yang berasingan dan enggan membuat pautan merentasinya. Dokumentasi imej rasmi LinuxServer.io menyatakan perkara ini secara terus: menggunakan laluan /downloads dan /tv yang berasingan akan mengorbankan keupayaan untuk melakukan hardlink.

Penyelesaiannya ialah satu mount sahaja. Setiap kontena yang mengakses media mendapat satu volum tunggal yang sama, /mnt/data:/data, dan setiap laluan yang digunakan adalah folder di dalamnya. Satu titik mount, satu sistem fail, hardlink berfungsi.

Cipta pengguna, kumpulan, dan folder

Kontena menulis fail sebagai ID pengguna berangka, yang ditetapkan oleh PUID dan PGID. Gunakan akaun anda sendiri supaya anda boleh membaca dan menyunting fail tersebut melalui SSH tanpa sudo.

id -u
id -g

Kedua-duanya biasanya mencetak 1000 pada VPS Ubuntu yang baharu. Sekarang, bina struktur direktori. Letakkannya pada mana-mana cakera yang menyimpan media anda, dan pastikan keseluruhan struktur tersebut berada pada cakera yang sama.

sudo mkdir -p /mnt/data/torrents/movies /mnt/data/torrents/tv
sudo mkdir -p /mnt/data/media/Movies /mnt/data/media/Shows
sudo chown -R 1000:1000 /mnt/data
sudo chmod -R 775 /mnt/data

Pastikan ia benar-benar berada pada satu sistem fail sebelum anda meneruskan:

df --output=source,target /mnt/data/torrents /mnt/data/media

Kedua-dua baris mesti menunjukkan peranti sumber yang sama. Dua peranti yang berbeza bermakna hardlink tidak akan berfungsi, walau apa pun yang anda tetapkan dalam konfigurasi kontena.

Folder pustaka dinamakan Movies dan Shows dengan sengaja. Jika anda sudah menjalankan Jellyfin sebagai pelayan media anda, lekapkan /mnt/data/media ke dalam Jellyfin sebagai /media dan pustakanya akan berada di /media/Movies dan /media/Shows, tepat di lokasi yang ditetapkan oleh panduan tersebut.

Fail persekitaran

Simpan nilai yang berubah mengikut pelayan di dalam .env, bersebelahan dengan fail Compose.

mkdir -p ~/arr && cd ~/arr

Tulis ~/arr/.env:

PUID=1000
PGID=1000
TZ=Etc/UTC
DATA_ROOT=/mnt/data

Tetapkan TZ kepada zon anda sendiri, contohnya Europe/Berlin. Aplikasi arr menjadualkan tugasan dan meletakkan cap masa pada baris log mengikut zon tersebut, jadi nilai yang salah akan menyebabkan setiap log mengelirukan pada masa hadapan.

Fail Compose

Tulis ~/arr/docker-compose.yml:

services:
  prowlarr:
    image: lscr.io/linuxserver/prowlarr:latest
    container_name: prowlarr
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - ./config/prowlarr:/config
    ports:
      - 127.0.0.1:9696:9696
    restart: unless-stopped

  sonarr:
    image: lscr.io/linuxserver/sonarr:latest
    container_name: sonarr
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - ./config/sonarr:/config
      - ${DATA_ROOT}:/data
    ports:
      - 127.0.0.1:8989:8989
    restart: unless-stopped

  radarr:
    image: lscr.io/linuxserver/radarr:latest
    container_name: radarr
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - ./config/radarr:/config
      - ${DATA_ROOT}:/data
    ports:
      - 127.0.0.1:7878:7878
    restart: unless-stopped

  qbittorrent:
    image: lscr.io/linuxserver/qbittorrent:latest
    container_name: qbittorrent
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
      - WEBUI_PORT=8080
      - TORRENTING_PORT=6881
    volumes:
      - ./config/qbittorrent:/config
      - ${DATA_ROOT}:/data
    ports:
      - 127.0.0.1:8080:8080
      - 6881:6881
      - 6881:6881/udp
    stop_grace_period: "10s"
    restart: unless-stopped

Empat perkara dalam fail tersebut melakukan kerja sebenar.

${DATA_ROOT}:/data adalah serupa dalam ketiga-tiga kontena yang mengakses media. Prowlarr tidak mendapatkannya, kerana Prowlarr tidak pernah membuka fail media.

Setiap port web diikat pada 127.0.0.1, jadi Docker menerbitkannya pada alamat loopback sahaja. 8989:8989 biasa akan menerbitkannya pada setiap antara muka, dan peraturan firewall Docker sendiri akan membawa trafik tersebut terus melepasi peraturan deny ufw. Gelagat itu sentiasa mengejutkan pengguna, dan ia dijelaskan dalam mengapa Docker menerbitkan port terus melalui ufw.

Port 6881 diterbitkan pada semua antara muka secara sengaja. Itu adalah port pendengaran torrent, dan ia perlu boleh dicapai untuk sambungan peer masuk. Benarkannya dengan sudo ufw allow 6881, dan baca asas firewall ufw untuk VPS jika arahan itu baharu bagi anda.

Direktori konfigurasi adalah berasingan bagi setiap aplikasi, dan hanya volum media yang dikongsi. Ciptakannya sebelum permulaan pertama supaya ia dimiliki oleh pengguna anda dan bukannya oleh root:

mkdir -p ~/arr/config/prowlarr ~/arr/config/sonarr ~/arr/config/radarr ~/arr/config/qbittorrent
docker compose up -d
docker compose ps

Keempat-empat servis harus membaca running. Setakat Julai 2026, imej-imej ini diterbitkan pada lscr.io dan tag latest mengikuti keluaran stabil semasa, jadi sematkan tag versi sebaliknya jika anda mahu naik taraf menjadi satu keputusan dan bukannya kejutan.

Capai antara muka web dengan selamat

Oleh kerana port tersebut berada pada loopback, tiada apa-apa yang terdedah lagi. Lakukan forwarding melalui SSH daripada mesin anda sendiri:

ssh -L 9696:127.0.0.1:9696 -L 8989:127.0.0.1:8989 \
    -L 7878:127.0.0.1:7878 -L 8080:127.0.0.1:8080 you@your-server

Kini http://127.0.0.1:8989 dalam pelayar anda mencapai Sonarr pada pelayan tersebut. Untuk akses kekal, letakkan stack di belakang Traefik dengan sijil TLS untuk beberapa aplikasi, atau capai pelayan melalui VPN WireGuard yang anda hoskan sendiri. Tiada satu pun aplikasi ini harus diletakkan di internet awam dengan hanya halaman log masuk masing-masing sebagai pelindung. Jika anda memilih laluan reverse proxy dan lebih suka mempunyai satu akaun untuk kesemua empat antara muka berbanding empat log masuk aplikasi berasingan untuk dijejaki, Authentik memberikan anda single sign-on yang dihoskan sendiri yang boleh dikuatkuasakan oleh Traefik pada setiap permintaan dengan forward auth.

qBittorrent menjana kata laluan pentadbir rawak pada permulaan pertama dan mencetaknya ke dalam log kontena. Baca kata laluan tersebut, kemudian tukarkannya dalam antara muka web:

docker compose logs qbittorrent | grep -i password

Jika anda melangkau langkah penukaran ini, kata laluan rawak baharu akan dijana pada setiap kali but semula, dan anda perlu kembali ke log setiap kali.

Tetapkan laluan di dalam setiap aplikasi

Dalam qBittorrent, buka Options, kemudian Downloads, dan tetapkan laluan simpan lalai kepada /data/torrents. Pastikan folder incomplete-downloads berada di dalam struktur yang sama, contohnya /data/torrents/incomplete. Muat turun yang selesai di mana-mana lokasi di luar /data tidak boleh di-hardlink ke dalam pustaka.

Dalam Sonarr, buka Settings, kemudian Media Management, dan tambah folder root /data/media/Shows. Dalam Radarr, folder root ialah /data/media/Movies. Ini adalah laluan di dalam kontena. Laluan hos /mnt/data/media/Shows akan ditolak, kerana direktori tersebut tidak wujud dari sudut pandangan kontena.

Dalam kedua-dua Sonarr dan Radarr, buka Settings, kemudian Download Clients, dan tambah qBittorrent. Hosnya ialah qbittorrent dan portnya ialah 8080. Nama servis berfungsi sebagai nama hos kerana Compose meletakkan kesemua empat kontena dalam satu rangkaian dengan servis DNS (domain name system) dalaman. Jangan gunakan localhost di sini: di dalam kontena Sonarr, localhost ialah Sonarr.

Biarkan Remote Path Mappings kosong. Ciri tersebut wujud untuk menterjemahkan laluan yang dilaporkan oleh klien muat turun kepada laluan yang boleh dilihat oleh aplikasi arr. Dengan satu mount /data yang dikongsi, kedua-dua kontena sudah bersetuju dengan setiap laluan, yang merupakan sebab kedua mengapa susun atur ini berbaloi untuk dilakukan.

Menyambungkan Prowlarr ke Sonarr dan Radarr

Prowlarr menolak definisi pengindeks ke dalam aplikasi lain, jadi anda hanya perlu mengonfigurasi pengindeks sekali sahaja dan bukannya dua kali. Ia memerlukan kunci API (application programming interface) daripada setiap aplikasi.

Dalam Sonarr, buka Settings, kemudian General, dan salin kunci API tersebut. Dalam Prowlarr, buka Settings, kemudian Apps, tambah aplikasi Sonarr, dan isikan tiga medan. Prowlarr Server ialah http://prowlarr:9696. Sonarr Server ialah http://sonarr:8989. API Key ialah nilai yang anda salin tadi. Tekan Test. Hasil berwarna hijau bermakna Prowlarr berjaya mencapai Sonarr melalui rangkaian Compose. Ulangi langkah ini dengan Radarr pada http://radarr:7878.

Hasil berwarna merah yang menyatakan sambungan ditolak hampir selalu bermaksud nama servis yang salah atau ketiadaan awalan http://. Sahkan bahawa nama tersebut dapat diselesaikan (resolve) dari dalam kontena:

docker compose exec prowlarr curl -sS -o /dev/null -w '%{http_code}\n' http://sonarr:8989

Kod status HTTP membuktikan laluan rangkaian adalah baik. Ralat penyelesaian nama membuktikan nama servis tersebut salah.

Jangan percayai tetapan tersebut sehingga anda melihat kiraan pautan (link count). Selepas satu item diimport, bandingkan fail yang dimuat turun dengan fail dalam pustaka:

stat -c '%i %h %n' /mnt/data/torrents/tv/*/*.mkv
stat -c '%i %h %n' /mnt/data/media/Shows/*/*/*.mkv

Nombor pertama ialah inode dan nombor kedua ialah kiraan pautan. Fail yang telah di-hardlink menunjukkan inode yang sama di kedua-dua lokasi dan kiraan pautan sebanyak 2. Dua inode berbeza, masing-masing dengan kiraan pautan sebanyak 1, bermakna Sonarr telah menyalin fail tersebut, dan log import akan menyatakan bahawa hardlink gagal.

Perhatikan juga cakera anda. df -h /mnt/data sepatutnya hampir tidak berubah apabila import berlaku, kerana hardlink hanya menambah nama dan bukan data.

Perkara yang sebenarnya menyebabkan kegagalan

Ralat kebenaran (permission) semasa import bermaksud ID pengguna kontena tidak mempunyai kebenaran untuk menulis ke dalam folder pustaka. Mesej tersebut ialah Access to the path ... is denied. Semak dengan ls -ln /mnt/data/media sama ada ID pemilik sepadan dengan PUID anda, dan ingat bahawa direktori memerlukan bit execute sebelum kontena boleh mengaksesnya.

Fail yang kelihatan dimiliki oleh root bermaksud kontena dimulakan sebelum direktori hos wujud, jadi Docker menciptakannya sebagai root. Hentikan stack, chown direktori tersebut, dan mulakan semula.

Memadam torrent daripada qBittorrent dan mendapati fail pustaka hilang bermaksud import tersebut merupakan salinan yang kemudiannya dibuang, atau anda memadam data tersebut dan bukannya entri torrent. Dengan hardlink yang sebenar, memadam satu nama akan membiarkan nama yang satu lagi kekal utuh, kerana data hanya dibebaskan apabila kiraan pautan mencapai sifar.

Cakera yang penuh lebih cepat daripada media yang anda tambah ialah masalah salinan dalam bentuk yang paling merugikan. Jalankan semakan stat di atas sebelum anda membeli lebih banyak storan.

Keperluan tindanan ini daripada VPS

Tiga aplikasi arr ringan. Aplikasi tersebut membuat tinjauan berkala terhadap indexer, menulis ke pangkalan data SQLite kecil dan menamakan semula fail. Pelayan dengan RAM 2 GB boleh menjalankan keempat-empat bekas dengan selesa. Beban sebenar datang daripada komponen lain. Klien muat turun boleh memenuhi kapasiti input dan output cakera apabila mengendalikan torrent besar, manakala pelayan media yang melakukan transcoding video pada mesin yang sama akan menggunakan CPU. Simpan media pada volum dengan throughput sebenar, dan tetapkan had jalur lebar pada klien muat turun jika pelayan turut menjalankan perkara lain yang penting. Peruntukkan kapasiti untuk komponen lain itu secara berasingan. Jangan anggap masih ada lebihan kapasiti: ruang kerja AFFiNE yang dihoskan sendiri terdiri daripada empat lagi bekas dengan pangkalan data di belakangnya, dan pada mesin dengan RAM 2 GB, aplikasi itu memerlukan sebahagian besar memori untuk dirinya sendiri. Tidak semua servis tambahan memerlukan kapasiti sebanyak itu. Sesuatu yang mempunyai satu tujuan, seperti penjejak senaman openGym yang dihoskan sendiri, boleh berkongsi mesin dengan baik, asalkan anda memberikannya TLS sendiri dan mengetahui lokasi fail pangkalan datanya sebelum mempercayakan rekod latihan setahun kepadanya. Apa-apa aplikasi yang mengandungi aplikasi web, pangkalan data Postgres dan baris gilir worker latar belakang memerlukan kapasiti yang lebih hampir kepada hujung julat AFFiNE. Oleh itu, tentukan sama ada meja bantuan Chatwoot yang dihoskan sendiri patut diletakkan pada pelayan ini atau pada pelayan sendiri sebelum anda menemui had tersebut di pertengahan proses import. Beban kerja yang datang secara mendadak memerlukan lebih banyak perhatian kerana perkara yang bertembung dengan proses import ialah penggunaan puncaknya, bukan puratanya. Jika anda mempertimbangkan OneCLI yang dihoskan sendiri dan memberikan setiap pengguna agent berkotak pasir sendiri, bandingkan angka saiz yang diterbitkan dengan kapasiti yang benar-benar tersedia ketika qBittorrent berjalan pada kelajuan penuh, bukan dengan nilai yang ditunjukkan oleh free -h pada mesin yang melahu.

FAQ

Ini berlaku kerana sumber dan destinasi berada pada sistem fail yang berbeza dari perspektif kontena. Dua bind mount yang berasingan, seperti /downloads dan /tv, dianggap sebagai dua sistem fail walaupun kedua-duanya berasal daripada cakera hos yang sama. Mount satu direktori induk sebagai /data dalam setiap kontena, letakkan folder muat turun dan pustaka di dalamnya, dan pautan tersebut akan dapat dilakukan. Sahkan hasilnya dengan stat -c '%i %h %n' pada kedua-dua fail: ia akan menunjukkan inode yang sama dan kiraan pautan sebanyak 2.

PUID dan PGID manakah yang perlu saya gunakan?

Gunakan ID berangka bagi akaun hos yang memiliki direktori media, yang boleh diperoleh melalui id -u dan id -g. Pada VPS Ubuntu yang baharu, nilainya biasanya 1000 untuk kedua-duanya. Setiap kontena dalam stack mesti menggunakan pasangan ID yang sama, jika tidak, satu aplikasi akan menulis fail yang tidak boleh diubah suai oleh aplikasi lain. Selepas menukar nilai tersebut, bina semula kontena dengan docker compose up -d --force-recreate dan betulkan fail sedia ada dengan chown -R.

Adakah saya perlu mendedahkan antaramuka web ini kepada internet?

Tidak, dan anda tidak sepatutnya berbuat demikian. Bind setiap port yang diterbitkan kepada 127.0.0.1 dalam fail Compose, kemudian akses antaramuka tersebut melalui SSH tunnel, VPN, atau reverse proxy yang melakukan TLS (transport layer security) termination dan menambah pengesahan tersendiri. Mendedahkannya secara terus adalah lebih berbahaya daripada yang disangka, kerana Docker memasukkan peraturan firewallnya sendiri dan peraturan ufw deny tidak akan menyekat trafik tersebut.

Di manakah saya boleh mencari kata laluan qBittorrent?

Imej LinuxServer.io mencetak kata laluan sementara untuk pengguna admin dalam log permulaannya. Jalankan docker compose logs qbittorrent | grep -i password untuk membacanya, kemudian tetapkan kata laluan kekal di bawah Options dan Web UI. Kata laluan sementara baharu akan dijana pada setiap kali but semula sehingga anda menetapkan kata laluan anda sendiri.

Bolehkah Jellyfin menggunakan folder yang sama?

Ya, dan itulah tujuan utama susun atur tersebut. Mount /mnt/data/media ke dalam pelayan media anda sebagai /media, dan pustakanya akan berada di /media/Movies dan /media/Shows, sementara Sonarr dan Radarr menulis ke direktori yang sama melalui /data/media. Berikan pelayan media PUID dan PGID yang sama supaya ia boleh membaca fail yang ditulis oleh stack arr tersebut.

#sonarr#radarr#prowlarr#docker-compose#self-hosting