SSD Nodes Learn RAM 8GB — $66/tahun
Panduan Matt ConnorOleh Matt Connor · Dikemas kini 2026-08-01

Tindanan arr dalam satu fail Docker Compose

Jalankan Prowlarr, Sonarr, Radarr dan qBittorrent pada VPS dengan PUID, PGID serta susun atur volum yang sama supaya hardlink terus berfungsi.

Perkara yang anda bina

Tindanan arr Docker Compose terdiri daripada empat kontena yang mengurus pustaka media: Prowlarr untuk tetapan pengindeks, Sonarr untuk siri, Radarr untuk filem dan qBittorrent sebagai klien muat turun. Kesemuanya berkomunikasi melalui rangkaian Compose menggunakan nama perkhidmatan, serta berkongsi satu pepohon folder pada hos. Pemasangannya ringkas. Susun atur volum yang menentukan sama ada tindanan ini berfungsi selama bertahun-tahun atau terus menimbulkan masalah setiap minggu. Oleh itu, sebahagian besar panduan ini menerangkannya.

Tindanan ini tidak mencari kandungan untuk anda. Prowlarr menyimpan sebarang pengindeks yang anda tambahkan, manakala pilihan pengindeks yang digunakan ialah keputusan dan tanggungjawab undang-undang anda. Panduan ini merangkumi aspek asas: pengguna, laluan, kebenaran, rangkaian kontena dan pemeriksaan untuk mengesahkan bahawa semuanya berfungsi.

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

Apabila Sonarr selesai memproses muat turun, Sonarr mengimport fail itu ke dalam pustaka anda. Jika folder muat turun dan folder pustaka berada pada sistem fail yang sama, proses import menggunakan hardlink: nama kedua yang menunjuk kepada data yang sama pada cakera. Proses ini tidak menggunakan ruang tambahan dan tidak mengambil masa. Torrent terus melakukan seeding menggunakan nama lama, manakala pelayan media anda membaca nama baharu.

Jika kedua-dua folder berada pada sistem fail yang berbeza, kernel tidak dapat membuat pautan itu. Sonarr akan menggunakan salinan sebagai pilihan gantian. Musim berukuran 40 GB kini menggunakan 80 GB ruang cakera dan memerlukan beberapa minit untuk operasi input dan output. Log import merekodkan bahawa hardlink gagal dan fail disalin sebagai gantinya. Pada VPS dengan kuota cakera tetap, keadaan ini boleh menyebabkan ruang habis dalam masa seminggu.

Inilah perangkapnya. Dalam container, bind mount ialah sempadan sistem fail. Lekapkan /mnt/data/torrents sebagai /downloads dan /mnt/data/media sebagai /tv. Walaupun kedua-duanya berada pada satu cakera hos, Sonarr melihatnya sebagai dua mount berasingan dan enggan membuat pautan merentas kedua-duanya. Dokumentasi imej LinuxServer.io rasmi menyatakan perkara ini secara langsung: penggunaan laluan /downloads dan /tv yang berasingan mengorbankan keupayaan untuk menggunakan hardlink.

Penyelesaiannya ialah satu mount. Setiap container yang mengakses media menerima volume tunggal yang sama, /mnt/data:/data, dan setiap laluan yang digunakan olehnya ialah folder di dalam volume tersebut. Satu titik mount, satu sistem fail, dan hardlink berfungsi.

Cipta pengguna, kumpulan dan folder

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

id -u
id -g

Kedua-duanya biasanya memaparkan 1000 pada Ubuntu VPS yang baharu. Sekarang bina pepohon direktori. Letakkannya pada mana-mana cakera yang menyimpan media anda dan pastikan keseluruhan pepohon berada pada cakera itu.

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

Semak bahawa semuanya benar-benar berada pada satu sistem fail sebelum meneruskan:

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

Kedua-dua baris mesti memaparkan peranti sumber yang sama. Peranti yang berbeza bermakna hardlink tidak akan berfungsi, walau apa pun tetapan dalam konfigurasi container.

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

Fail persekitaran

Simpan nilai yang berubah mengikut pelayan dalam .env, di sebelah 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, seperti Europe/Berlin. Aplikasi arr menjadualkan tugas dan menambah cap masa pada baris log dalam zon tersebut. Oleh itu, nilai yang salah akan menyebabkan semua log mengelirukan kemudian.

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 itu menjalankan fungsi penting.

${DATA_ROOT}:/data adalah sama dalam ketiga-tiga bekas yang mengendalikan media. Prowlarr tidak mendapatnya kerana Prowlarr tidak pernah membuka fail media.

Setiap port web diikat kepada 127.0.0.1, jadi Docker menerbitkannya pada alamat gelung balik sahaja. 8989:8989 biasa akan menerbitkannya pada setiap antara muka, dan peraturan firewall Docker sendiri akan membawa trafik itu terus melepasi peraturan ufw deny. Tingkah laku ini sering mengejutkan pengguna, dan penjelasannya terdapat dalam sebab Docker menerbitkan port terus melalui ufw.

Port 6881 sengaja diterbitkan pada semua antara muka. Itu ialah port pendengaran torrent dan port tersebut mesti boleh dicapai untuk sambungan masuk daripada peer. Benarkan port itu dengan sudo ufw allow 6881, dan baca asas firewall ufw untuk VPS jika arahan itu baharu bagi anda.

Direktori konfigurasi diasingkan untuk setiap aplikasi, manakala hanya volum media dikongsi. Cipta direktori tersebut sebelum memulakan perkhidmatan kali pertama supaya direktori itu dimiliki oleh pengguna anda, bukannya root:

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

Keempat-empat perkhidmatan sepatutnya membaca running. Setakat July 2026, imej ini diterbitkan pada lscr.io dan tag latest mengikut keluaran stabil semasa. Oleh itu, gunakan tag versi secara khusus jika anda mahu peningkatan dibuat berdasarkan keputusan, bukan secara mengejut.

Akses antara muka web dengan selamat

Oleh sebab port terikat pada loopback, tiada apa-apa yang terdedah lagi. Majukan port tersebut melalui SSH dari 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 mengakses Sonarr pada pelayan. Untuk akses kekal, letakkan tindanan tersebut di belakang Traefik dengan sijil TLS untuk beberapa aplikasi, atau akses pelayan melalui VPN WireGuard yang anda hos sendiri. Tiada satu pun aplikasi ini patut diletakkan di internet awam dengan hanya halaman log masuknya sendiri sebagai perlindungan.

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

docker compose logs qbittorrent | grep -i password

Jika anda tidak menukarnya, kata laluan rawak baharu akan dijana pada setiap permulaan semula, dan anda perlu melihat log setiap kali.

Tetapkan laluan dalam setiap aplikasi

Dalam qBittorrent, buka Options, kemudian Downloads, dan tetapkan laluan simpan lalai kepada /data/torrents. Simpan folder muat turun yang belum lengkap dalam pepohon yang sama, seperti /data/torrents/incomplete. Muat turun yang selesai di mana-mana lokasi di luar /data tidak boleh dipaut keras ke dalam pustaka.

Dalam Sonarr, buka Settings, kemudian Media Management, dan tambahkan folder akar /data/media/Shows. Dalam Radarr, folder akarnya ialah /data/media/Movies. Laluan ini berada dalam container. Laluan hos /mnt/data/media/Shows ditolak kerana direktori itu tidak wujud dari sudut pandangan container.

Dalam Sonarr dan Radarr, buka Settings, kemudian Download Clients, dan tambahkan qBittorrent. Hos ialah qbittorrent dan port ialah 8080. Nama perkhidmatan boleh digunakan sebagai nama hos kerana Compose meletakkan keempat-empat container pada satu rangkaian dengan perkhidmatan DNS (domain name system) dalaman. Jangan gunakan localhost di sini: dalam container Sonarr, localhost ialah Sonarr.

Biarkan Remote Path Mappings kosong. Ciri ini digunakan untuk menterjemahkan laluan yang dilaporkan oleh klien muat turun kepada laluan yang boleh dilihat oleh aplikasi arr. Dengan satu lekap /data yang dikongsi, kedua-dua container sudah menggunakan laluan yang sama. Ini ialah sebab kedua susun atur ini berbaloi.

Sambungkan Prowlarr kepada Sonarr dan Radarr

Prowlarr menyalurkan definisi pengindeks kepada aplikasi lain, jadi anda hanya perlu mengkonfigurasi pengindeks sekali. Prowlarr memerlukan kunci API (antara muka pengaturcaraan aplikasi) daripada setiap aplikasi.

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

Keputusan berwarna merah yang menyatakan sambungan ditolak hampir selalu bermaksud nama perkhidmatan salah atau awalan http:// tiada. Sahkan bahawa nama tersebut dapat diselesaikan dari dalam kontena:

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

Kod status HTTP membuktikan bahawa laluan rangkaian berfungsi. Ralat penyelesaian nama membuktikan bahawa nama perkhidmatan adalah salah.

Jangan percayai persediaan itu sehingga anda melihat bilangan link. 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 bilangan link. Fail yang menggunakan hardlink mempunyai inode yang sama di kedua-dua lokasi dan bilangan link sebanyak 2. Dua inode berbeza, masing-masing dengan bilangan link 1, bermakna Sonarr menyalin fail, dan log import akan menyatakan bahawa hardlink gagal.

Pantau cakera juga. df -h /mnt/data sepatutnya hampir tidak berubah apabila import berlaku kerana hardlink menambah nama tanpa menambah data.

Perkara yang sebenarnya rosak

Ralat kebenaran semasa import bermaksud id pengguna container tidak boleh menulis ke dalam folder pustaka. Mesejnya ialah Access to the path ... is denied. Semak dengan ls -ln /mnt/data/media bahawa id pemilik sepadan dengan PUID anda, dan ingat bahawa direktori memerlukan bit execute sebelum container boleh memasukinya.

Fail yang kelihatan dimiliki oleh root bermaksud container dimulakan sebelum direktori hos wujud, jadi Docker menciptanya sebagai root. Hentikan stack, chown direktori itu, kemudian mulakannya semula.

Memadam torrent daripada qBittorrent kemudian mendapati fail pustaka telah hilang bermaksud import itu ialah salinan yang kemudiannya dipadamkan, atau anda memadam data dan bukannya entri torrent. Dengan hardlink sebenar, membuang satu nama tidak menjejaskan nama yang satu lagi kerana data hanya dibebaskan apabila kiraan pautan mencapai sifar.

Cakera yang penuh lebih cepat daripada jumlah media yang anda tambahkan ialah bentuk masalah penyalinan yang paling mahal. Jalankan semakan stat di atas sebelum membeli storan tambahan.

Keperluan stack ini daripada VPS

Tiga aplikasi arr ini tidak menggunakan banyak sumber. Aplikasi ini meninjau indexer, menulis ke pangkalan data SQLite yang kecil dan menamakan semula fail. Pelayan dengan RAM 2 GB boleh menjalankan keempat-empat bekas dengan lancar. Beban utama datang daripada tugas lain. Klien muat turun boleh memenuhi kapasiti input dan output cakera apabila mengendalikan torrent yang besar, manakala pelayan media yang melakukan transkod video pada mesin yang sama akan menggunakan CPU. Simpan media pada volum yang mempunyai kadar pemindahan sebenar yang tinggi, dan tetapkan had lebar jalur pada klien muat turun jika pelayan turut menjalankan tugas lain yang penting.

FAQ

Ini berlaku kerana sumber dan destinasi berada pada sistem fail yang berbeza dari perspektif container. Dua bind mount berasingan, seperti /downloads dan /tv, dianggap sebagai dua sistem fail walaupun kedua-duanya berasal daripada satu cakera hos. Lekapkan satu direktori induk sebagai /data dalam setiap container, kemudian letakkan direktori muat turun dan pustaka di dalamnya. Dengan itu, pautan boleh dicipta. Sahkan hasilnya dengan stat -c '%i %h %n' pada kedua-dua fail: inode yang sama dan kiraan pautan 2.

Apakah PUID dan PGID yang patut saya gunakan?

Gunakan id berangka akaun hos yang memiliki pepohon media. Anda boleh mendapatkannya dengan id -u dan id -g. Pada VPS Ubuntu baharu, nilainya biasanya 1000 untuk kedua-duanya. Setiap container dalam tindanan mesti menggunakan pasangan yang sama. Jika tidak, satu aplikasi mungkin menulis fail yang tidak boleh diubah suai oleh aplikasi lain. Selepas menukar nilai tersebut, cipta semula container dengan docker compose up -d --force-recreate dan betulkan fail sedia ada dengan chown -R.

Adakah saya perlu mendedahkan antara muka web ini kepada internet?

Tidak, dan anda tidak sepatutnya berbuat demikian. Ikat setiap port yang diterbitkan kepada 127.0.0.1 dalam fail Compose. Kemudian akses antara muka tersebut melalui terowong SSH, VPN, atau proksi songsang yang menamatkan TLS (keselamatan lapisan pengangkutan) dan menambah pengesahannya sendiri. Menerbitkannya secara langsung lebih berisiko daripada yang kelihatan kerana Docker memasukkan peraturan firewallnya sendiri. Peraturan ufw deny tidak akan menghentikan trafik tersebut.

Di manakah saya boleh mendapatkan 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 mula semula sehingga anda menetapkan kata laluan sendiri.

Bolehkah Jellyfin menggunakan folder yang sama?

Ya, dan itulah tujuan susun atur ini. Lekapkan /mnt/data/media ke dalam pelayan media anda sebagai /media. Pustakanya berada di /media/Movies dan /media/Shows, manakala Sonarr dan Radarr menulis ke direktori yang sama melalui /data/media. Berikan pelayan media nilai PUID dan PGID yang sama supaya pelayan tersebut boleh membaca perkara yang ditulis oleh tindanan arr.

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