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 sedang bina
Stak Docker Compose arr terdiri daripada empat kontena yang mengurus pustaka media: Prowlarr untuk tetapan pengindeks, Sonarr untuk siri, 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 pepohon folder pada hos. Pemasangannya ringkas. Bahagian yang menentukan sama ada stak ini berfungsi untuk tempoh bertahun-tahun atau menimbulkan masalah setiap minggu ialah susun atur volum, jadi sebahagian besar panduan ini tertumpu kepada perkara tersebut.
Stak ini tidak mencari kandungan untuk anda. Prowlarr menyimpan sebarang pengindeks yang anda tambah kepadanya, 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 ia berfungsi.
Jika anda belum pernah menulis fail Compose, baca asas Docker Compose untuk VPS terlebih dahulu. Catatan ini mengandaikan docker compose version sudah memaparkan sesuatu pada pelayan anda. Gunakan Docker Engine 28.0.0 atau lebih baharu: keluaran yang lebih lama membenarkan hos pada segmen rangkaian tempatan yang sama mencapai port yang diterbitkan ke localhost.
Mengapa hardlink gagal, dan mengapa ini adalah faktor penentu
Apabila Sonarr selesai memuat turun, ia akan mengimport fail tersebut ke dalam pustaka anda. Jika folder muat turun dan folder pustaka berada pada sistem fail yang sama dan hardlinking diaktifkan, Sonarr akan cuba melakukan hardlink: satu nama kedua yang menunjuk kepada data yang sama pada cakera. Ia tidak mengambil ruang tambahan dan tidak memakan masa. Torrent akan 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 dapat 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. Sonarr merekodkan kegagalan hardlink merentas sistem fail pada tahap Trace dan pengecualian hardlink lain pada tahap Debug, jadi log biasa tidak menjamin mesej kegagalan akan dipaparkan. Pada VPS dengan peruntukan cakera tetap, inilah punca pengguna kehabisan ruang dalam masa seminggu.
Berikut adalah 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, Sonarr melihat dua mount yang berasingan dan tidak boleh melakukan hardlink merentasnya. Dokumentasi imej rasmi LinuxServer.io menyatakan perkara ini secara terus: menggunakan laluan /downloads dan /tv yang berasingan akan mengorbankan keupayaan untuk melakukan hardlink.
Penyelesaiannya adalah satu mount sahaja. Setiap kontena yang mengakses media mendapat satu volume tunggal yang sama, /mnt/data:/data, dan setiap laluan yang digunakan adalah folder di dalamnya. Satu titik mount, satu sistem fail, hardlink berfungsi dengan lancar.
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 -gKedua-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/dataPastikan ia benar-benar berada pada satu sistem fail sebelum anda meneruskan:
df --output=source,target /mnt/data/torrents /mnt/data/mediaKedua-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 ~/arrTulis ~/arr/.env:
PUID=1000
PGID=1000
TZ=Etc/UTC
DATA_ROOT=/mnt/dataTetapkan 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-stoppedEmpat perkara dalam fail tersebut melakukan kerja yang 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 kepada 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 ufw deny. Gelagat ini sentiasa mengejutkan pengguna, dan ia dijelaskan dalam mengapa Docker menerbitkan port terus melalui ufw.
Port 6881 diterbitkan pada semua antara muka dengan sengaja. Itu adalah port pendengaran torrent, dan ia perlu boleh dicapai untuk sambungan peer masuk. Gelagat Docker yang sama terpakai di sini, jadi anda tidak memerlukan peraturan ufw untuknya, dan menambah satu peraturan tidak mengubah apa-apa. Dokumentasi Docker, yang disemak pada 8 November 2026, menyatakan trafik ke port yang diterbitkan dihalakan sebelum ia mencapai rantaian yang digunakan oleh ufw, jadi sudo ufw allow 6881 tidak mempunyai kesan pada port ini. Docker menerbitkannya pada semua antara muka hos sebaik sahaja kontena bermula, dan ufw deny juga tidak akan menutupnya. Jika anda perlu mengehadkan siapa yang boleh menyambung kepadanya, dokumentasi Docker merujuk kepada peraturan dalam rantaian DOCKER-USER miliknya dengan backend iptables lalai; backend nftables miliknya pula memerlukan peraturan dalam jadual nftables yang berasingan. Kekalkan ufw untuk servis yang tidak berjalan dalam Docker, seperti SSH, dan baca asas firewall ufw untuk VPS jika alat tersebut 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 psKeempat-empat servis harus membaca running. Setakat 8 November 2026, imej-imej ini diterbitkan pada lscr.io dan tag latest mengikuti keluaran stabil semasa, jadi tetapkan tag versi jika anda mahu naik taraf menjadi satu keputusan dan bukannya kejutan.
Capai antara muka web dengan selamat
Antara muka web diikat pada loopback. Lakukan forward trafik tersebut 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-serverKini http://127.0.0.1:8989 dalam pelayar anda akan mencapai Sonarr pada pelayan. Untuk akses kekal, letakkan stack tersebut di belakang Traefik dengan sijil TLS untuk beberapa aplikasi, atau capai pelayan melalui VPN WireGuard yang anda hoskan sendiri. Walau bagaimanapun, VPN tidak mencapai port ini secara automatik. Dokumentasi Docker, yang disemak pada 8 November 2026, menyatakan bahawa dengan Docker Engine 28.0.0 atau lebih baharu dan konfigurasi bridge lalai, hanya hos Docker yang boleh mengakses port yang diterbitkan pada alamat localhost. Untuk menggunakan VPN, sama ada teruskan menjalankan SSH tunnel melaluinya, atau tukar ikatan (bindings) dalam fail Compose daripada 127.0.0.1 kepada alamat pelayan itu sendiri pada antara muka VPN. 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 diuruskan, Authentik memberikan anda single sign-on yang dihoskan sendiri yang boleh dikuatkuasakan oleh Traefik pada setiap permintaan dengan forward auth. Sonarr dan Radarr mempunyai dua kekangan tersendiri di sebalik proksi, jadi sebelum anda menghalakan trafik melaluinya melalui Traefik, baca cara menjalankan Sonarr dan Radarr di sebalik reverse proxy untuk entri Allowed Hosts yang menghentikan ralat Invalid Hostname dan sebab mengapa /api mesti melangkau log masuk.
qBittorrent menjana kata laluan pentadbir rawak pada permulaan pertama dan mencetaknya ke dalam log container. Baca kata laluan tersebut, kemudian tukarkannya dalam antara muka web:
docker compose logs qbittorrent | grep -i passwordJika anda melangkau proses penukaran ini, kata laluan rawak baharu akan dijana pada setiap kali restart, dan anda perlu menyemak log semula 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 luar /data tidak boleh dipautkan secara keras (hardlinked) ke dalam pustaka dengan fail Compose ini.
Dalam Sonarr, buka Settings, kemudian Media Management, dan tambah folder akar /data/media/Shows. Dalam Radarr, folder akarnya 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 pada satu rangkaian dengan perkhidmatan 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 mengkonfigurasi pengindeks sekali sahaja dan bukannya dua kali. Ia memerlukan kunci API (application programming interface) daripada setiap aplikasi.
Di dalam Sonarr, buka Settings, kemudian General, dan salin kunci API tersebut. Di 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 telah anda salin. Tekan Test. Hasil berwarna hijau bermakna Prowlarr telah mencapai Sonarr melalui rangkaian Compose. Ulangi langkah ini dengan Radarr pada http://radarr:7878.
Hasil berwarna merah yang menyatakan sambungan ditolak bermakna sambungan tidak sampai ke servis yang sedang mendengar pada alamat dan port yang dikonfigurasikan. Sahkan nama tersebut dapat diselesaikan (resolve) dari dalam kontena:
docker compose exec prowlarr curl -sS -o /dev/null -w '%{http_code}\n' http://sonarr:8989Kod status HTTP membuktikan laluan rangkaian adalah baik. Ralat penyelesaian nama bermakna nama servis tidak dapat diselesaikan; semak ejaannya dan pastikan kedua-dua kontena sedang berjalan pada rangkaian Compose yang sama.
Buktikan bahawa hardlink benar-benar berlaku
Jangan percayai persediaan 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/*/*/*.mkvNombor pertama ialah inode dan nombor kedua ialah kiraan pautan. Pada sistem fail yang sama, dua fail yang merupakan hardlink antara satu sama lain akan menunjukkan inode yang sama dan kiraan pautan sekurang-kurangnya 2; hardlink tambahan akan meningkatkan kiraan tersebut. Inode yang berbeza bermakna fail tersebut bukan hardlink antara satu sama lain, tetapi ini tidak membuktikan percubaan hardlink gagal. Sonarr juga akan menyalin fail tanpa mencuba hardlink apabila tetapan hardlink dilumpuhkan. Kegagalan hardlink merentas sistem fail akan direkodkan pada tahap Trace dan pengecualian hardlink lain pada tahap Debug, jadi log import biasa tidak menjamin penjelasan.
Perhatikan juga cakera. 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 laksana (execute bit) sebelum kontena boleh mengaksesnya.
Direktori yang dimiliki oleh root boleh berlaku jika kontena dimulakan sebelum direktori hos wujud, kerana Docker akan mencipta direktori bind-mount yang tiada. Hentikan stack, chown direktori tersebut, dan mulakan semula.
Memadam torrent daripada qBittorrent dan mendapati fail pustaka hilang memerlukan pemeriksaan laluan mana yang telah dipadam; memadam muat turun sahaja tidak akan membuang salinan pustaka atau hardlink yang berasingan. Dengan hardlink yang sebenar, membuang satu nama akan membiarkan nama yang satu lagi kekal utuh, kerana data hanya akan dibebaskan apabila kiraan pautan (link count) mencapai sifar.
Cakera yang penuh lebih cepat daripada media yang anda tambah adalah masalah penyalinan dalam bentuk yang paling merugikan. Jalankan pemeriksaan stat di atas sebelum anda membeli storan tambahan.
Keperluan tindanan ini daripada VPS
Tiga aplikasi arr adalah ringan. Ia meninjau pengindeks, menulis ke pangkalan data SQLite yang kecil, dan menamakan semula fail. Beban kerja datang daripada tempat lain. Pelanggan muat turun akan menepukan input dan output cakera semasa memproses torrent yang besar, dan pelayan media yang melakukan transkod video pada mesin yang sama akan menggunakan CPU. Simpan media pada volum dengan daya pemprosesan sebenar, dan tetapkan had lebar jalur pada pelanggan muat turun jika pelayan tersebut melakukan tugas lain yang penting bagi anda. Bajet untuk tugas-tugas lain tersebut secara berasingan dan jangan menganggap ruang kepala (headroom) sudah tersedia: ruang kerja AFFiNE yang dihoskan sendiri memerlukan empat bekas tambahan dengan pangkalan data di belakangnya, dan AFFiNE mengesyorkan 2 GB RAM untuk penggunaan asas serta 4 GB untuk dokumen melebihi 10,000 perkataan. Untuk sesuatu yang mempunyai tujuan tunggal seperti penjejak senaman openGym yang dihoskan sendiri, berikan ia TLS sendiri dan pastikan anda tahu di mana folder datanya berada sebelum anda mempercayainya dengan sejarah latihan selama setahun. Mana-mana aplikasi yang membawa aplikasi web, pangkalan data Postgres dan baris gilir pekerja latar belakang berada lebih dekat dengan julat AFFiNE, jadi tentukan sama ada meja bantuan Chatwoot yang dihoskan sendiri sesuai diletakkan pada pelayan ini atau pada pelayan berasingan sebelum anda menemui hadnya di pertengahan proses import. Beban kerja yang melonjak memerlukan lebih banyak perhatian, kerana kemuncak beban tersebut, bukannya puratanya, yang akan bertembung dengan proses import: jika anda sedang mempertimbangkan OneCLI yang dihoskan sendiri yang memberikan setiap orang ejen berkotak pasir mereka sendiri, semak angka saiz yang diterbitkan berbanding dengan apa yang sebenarnya bebas semasa qBittorrent berjalan pada kelajuan penuh, bukan berbanding dengan apa yang ditunjukkan oleh free -h pada mesin yang melahu.
FAQ
Mengapa Sonarr menyalin fail dan bukannya membuat hardlink?
Ini berlaku kerana hardlink dinyahaktifkan, atau percubaan hardlink gagal, termasuk apabila sumber dan destinasi berada pada sistem fail yang berbeza dari sudut pandangan kontena. Dua bind mount yang berasingan, seperti /downloads dan /tv, adalah titik lekap (mount point) yang berbeza walaupun kedua-duanya berasal daripada cakera hos yang sama, dan hardlink tidak boleh merentasinya. Lekapkan satu direktori induk sebagai /data dalam setiap kontena, letakkan muat turun dan pustaka di dalamnya, dan pautan akan menjadi mungkin. Sahkan hasilnya dengan stat -c '%i %h %n' pada kedua-dua fail: pada sistem fail yang sama, ia mesti menunjukkan inode yang sama dan kiraan pautan sekurang-kurangnya 2.
PUID dan PGID manakah yang perlu saya gunakan?
Gunakan ID berangka bagi akaun hos yang memiliki pepohon media, yang boleh diperoleh daripada id -u dan id -g. Pada VPS Ubuntu yang baharu, ia biasanya 1000 untuk kedua-duanya. Setiap kontena dalam tindanan (stack) mesti menggunakan pasangan yang sama, jika tidak, satu aplikasi akan menulis fail yang tidak boleh diubah suai oleh aplikasi lain. Selepas menukar nilai tersebut, cipta semula kontena dengan docker compose up -d --force-recreate dan betulkan fail sedia ada dengan chown -R.
Adakah saya perlu mendedahkan antara muka web ini ke internet?
Tidak, dan anda tidak sepatutnya berbuat demikian. Ikat setiap port yang diterbitkan ke 127.0.0.1 dalam fail Compose, kemudian akses antara muka tersebut melalui terowong SSH atau melalui reverse proxy pada pelayan yang menamatkan TLS (transport layer security) dan menambah pengesahan tersendiri. Dengan Docker Engine 28.0.0 atau lebih baharu dan konfigurasi bridge lalai, VPN sahaja tidak boleh mencapai port yang diterbitkan pada 127.0.0.1, kerana Docker menjadikan port yang diterbitkan itu hanya boleh dicapai daripada hos itu sendiri. Keluaran Docker yang lebih lama membenarkan hos pada segmen rangkaian tempatan yang sama mencapai port yang diterbitkan ke localhost. Jika anda mahukan akses terus melalui VPN, terbitkan port tersebut pada alamat VPN pelayan. Menerbitkannya terus pada antara muka awam adalah lebih buruk 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 dijana pada setiap kali but semula sehingga anda menetapkan kata laluan anda sendiri.
Bolehkah Jellyfin menggunakan folder yang sama?
Ya, dan itulah tujuan susun atur tersebut. Lekapkan /mnt/data/media ke dalam pelayan media anda sebagai /media, dan pustakanya terletak di /media/Movies dan /media/Shows manakala Sonarr dan Radarr menulis ke direktori yang sama melalui /data/media. Berikan pelayan media PUID dan PGID yang sama supaya ia boleh membaca apa yang ditulis oleh tindanan arr.