زمان خواندن : 14 minutes

دو اشتراک Pro، یک دستگاه، یک کارت بانکی، و بدون هیچ تضاد شبکه. چگونه Docker به من اجازه داد تا ظرفیت استنتاج ابر خود را دو برابر کنم بدون خرید یک PC دوم.

مقدمه

من از چندین ماه Ollama Pro را برای تغذیه جلسات OpenCode خود با مدل‌های ابری استفاده می‌کنم. حتی با اشتراک Pro، به سرعت به دلیل rate limiting محدود می‌شویم وقتی چند عامل را به‌طور موازی اجرا می‌کنیم. حل واضح: اشتراک دوم.

اما اینجا، این تراژدی است.

Ollama هر دستگاه را با یک کلید SSH منحصربه‌فرد شناسایی می‌کند — کلید معروف Device Key آن. دو نمونه روی همان سیستم عامل، هویت یکسانی خواهند داشت و linking دو حساب Pro به یک دستگاه ممکن نیست. و همان‌طور که شما حدس می‌زنید، من نمی‌خواستم فقط به این دلیل یک لپ‌تاپ دیگر بخرم.

راه‌حل: تقلب. Ollama را متقاعد کن که روی دو ماشین مختلف در حال اجرا است، در حالی که آن‌ها یک CPU، یک RAM و یک اتصال شبکه مشترک دارند. Docker یک بUBLE ایزولیشن کامل به ما ارائه خواهد دهد.

@startuml
!theme plain
skinparam BoxPadding 10
skinparam DefaultFontSize 12

left to right direction

node "ماشین فیزیکی" {
  frame "Ollama نمونه A (بومی)" as Native {
    database "هویت\n/usr/share/ollama/.ollama/id_ed25519" as KeyA
    portin "API\n:11434" as PortA
  }

  frame "Ollama نمونه B (Docker)" as Docker {
    database "هویت\n~/ollama-b-data/id_ed25519" as KeyB
    portin "API
:11435" as PortB
  }
}

cloud "Ollama Cloud" {
  actor "حساب Pro A\n(email 1)" as AccountA
  actor "حساب Pro B
(ایمیل 2)" as AccountB
}

KeyA --> AccountA : "کلید SSH A"
KeyB --> AccountB : "کلید SSH B"
PortA --> AccountA : "درخواست‌های A"
PortB --> AccountB : "درخواست‌های B"

note bottom of Docker
  Conteneur isolé : identité SSH distincte,
  port réseau distinct, volume persistant
end note
@enduml

چرا دو بار همان چیز؟

قبل از اینکه من را بیمار ذهنی بنامید، اجازه دهید مورد استفاده را برای شما توضیح دهم.

با یک اشتراک Pro، می‌توانم یک مدل را مانند`deepseek-v4-pro:cloud`در یک جلسه OpenCode. مشکل زمانی پیش می‌آید که می‌خواهم دو جلسه همزمان داشته باشم. محدودیت‌های نرخ limiting باعث می‌شود که جلسه دوم کند شود یا به‌طور کامل رد شود.

به همراه دو اشتراک Pro مستقل:

  • جلسه OpenCode 1 → حساب حرفه‌ای A`localhost:11434`)

  • Session OpenCode 2 → حساب حرفه‌ای B`localhost:11435`)

هر جلسه quota و زمینه خود را دارد و دیگری را مختل نمی‌کند. این پردازش چندفرآیند انسانی است.

دو اشتراک Pro = دو ایمیل متفاوت. کارت بانکی یکسان کار می‌کند — سیستم پرداخت Ollama اشتراک‌هایمتعدد را از همان روش پرداخت مسدود نمی‌کند. من بررسی کردم.

قلب مشکل : کلید دستگاه

وقتی Ollama را نصب می‌کنید، یک جفت کلید SSH ed25519 در دایرکتوری هویت ایجاد می‌شود :

$ cat /usr/share/ollama/.ollama/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...

این کلید به سرورهای Ollama آپلود می‌شود در حین`ollama signin`. او می‌گوید « این ماشین به یک حساب Pro تعلق دارد ». اگر دو نمونه شما فایل یکسانی را به اشتراک می‌گذارند`id_ed25519`,هما هویت یکسانی دارند. بازی تمام شد.

راه‌حل: به نمونه دوم خود دایرکتوری هویت مخصوصش بدهید، که در یک حجم Docker به‌طور منفصل باشد.

آماده‌سازی — قدم به قدم

پیش‌نیاز

  • نصب بومی کارآمد Ollama (اسکریپت رسمی`curl | sh`)

  • Docker نصب و کارآمد

  • Portainer یا docker-compose برای استقرار

  • دو حساب Ollama با دو ایمیل متفاوت

من نسخه را استفاده کردم`0.20.2`— این ارائه شده توسط اسکریپت رسمی و تصویر Docker متناظر.

مرحله ۱: ایجاد حجم

یک دایرکتوری ساده روی میزبان به‌عنوان یک حجم پایدار برای هویت نمونه B :

mkdir -p ~/ollama-b-data

این پوشه در کانتینر Docker به صورت …​ مونت خواهد شد./root/.ollama, جایی که Ollama کلیدهای هویتش، تاریخچه و مدل‌هایش را ذخیره می‌کند.

مرحله 2: اجرای کنتینر Docker

# docker-compose.yml
services:
  ollama-instance-b:
    image: ollama/ollama:0.20.2
    container_name: ollama-instance-b
    ports:
      - "11435:11434"
    volumes:
      - /home/cheroliv/ollama-b-data:/root/.ollama
    environment:
      - OLLAMA_HOST=0.0.0.0
    restart: always

اینجا چه می‌شود :

  • بندر11435از میزبان به11434داخل کنتینر. بنابراین، مثال Docker به`:11435`بدون تعارض با نمونه بومی که اشغال می‌کند`:11434`.

  • حجم`~/ollama-b-data`نصب شده روی`/root/.ollama`— اینجا جایی است که هویت SSH ذخیره خواهد شد.

  • `OLLAMA_HOST=0.0.0.0`اجازه می‌دهد تا کانتینر بتواند اتصالات خارجی را پذیرد.

من این استک را از طریق Portainer استقرار دادم، اما یک ساده`docker compose up -d`به همان میزان خوب عمل می‌کند.

مرحله 3: دریافت کلید عمومی

چون کانتینر در اولین راه‌اندازی خالی است، Ollama به‌صورت خودکار یک جفت کلید SSH جدید در حجم ایجاد می‌کند. کلید عمومی را دریافت می‌کنیم:

$ docker exec ollama-instance-b cat /root/.ollama/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDDQ+dvnfmuo49q5O8LOlvgZ39SKORFw47ry9k4H2jPc

من بررسی می‌کنم که این کلید مختلف نسبت به آن کلید نمونه بومی است :

# Instance native
$ cat /usr/share/ollama/.ollama/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGyF...(différente)

# Instance Docker
$ cat ~/ollama-b-data/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDDQ...(différente)

دو کلید متمایز، دو هویت جداگانه. بازی تمام شد.

اگر conteneur شما دوباره راه‌اندازی شود، بازکاربرد کلیدهای موجود در حجم را انجام می‌دهد. هویت پایدار است. شما ارتباط با حساب Pro را از دست نخواهید داد.

مرحله ۴ : کلید را در Ollama.com ثبت کنید

به https://ollama.com/settings/keys → کلید SSH را اضافه کنید. کلید عمومی Docker را جایگذاری کنید و تأیید نمایید.

سپس، این هویت را به حساب Pro B متصل می‌کنیم:

$ docker exec -it ollama-instance-b ollama signin

مرورگر باز می‌شود، با ایمیل حساب B وارد می‌شویم و توکن به کلید SSH conteneur مرتبط می‌شود. بررسی می‌کنیم که همه چیز OK است :

$ docker exec -it ollama-instance-b ollama signin
User: cherolivpro

مرحله ۵ : آزمایش کنید با یک مدل کوچک و رایگان

قبل از رد قیمت اشتراک Pro، می‌خواهم مطمئن شوم لول کار می‌کند. یک مدل محلی و رایگان کوچک را می‌کش تا اتصال را تأیید کنم :

$ docker exec ollama-instance-b ollama pull qwen3:0.6b
pulling manifest
pulling 7f4030143c1c: 100% ▕██████████████████▏ 522 MB
success

$ curl -s http://localhost:11435/api/tags
{"models":[{"name":"qwen3:0.6b","model":"qwen3:0.6b",...}]}

بندر`11435`جواب می‌دهد، مدل آماده است. نمونه B زنده است.

بعد از اطمینان یافتن، من به pull مدل واقعی cloud Pro می‌رم :

$ docker exec ollama-instance-b ollama pull deepseek-v4-pro:cloud
pulling manifest
pulling 31c3059e137e: 100% ▕██████████████████▏  344 B
success

344 بایت برای منیفست مدل cloud — عادی است، استنتاج سمت سرور انجام می‌شود، نه به صورت محلی. و اینجا تست نهایی است:

$ curl -s http://localhost:11435/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model":"deepseek-v4-pro:cloud","messages":[{"role":"user","content":"Dis bonjour en une phrase courte."}]}'

{
  "id": "chatcmpl-480",
  "model": "deepseek-v4-pro",
  "choices": [{
    "message": { "content": "Bonjour !" },
    "finish_reason": "stop"
  }],
  "usage": { "total_tokens": 181 }
}

سلام به تو نیز، نمونه B.

پانگه API `/v1/models

من 20 دقیقه را به دلیل یک جزئی احمق گم کردم. وقتی provider را پیکربندی کردم`ollama-b`در OpenCode، هیچ چیزی در انتخاب‌کننده مدل‌ها نمایان نمی‌شد. هیچ چیز. اصلاً.

دلیل؟ API`/v1/models`از نمونه B برمی‌گشت`{"object":"list","data":null}`به جای`{"object":"list","data":[]}`وقتی هیچ مدلی کشیده نشده بود. مقدار`null`پارس کردن را در طرف OpenCode باعث crash می‌شد که provider را نمایش نمی‌داد.

حل: تعریفه مدل‌های صریحاً در تنظیمات OpenCode به جای اعتماد بر كشف دینامیک

~/.config/opencode/opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "ollama": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Ollama (local)",
      "options": { "baseURL": "http://localhost:11434/v1" },
      "models": {
        "gemma4:e2b": { "name": "Gemma 4 E2B (local)" }
      }
    },
    "ollama-b": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Ollama Instance B (Docker)",
      "options": { "baseURL": "http://localhost:11435/v1" },
      "models": {
        "qwen3:0.6b": { "name": "Qwen3 0.6B (B)" },
        "deepseek-v4-pro:cloud": { "name": "DeepSeek V4 Pro (B)" }
      }
    }
  }
}

با این اظهارات صریح، OpenCode به سرعت ارائه دهنده B و مدل‌های آن را می‌بیند. بازنشانی جلسه و سپس انتخابگر`/models`نمایش دو مورد کنار هم.

اگر ارائه‌دهنده سفارشی خود را در`/models`, سه ساعت را برای راه‌اندازی مجدد ترمینال خود هدر ندهید. مدل‌ها را به صورت دستی در`opencode.json`— این مشکل را به طور فوری حل می‌کند.

نتیجه: دو جلسه، دو حساب، بدون تعارض

در نهایت، می‌توانم دو جلسه OpenCode را به‌صورت همزمان راه‌اندازی کنم :

Session 1 → /models → Ollama (local) → deepseek-v4-pro:cloud → Compte A
Session 2 → /models → Ollama Instance B (Docker) → deepseek-v4-pro:cloud → Compte B

هر جلسه محدودیت خاص خود، محدودیت نرخ خاص خود را دارد و با یکدیگر تداخل نمی‌کند. همان ماشین، همان کارت آبی، دو ایمیل متفاوت.

و بهترین بخش؟ کانتینر Docker در`restart: always`.سیستم پس از ریبوت‌ها بدون دخالت دستی زنده می‌ماند.

دروس آموخته

  1. داکر همه چیز را، حتی هویت را، از بقیه جدا می‌کندیک bind mount سادهٔ حجم کافی است تا به یک کانتینر کلیدهای SSH اختصاصی بدهد، که از دید Ollama ناپذیر تمایز با یک ماشین فیزیکی دیگر باشد.

  2. دو ایمیل، همان کارت بانکی— Ollama اشتراک‌های多重 را از همان روش پرداخت مسدود نمی‌کند؛ فقط ایمیل باید متمایز باشد.

  3. آزمایش رایگان قبل از پرداخت — Un ollama pull qwen3:0.6b (modèle libre, 522 Mo) permet de valider toute la chaîne réseau sans débourser un centime. Vous validez le plomberie d’abord, vous activez le Pro ensuite.

  4. /v1/models` با data: null OpenCode را می‌شکند— اگر شما یک provider سفارشی را پیکربندی کنید با`"models": {}`, OpenCode سعی می‌کند الگو‌ها را از طریق API کشف کند. اگر API پاسخ دهد`data: null`، ارائه‌دهنده نمایش داده نمی‌شود. مدل‌ها را به صورت صریح اعلام کنید.

  5. دو حساب، یعنی پردازش چندفراید انسانی— یک حساب Pro = یک sesión OpenCode فعال. دو حساب = دو جلسه موازی. برای کسی که در حال جابجایی بین چندین پروژه Gradle همزمان است، این یک گیم چینجر است.

مقالات مرتبط