सामग्री पर जाएँ

कंटेनर इमेज ​

हर Arkvory रिपॉज़िटरी एक कंटेनर रजिस्ट्री भी है। Docker, Podman, Buildx, containerd, Helm और ORAS OCI Distribution प्रोटोकॉल से उसमें पुश करते हैं और उससे पुल करते हैं। इमेज लेयर और मैनिफ़ेस्ट सामान्य आर्टिफ़ैक्ट के रूप में सहेजे जाते हैं। रिपॉज़िटरी की अनुमतियाँ, कोटा, SHA-256 जाँच, बैकअप और मिरर उन पर वैसे ही लागू होते हैं जैसे किसी भी दूसरी फ़ाइल पर।

शुरू करने से पहले ​

आपको चाहिए:

  • HTTPS और विश्वसनीय सर्टिफ़िकेट वाला सर्वर पता, उदाहरण के लिए arkvory.example। HTTPS देखें।
  • एक रिपॉज़िटरी, उदाहरण के लिए releases।
  • एक कुंजी: व्यक्तिगत एक्सेस टोकन या सेवा कुंजी। खाते और कुंजियाँ देखें।

रजिस्ट्री होस्ट के रूट पर /v2/ के अंतर्गत उत्तर देती है। वह https://example.com/arkvory/ जैसे पथ उपसर्ग के नीचे काम नहीं कर सकती, क्योंकि Docker उसका समर्थन नहीं करता। रिवर्स प्रॉक्सी को /v2/ बिना बदले आगे भेजना चाहिए और अनुरोध की बॉडी को बफ़र नहीं करना चाहिए। nginx में client_max_body_size 0 सेट करें और अनुरोध बफ़रिंग बंद करें।

इमेज के नाम ​

इमेज संदर्भ का रूप यह है:

text
<host>/<repository>/<image>:<tag>
<host>/<repository>/<image>@sha256:<digest>

पथ का पहला खंड Arkvory रिपॉज़िटरी है। यही एक्सेस की सीमा है: कुंजी केवल उन्हीं रिपॉज़िटरी को देखती है जिनकी उसे अनुमति मिली है। बाकी हिस्सा इमेज का नाम है, जिसमें एक या अधिक घटक हो सकते हैं।

संदर्भरिपॉज़िटरीइमेजसंदर्भ का हिस्सा
arkvory.example/releases/web:1.4releaseswebटैग 1.4
arkvory.example/releases/team/web:1.4releasesteam/webटैग 1.4
arkvory.example/qa/tools/builder@sha256:…qatools/builderडाइजेस्ट
भागनियम
रिपॉज़िटरीलोअरकेस अक्षर, अंक, _ और -। अक्षर या अंक से शुरू होती है। अधिकतम 64 वर्ण।
इमेज/ से अलग किए गए घटक। हर घटक में लोअरकेस अक्षर और अंक होते हैं, जो ., _, __ या डैश से जुड़े हों। कुल मिलाकर अधिकतम 200 वर्ण।
टैगअक्षर, अंक, _, . और -। अक्षर, अंक या _ से शुरू होता है। अधिकतम 128 वर्ण।
डाइजेस्टsha256: और 64 लोअरकेस हेक्साडेसिमल अंक। दूसरे एल्गोरिदम अस्वीकार किए जाते हैं।

इमेज वाले हिस्से के बिना संदर्भ, जैसे arkvory.example/web:1.4, NAME_INVALID के साथ अस्वीकार किया जाता है: web को रिपॉज़िटरी मान लिया जाता है, और इमेज का नाम खाली रहता है।

लॉग इन करें ​

रजिस्ट्री Arkvory की कुंजी को HTTP Basic प्रमाणीकरण के पासवर्ड के रूप में लेती है। उपयोगकर्ता नाम जाँचा नहीं जाता: कोई भी नाम इस्तेमाल करें, उदाहरण के लिए CI जॉब का नाम। अनुरोध कुंजी को Authorization: Bearer <key> के रूप में भी भेज सकता है। आपको अलग टोकन सेवा नहीं चाहिए।

bash
docker login arkvory.example -u ci --password-stdin < ~/.arkvory/key
powershell
Get-Content C:\Private\arkvory.key | docker login arkvory.example -u ci --password-stdin

दूसरे क्लाइंट इसी तरह लॉग इन करते हैं:

bash
podman login arkvory.example -u ci --password-stdin < ~/.arkvory/key
helm registry login arkvory.example -u ci --password-stdin < ~/.arkvory/key
oras login arkvory.example -u ci --password-stdin < ~/.arkvory/key
कुंजीकिसके लिए इस्तेमाल करें
व्यक्तिगत एक्सेस टोकन, स्कोप readवर्कस्टेशन पर पुल करने के लिए
व्यक्तिगत एक्सेस टोकन, स्कोप read-writeवर्कस्टेशन से पुश करने के लिए
सेवा कुंजीCI/CD और डिप्लॉयमेंट एजेंट। यही एकमात्र प्रकार की कुंजी है जो इमेज हटा सकती है।
सर्वर की कुंजी फ़ाइल से फ़ाइल कुंजीइंस्टॉलेशन का स्वामी और पुराने इंटीग्रेशन (read या write)

व्यक्तिगत टोकन समाप्त हो जाता है। उसके बाद हर अनुरोध को 401 UNAUTHORIZED मिलता है: नया टोकन बनाएँ और फिर से लॉग इन करें। जब तक आप क्रेडेंशियल हेल्पर कॉन्फ़िगर नहीं करते, Docker कुंजी को ~/.docker/config.json में सहेजता है। उस फ़ाइल की सुरक्षा करें या क्रेडेंशियल स्टोर इस्तेमाल करें।

पुश और पुल ​

bash
docker tag web:1.4 arkvory.example/releases/team/web:1.4
docker push arkvory.example/releases/team/web:1.4
docker pull arkvory.example/releases/team/web:1.4
docker pull arkvory.example/releases/team/web@sha256:<digest>

रजिस्ट्री क्या करती है:

  • जो लेयर रिपॉज़िटरी में पहले से है, उसे दोबारा नहीं सहेजा जाता, भले ही उसे कोई दूसरी इमेज इस्तेमाल करे।
  • लेयर रिपॉज़िटरी के बीच साझा नहीं होतीं। किसी दूसरी रिपॉज़िटरी से लेयर माउंट करने का अनुरोध सामान्य अपलोड सत्र पाता है, इसलिए क्लाइंट लेयर दोबारा भेजता है।
  • हर लेयर और हर मैनिफ़ेस्ट की जाँच उसके SHA-256 डाइजेस्ट से होती है। बेमेल होने पर कुछ नहीं सहेजा जाता और DIGEST_INVALID लौटता है।
  • मैनिफ़ेस्ट तभी स्वीकार होता है जब वह जिस-जिस का हवाला देता है वह सब रिपॉज़िटरी में पहले से हो: इमेज का config और लेयर, या इंडेक्स के प्लेटफ़ॉर्म मैनिफ़ेस्ट। प्लेटफ़ॉर्म मैनिफ़ेस्ट अपने इंडेक्स वाली ही इमेज में होने चाहिए। नहीं तो उत्तर MANIFEST_BLOB_UNKNOWN होता है।
  • लेयर डाउनलोड Range अनुरोधों का समर्थन करते हैं।

रजिस्ट्री ये मैनिफ़ेस्ट प्रकार स्वीकार करती है:

मीडिया प्रकारकिसके लिए
application/vnd.oci.image.manifest.v1+jsonOCI इमेज, Helm चार्ट, ORAS आर्टिफ़ैक्ट
application/vnd.oci.image.index.v1+jsonमल्टी-प्लेटफ़ॉर्म इमेज, BuildKit रजिस्ट्री कैश
application/vnd.docker.distribution.manifest.v2+jsonDocker इमेज (schema 2)
application/vnd.docker.distribution.manifest.list.v2+jsonDocker मल्टी-प्लेटफ़ॉर्म इमेज

मैनिफ़ेस्ट में schemaVersion: 2 होता है और वह अधिकतम 4 MiB का होता है। Docker schema 1 समर्थित नहीं है। प्रकार Content-Type हेडर या मैनिफ़ेस्ट के mediaType फ़ील्ड से आता है, और दोनों का मेल होना चाहिए। पुल मैनिफ़ेस्ट को ठीक उसी रूप में लौटाता है जैसे वह पुश किया गया था, अपने मीडिया प्रकार के साथ। रजिस्ट्री फ़ॉर्मेट के बीच रूपांतरण नहीं करती।

मल्टी-प्लेटफ़ॉर्म इमेज ​

bash
docker buildx build --platform linux/amd64,linux/arm64 \
  -t arkvory.example/releases/team/web:1.4 --push .

Buildx हर प्लेटफ़ॉर्म मैनिफ़ेस्ट को उसके डाइजेस्ट से पुश करता है, फिर इंडेक्स को टैग के नीचे। सभी एक ही इमेज नाम पर जाते हैं, जैसा रजिस्ट्री माँगती है।

बिल्ड कैश ​

कैश एक्सपोर्ट कर सकने वाला BuildKit बिल्डर, उदाहरण के लिए docker-container ड्राइवर वाला docker buildx बिल्डर, अपना रजिस्ट्री कैश Arkvory में रख सकता है:

bash
docker buildx build \
  --cache-from type=registry,ref=arkvory.example/releases/team/web:cache \
  --cache-to type=registry,ref=arkvory.example/releases/team/web:cache,mode=max \
  -t arkvory.example/releases/team/web:1.4 --push .

कैश इंडेक्स लेयर और कैश कॉन्फ़िगरेशन की सूची देता है। Arkvory उन्हें इमेज के ब्लॉब के रूप में सहेजता है और किसी भी सहेजे गए मैनिफ़ेस्ट की लेयर की तरह उनकी सुरक्षा करता है।

Helm चार्ट ​

Helm चार्ट को OCI आर्टिफ़ैक्ट के रूप में सहेजता है। helm registry login के बाद:

bash
helm push web-1.4.0.tgz oci://arkvory.example/releases/charts
helm pull oci://arkvory.example/releases/charts/web --version 1.4.0
helm install web oci://arkvory.example/releases/charts/web --version 1.4.0

चार्ट रिपॉज़िटरी releases में टैग 1.4.0 के साथ इमेज charts/web बन जाता है। Arkvory में index.yaml फ़ाइल वाली पारंपरिक चार्ट रिपॉज़िटरी नहीं है।

ORAS आर्टिफ़ैक्ट ​

ORAS किसी भी फ़ाइल को OCI मैनिफ़ेस्ट की लेयर के रूप में सहेजता है:

bash
oras push arkvory.example/releases/tools/settings:1.0 ./settings.json:application/json
oras pull arkvory.example/releases/tools/settings:1.0

Referrers API उपलब्ध नहीं है: /v2/<name>/referrers/<digest> 404 देता है। OCI विनिर्देश का पालन करने वाले क्लाइंट, जैसे ORAS, तब संलग्न आर्टिफ़ैक्ट को डाइजेस्ट के नाम वाले टैग के नीचे रखते हैं।

टैग और डाइजेस्ट ​

  • मैनिफ़ेस्ट को किसी टैग के नीचे पुश करने से टैग खिसककर नए मैनिफ़ेस्ट पर आ जाता है। टैग जिस मैनिफ़ेस्ट का नाम पहले था, वह रजिस्ट्री में बना रहता है और अब भी डाइजेस्ट से पुल किया जा सकता है।
  • डाइजेस्ट से पुश (PUT /v2/<name>/manifests/sha256:…) मैनिफ़ेस्ट को बिना टैग के सहेजता है। डाइजेस्ट बॉडी का SHA-256 होना चाहिए।
  • टैग बाइट क्रम में सूचीबद्ध होते हैं, इसलिए बड़े अक्षर छोटे अक्षरों से पहले आते हैं।

किसी इमेज के टैग सूचीबद्ध करें:

bash
curl -fsS -u "ci:$ARKVORY_KEY" https://arkvory.example/v2/releases/team/web/tags/list

उत्तर {"name": "releases/team/web", "tags": [...]} होता है। पेज के आकार के लिए n (डिफ़ॉल्ट रूप से 100, अधिकतम 1000) और पिछले पेज के आख़िरी टैग के लिए last इस्तेमाल करें। और टैग होने पर Link हेडर में अगले पेज का पता होता है।

किसी टैग का डाइजेस्ट खोजें:

bash
curl -fsSI -u "ci:$ARKVORY_KEY" \
  https://arkvory.example/v2/releases/team/web/manifests/1.4 | grep -i docker-content-digest

सभी इमेज का कैटलॉग (/v2/_catalog) नहीं है। कंसोल में लेयर और मैनिफ़ेस्ट रिपॉज़िटरी के आर्टिफ़ैक्ट के बीच लेबल oci के साथ, अपने डाइजेस्ट के नाम से दिखते हैं। उन्हें दिखाने के लिए आर्टिफ़ैक्ट अनुभाग में लेबल से फ़िल्टर करें इस्तेमाल करें।

इमेज हटाएँ और जगह खाली करें ​

आप इमेज को रजिस्ट्री API से हटाते हैं। Docker कमांड लाइन में इसके लिए कोई कमांड नहीं है: curl, oras manifest delete या कोई दूसरा रजिस्ट्री टूल इस्तेमाल करें।

अनुरोधप्रभाव
DELETE /v2/<name>/manifests/<tag>केवल टैग हटाता है। मैनिफ़ेस्ट बना रहता है और डाइजेस्ट से पुल किया जा सकता है।
DELETE /v2/<name>/manifests/<digest>मैनिफ़ेस्ट और उसकी ओर इशारा करने वाला हर टैग हटाता है
DELETE /v2/<name>/blobs/<digest>405 के साथ अस्वीकार। लेयर अपने मैनिफ़ेस्ट के साथ ही जाती हैं।

दोनों तरह से हटाने के लिए रिपॉज़िटरी में artifact.delete कार्रवाई वाली सेवा कुंजी चाहिए। व्यक्तिगत टोकन, कंसोल सत्र और फ़ाइल कुंजियाँ इमेज नहीं हटा सकतीं। हटाने पर उत्तर 202 होता है।

bash
curl -fsS -X DELETE -H "Authorization: Bearer $ARKVORY_CLEANUP_KEY" \
  https://arkvory.example/v2/releases/team/web/manifests/sha256:<digest>

जगह कैसे खाली होती है:

  1. जब तक कोई मैनिफ़ेस्ट सहेजा है, टैग के साथ या उसके बिना, Arkvory उसकी और उसकी हर लेयर की रक्षा करता है। प्रतिधारण उन्हें ब्लॉकर reference के साथ छोड़ देता है।
  2. टैग को खिसकाने या हटाने से कुछ खाली नहीं होता। पुराने मैनिफ़ेस्ट तब तक अपनी लेयर रखते हैं जब तक आप उन मैनिफ़ेस्ट को डाइजेस्ट से नहीं हटाते।
  3. डाइजेस्ट से मैनिफ़ेस्ट हटाने के बाद उसका आर्टिफ़ैक्ट और वे लेयर, जिन्हें कोई दूसरा मैनिफ़ेस्ट इस्तेमाल नहीं करता, यह सुरक्षा खो देते हैं। वे तब तक सहेजे रहते हैं जब तक कोई उन्हें प्रतिधारण से नहीं हटाता या आर्टिफ़ैक्ट के रूप में नहीं हटाता। स्टोरेज देखें।
  4. जो लेयर बिना मैनिफ़ेस्ट के पुश की गई, उदाहरण के लिए विफल पुश से, वह सुरक्षित नहीं है।
  5. जब हटाई गई लेयर की फिर ज़रूरत पड़ती है, तो रजिस्ट्री उसे अज्ञात बताती है, और अगला पुश उसे फिर अपलोड करता है।

अनुमतियाँ ​

व्यक्तिगत टोकन और फ़ाइल कुंजियों को रिपॉज़िटरी का पढ़ने या लिखने का एक्सेस मिलता है। सेवा कुंजियों को सटीक कार्रवाइयाँ मिलती हैं।

ऑपरेशनसेवा कुंजी की कार्रवाइयाँव्यक्तिगत टोकन या फ़ाइल कुंजी
मैनिफ़ेस्ट और लेयर पुल करनाcontent.readपढ़ने का एक्सेस
टैग सूचीबद्ध करनाartifact.listपढ़ने का एक्सेस
पुशupload.create, upload.write, upload.completeलिखने का एक्सेस; टोकन को स्कोप read-write चाहिए
टैग या मैनिफ़ेस्ट हटानाartifact.deleteसंभव नहीं

पुश करने वाली CI कुंजी आमतौर पर पुल भी करती है, उदाहरण के लिए बेस इमेज या बिल्ड कैश। उसे content.read और artifact.list भी दें। जिस रिपॉज़िटरी का एक्सेस कुंजी को नहीं दिया गया है, उसका उत्तर 403 DENIED होता है।

रीड गेटवे और मिरर ​

  • रीड गेटवे पुल परोसता है। पुश को 405 मिलता है।
  • मिरर अपने स्रोत की इमेज उनके टैग और हटाए जाने के साथ प्राप्त करता है। क्लाइंट मिरर से उसके अपने पते पर पुल करते हैं। पुश को 409 DENIED मिलता है, जिसका कारण mirror_read_only है।

सीमाएँ ​

सीमामान
मैनिफ़ेस्ट का आकार4 MiB
लेयर का आकारइंस्टॉलेशन का सबसे बड़ा ऑब्जेक्ट, ARKVORY_MAX_OBJECT_BYTES (डिफ़ॉल्ट रूप से लगभग 10 TiB)
एक अपलोड अनुरोध30 मिनट के भीतर पूरा होना चाहिए और 30 सेकंड से ज़्यादा रुकना नहीं चाहिए (ARKVORY_UPLOAD_DEADLINE_MS, ARKVORY_UPLOAD_IDLE_TIMEOUT_MS)। 30 मिनट अनुमत सबसे ऊँचा मान भी है।
अधूरा अपलोडबिना गतिविधि के 24 घंटे बाद उसके बाइट सहित हटा दिया जाता है
अस्थायी डिस्क स्पेसअपलोड के दौरान लेयर के आकार का दोगुना तक
एक साथ अपलोडडिफ़ॉल्ट रूप से प्रति कुंजी 1 और प्रति सर्वर 2 (ARKVORY_MAX_UPLOADS_PER_PRINCIPAL, ARKVORY_MAX_UPLOADS)। प्रतीक्षा करता अनुरोध 20 सेकंड बाद प्रतीक्षा छोड़ देता है (ARKVORY_TRANSFER_QUEUE_TIMEOUT_MS)।
एक साथ डाउनलोडडिफ़ॉल्ट रूप से प्रति कुंजी 4 और प्रति सर्वर 16
प्रति पेज टैग1000
कोटालेयर, मैनिफ़ेस्ट और अधूरे अपलोड के बाइट रिपॉज़िटरी कोटा और इंस्टॉलेशन की क्षमता में गिने जाते हैं

Docker हर लेयर को एक ही अनुरोध में भेजता है। इसलिए लेयर अपलोड की समय-सीमा के भीतर पहुँचनी चाहिए, और विफल लेयर अपलोड पहले बाइट से फिर शुरू होता है। कई गीगाबाइट की फ़ाइलों के लिए इसके बजाय arkvoryctl इस्तेमाल करें: वह भागों में अपलोड करता है और विफलता के बाद जारी रहता है। वेरिएबल एनवायरनमेंट वेरिएबल में वर्णित हैं।

समर्थित नहीं ​

  • Referrers API। यह 404 देता है, और क्लाइंट टैग पर लौट आते हैं।
  • सभी इमेज का कैटलॉग, /v2/_catalog।
  • किसी दूसरी रिपॉज़िटरी से लेयर माउंट करना। क्लाइंट लेयर दोबारा अपलोड करता है।
  • Bearer टोकन के लिए टोकन सेवा। कुंजी को ही Basic या Bearer के साथ भेजें।
  • Docker Hub या दूसरी रजिस्ट्रियों का पुल-थ्रू कैश।
  • Docker schema 1 मैनिफ़ेस्ट और sha256 के अलावा दूसरे डाइजेस्ट।
  • अलग-अलग लेयर हटाना।
  • कंसोल में इमेज के लिए अनुभाग।

टेस्ट के लिए सादा HTTP ​

Docker बिना HTTPS वाली रजिस्ट्री अस्वीकार करता है। डिफ़ॉल्ट रूप से केवल स्थानीय कंप्यूटर के पते (localhost, 127.0.0.0/8) सादे HTTP पर काम करते हैं। किसी दूसरे होस्ट पर चल रहे टेस्ट सर्वर के लिए उसे Docker डेमन कॉन्फ़िगरेशन (Linux पर /etc/docker/daemon.json) के insecure-registries में जोड़ें और Docker रीस्टार्ट करें:

json
{
  "insecure-registries": ["arkvory.test:8080"]
}

Podman विकल्प --tls-verify=false इस्तेमाल करता है। सादे HTTP पर कुंजी स्पष्ट पाठ में जाती है। इसे केवल टेस्ट नेटवर्क पर इस्तेमाल करें।

अपनी सर्टिफ़िकेट अथॉरिटी के सर्टिफ़िकेट के लिए Linux पर Docker, CA को /etc/docker/certs.d/<host>/ca.crt से पढ़ता है (पोर्ट के साथ, अगर वह 443 नहीं है)। Docker Desktop सिस्टम के ट्रस्ट स्टोर का इस्तेमाल करता है।

समस्या निवारण ​

Docker रजिस्ट्री के त्रुटि कोड छोटे अक्षरों में और स्पेस के साथ छापता है, उदाहरण के लिए denied या name invalid, और उसके बाद सर्वर का संदेश। हर त्रुटि में detail.requestId में अनुरोध ID भी होती है। इसे अपने व्यवस्थापक को दें: वह सर्वर लॉग में अनुरोध ढूँढ लेता है।

त्रुटिकारणक्या करें
UNAUTHORIZED (401)कुंजी गायब, गलत, समाप्त या निरस्त हैवैध कुंजी से फिर लॉग इन करें
DENIED (403)कुंजी लिख नहीं सकती या रिपॉज़िटरी नहीं देखती। स्कोप read वाले टोकन को "Read-only personal access token" मिलता है।इस रिपॉज़िटरी में लिखने के एक्सेस वाली कुंजी इस्तेमाल करें
DENIED (409)रिपॉज़िटरी मिरर हैमुख्य सर्वर पर पुश करें
DENIED (507)रिपॉज़िटरी का कोटा या इंस्टॉलेशन की क्षमता पूरी हो गई है। अधूरे अपलोड भी गिने जाते हैं।जगह खाली करें या बड़ा कोटा माँगें
NAME_INVALIDसंदर्भ में रिपॉज़िटरी के बाद इमेज वाला हिस्सा नहीं है, या उसमें बड़े अक्षर हैंलोअरकेस में <host>/<repository>/<image>:<tag> इस्तेमाल करें
MANIFEST_UNKNOWNटैग या डाइजेस्ट इस इमेज में मौजूद नहीं हैtags/list से नाम जाँचें
MANIFEST_BLOB_UNKNOWNमैनिफ़ेस्ट ऐसी लेयर या प्लेटफ़ॉर्म मैनिफ़ेस्ट का हवाला देता है जो इस रिपॉज़िटरी में नहीं हैपूरी इमेज फिर से पुश करें, ताकि क्लाइंट छूटे हुए हिस्से अपलोड करे
DIGEST_INVALIDबाइट डाइजेस्ट से मेल नहीं खातेफिर से पुश करें। बार-बार हो तो प्रॉक्सी जाँचें।
TOOMANYREQUESTS (503 या 429)इस कुंजी के बहुत सारे ट्रांसफ़र एक साथ चल रहे हैं, या सर्वर व्यस्त हैप्रतीक्षा करें और दोबारा आज़माएँ। क्लाइंट के समानांतर अपलोड घटाएँ, उदाहरण के लिए Docker डेमन कॉन्फ़िगरेशन में "max-concurrent-uploads": 1, या व्यवस्थापक से ट्रांसफ़र सीमाएँ बढ़ाने को कहें।
http: server gave HTTP response to HTTPS clientसर्वर में HTTPS नहीं हैHTTPS सेट करें, या टेस्ट सर्वर के लिए insecure-registries इस्तेमाल करें
x509: certificate signed by unknown authorityDocker सर्टिफ़िकेट पर भरोसा नहीं करताCA सर्टिफ़िकेट इंस्टॉल करें, जैसा ऊपर बताया गया है
413 Request Entity Too Largeरिवर्स प्रॉक्सी अनुरोध का आकार सीमित करता हैnginx में client_max_body_size 0 सेट करें
बड़ी लेयर 30 मिनट बाद रुक जाती हैएक अनुरोध की अपलोड समय-सीमातेज़ नेटवर्क इस्तेमाल करें, या ऐसी फ़ाइलें इमेज से बाहर रखें और arkvoryctl से अपलोड करें

Arkvory · ProAnimaStudio