Qdrant Dockerは、公式イメージqdrant/qdrantを起動するだけでベクトル検索のサーバーが手元に立ち上がる構成です。この記事では、2026年10月22日公開のv1.20.0を前提に、タグとポートの選び方、データを消さない永続化、Docker ComposeでのAPIキーと非root実行の設定、qdrant-clientとcurlでのコレクション作成・upsert・検索までを、Qdrant公式ドキュメントの記述に沿って順に動かします。後半では、Windowsでのデータ破損やスナップショットの版互換など本番前に確かめる点と、Docker単体で運用を続けてよい条件も示します。
まとめ:Qdrant Dockerは永続化先・公開ポート・APIキーを起動時に決める
試すだけならdocker run -p 6333:6333 qdrant/qdrantの1行で動きます。ただし、そのままでは全インターフェースに認証なしで公開され、コンテナを消せばデータも消えます。起動コマンドを書く時点で、名前付きボリュームへの永続化、127.0.0.1に絞ったポート公開、QDRANT__SERVICE__API_KEYの3つを入れておくのが安全です。
イメージはlatestではなくv1.20.0のように版を固定します。スナップショットは同じminor版か次のminor版にしか戻せず、Pythonクライアントもサーバーとminor差1以内で揃える必要があるためです。単一ノードのDocker運用は社内検証や小規模なRAGまでとし、可用性が要る段階でKubernetesかQdrant Cloudへ移します。
Qdrant Dockerで動かす前に確認するイメージのタグ・ポート・ストレージ要件
起動コマンドを書く前に決めることは3つあります。どのタグを使うか、どのポートをどこまで開けるか、データをどのファイルシステムに置くかです。ベクトルDBそのものの仕組みと製品の違いはベクトルDBとは?仕組み・インデックス構造・製品比較とpgvectorでの作り方にまとめているので、この記事は構築に絞ります。
qdrant/qdrantのタグ選びとv1.20.0・unprivileged版の違い
Docker Hubのqdrant/qdrantには、2026年11月8日時点でv1.20.0・v1.20・v1・latestのほか、末尾に-unprivilegedや-gpu-nvidia・-gpu-amdが付くタグが並んでいます。GitHubのv1.20.0リリースが現行の最新版です。
実務で選ぶのは2択で足ります。通常はv1.20.0のようなパッチ版まで固定したタグ、本番に近い環境ならroot権限を持たないv1.20.0-unprivilegedです。latestは再作成のたびに版が変わり、後述するスナップショットの版互換を崩すので、検証の初回以外では使いません。GPU版はインデックス構築を速めるためのもので、数万件規模の検証では不要です。
6333・6334・6335の3ポートの役割と開発時に公開する範囲
公式のInstallation requirementsによると、6333はHTTP(REST API)、6334はgRPC API、6335は分散構成のノード間通信に使います。ブラウザで開く管理画面も6333の/dashboardで提供されます。
単一ノードで動かすなら6335は外に出しません。開発機でもホスト側を127.0.0.1に限定して公開します。公式のSecurity & Access Controlは、セルフホストのQdrantは既定で全ネットワークインターフェースにbindし、認証も設定されていないと明記しており、クラウドのVMで-p 6333:6333のまま起動すると、インターネットから誰でも読み書きできる状態になります。
NFSやWSLの共有フォルダで壊れるストレージ要件と名前付きボリューム
同じInstallationページは、永続ストレージにPOSIX互換のファイルシステムとブロックレベルのアクセスを求め、NFSなどのネットワークファイルシステムやS3のようなオブジェクトストレージでは動かないと書いています。EFSを共有マウントしてデータを置く構成は、この条件に当たるので採用できません。
Windowsも要注意です。公式のSolving common errorsには、WSLベースのDockerでWindowsのフォルダをマウントすると完全なPOSIX互換にならず、再起動後にベクトルがすべてゼロになるなどのデータ消失が起こりうるとあります。v1.15.0以降は起動時にファイルシステムを検査し、警告やエラーをログに出します。Windowsではdocker volume createで作る名前付きボリュームを使い、C:\配下のフォルダを直接マウントしないでください。
docker runとDocker ComposeでQdrantを起動して永続化する手順
ここからは実際に起動します。最初にdocker runで動作を確かめ、続けて設定をComposeファイルへ移すと、再作成のたびにオプションを打ち直す手間がなくなります。コンテナイメージの基礎はDockerfileとは|書き方・主要命令とsyntaxの版も参照してください。
docker runで1行起動してダッシュボードとreadyzを確認する手順
次のコマンドは、名前付きボリュームにデータを置き、6333と6334をローカルホストだけに公開して起動する例です。最後のcurlで起動完了を確かめます。
# 版を固定してイメージを取得する
docker pull qdrant/qdrant:v1.20.0
# データ用の名前付きボリュームを作る(Windowsでもこの方式なら安全)
docker volume create qdrant-storage
# ローカルホストだけに公開して起動する
docker run -d --name qdrant \
-p 127.0.0.1:6333:6333 -p 127.0.0.1:6334:6334 \
-v qdrant-storage:/qdrant/storage \
qdrant/qdrant:v1.20.0
# 起動確認(200が返れば準備完了)
curl -i http://localhost:6333/readyz
公式のMonitoring & Telemetryでは、/healthz・/livez・/readyzの3つが状態確認用のエンドポイントとして案内されています。ブラウザでlocalhost:6333/dashboardを開くと、コレクションの一覧と中身を画面で確認できる仕組みです。docker rm qdrantでコンテナを消してもボリュームは残り、同じ-vで起動し直せばデータは戻ります。
compose.yamlで永続化・APIキー・非root実行をまとめて書く設定例
チームで同じ環境を立てるなら、設定をComposeファイルに固めます。次の例は、公式のSecurityページのHardening節が勧める非rootイメージと、Solving common errorsのファイル数上限の対策を1つにまとめたものです。
# compose.yaml(.env に QDRANT_API_KEY と QDRANT_RO_API_KEY を置く)
services:
qdrant:
image: qdrant/qdrant:v1.20.0-unprivileged
container_name: qdrant
restart: unless-stopped
ports:
- "127.0.0.1:6333:6333"
- "127.0.0.1:6334:6334"
environment:
QDRANT__SERVICE__API_KEY: ${QDRANT_API_KEY}
QDRANT__SERVICE__READ_ONLY_API_KEY: ${QDRANT_RO_API_KEY}
volumes:
- qdrant-storage:/qdrant/storage
- qdrant-snapshots:/qdrant/snapshots
ulimits:
nofile:
soft: 10000
hard: 10000
volumes:
qdrant-storage:
qdrant-snapshots:
docker compose up -dで起動し、docker compose downでは停止だけを行います。down -vを付けるとボリュームごと消えるので、手順書には付けない形で書いておきます。root版のイメージで作ったボリュームを非root版へ引き継ぐ場合は、中のファイル所有者がコンテナの実行ユーザーと合っているかを先に確かめてください。
環境変数QDRANT__で設定を上書きする書式とconfig.yamlの既定値
公式のConfigurationページによると、環境変数はQDRANT__で始め、階層を__(アンダースコア2つ)で区切ります。設定ファイルより常に優先されるため、上のComposeのように秘密情報だけを環境変数で渡し、それ以外は既定値のまま使う構成が扱いやすくなります。
既定値はv1.20.0のconfig.yamlで確認できます。service.http_portは6333、grpc_portは6334、max_request_size_mbは32、enable_tlsはfalse、api_keyはコメントアウトされた状態です。大量のベクトルを1回のupsertで送ると32MBの上限に当たるため、数千件単位に分けて送るかQDRANT__SERVICE__MAX_REQUEST_SIZE_MBで引き上げます。
コレクション作成・upsert・ベクトル検索をPythonとRESTで動かす手順
サーバーが立ったら、データを入れて検索します。ここでは4次元の小さなベクトルで流れを確かめ、実データでは埋め込みモデルの出力次元に置き換える手順です。テキストからベクトルを作る部分はPythonでembeddingを生成する方法で扱っています。
qdrant-client 1.20系でコレクションを作りupsertと検索を通すコード
PyPIのqdrant-clientは2026年10月22日公開の1.20.0が最新で、Python 3.10以上が必要です。次のコードは、コレクションが無ければ作り、3件をupsertしてから、ペイロードの部署で絞り込んで検索します。
# pip install "qdrant-client==1.20.0"
import os
from qdrant_client import QdrantClient, models
client = QdrantClient(
url="http://localhost:6333",
api_key=os.environ.get("QDRANT_API_KEY"),
)
COL = "docs"
# 次元数と距離はコレクション作成時に決まり、後から変えられない
if not client.collection_exists(COL):
client.create_collection(
collection_name=COL,
vectors_config=models.VectorParams(size=4, distance=models.Distance.COSINE),
)
client.upsert(
collection_name=COL,
wait=True, # 書き込みの反映を待ってから戻る
points=[
models.PointStruct(id=1, vector=[0.05, 0.61, 0.76, 0.74], payload={"title": "就業規則", "dept": "人事"}),
models.PointStruct(id=2, vector=[0.19, 0.81, 0.75, 0.11], payload={"title": "経費精算の手順", "dept": "経理"}),
models.PointStruct(id=3, vector=[0.36, 0.55, 0.47, 0.94], payload={"title": "育児休業の申請", "dept": "人事"}),
],
)
# 絞り込みに使う項目にはペイロードインデックスを張っておく
client.create_payload_index(COL, field_name="dept", field_schema=models.PayloadSchemaType.KEYWORD)
hits = client.query_points(
collection_name=COL,
query=[0.2, 0.1, 0.9, 0.7],
query_filter=models.Filter(must=[models.FieldCondition(key="dept", match=models.MatchValue(value="人事"))]),
with_payload=True,
limit=3,
).points
for p in hits:
print(p.id, round(p.score, 3), p.payload["title"])
検索はquery_pointsで行います。古い記事にあるsearchメソッドやrecreate_collectionを使った例は、現行のクライアントでは公式Quickstartと同じquery_pointsとcollection_existsの組み合わせに読み替えてください。httpのURLにapi_keyを渡すと、クライアントは「Api key is used with an insecure connection.」という警告を出します。ローカルホスト内の検証なら問題ありませんが、別サーバーへつなぐ時点でTLSを用意する合図です。
curlでPUT・POSTを送りREST APIだけで同じ操作を確かめる例
PythonやSDKを入れずに疎通だけ見たいときは、REST APIを直接呼びます。コレクション作成とポイントのupsertはPUT、検索(Query points)はPOSTです。APIキーはapi-keyヘッダで渡します。
# コレクション作成(4次元・コサイン距離)
curl -X PUT http://localhost:6333/collections/docs_rest \
-H "api-key: ${QDRANT_API_KEY}" -H "Content-Type: application/json" \
-d '{"vectors": {"size": 4, "distance": "Cosine"}}'
# ポイントの登録(wait=true で反映を待つ)
curl -X PUT "http://localhost:6333/collections/docs_rest/points?wait=true" \
-H "api-key: ${QDRANT_API_KEY}" -H "Content-Type: application/json" \
-d '{"points": [{"id": 1, "vector": [0.05, 0.61, 0.76, 0.74], "payload": {"title": "就業規則"}}]}'
# 類似検索(上位3件とペイロードを返す)
curl -X POST http://localhost:6333/collections/docs_rest/points/query \
-H "api-key: ${QDRANT_API_KEY}" -H "Content-Type: application/json" \
-d '{"query": [0.2, 0.1, 0.9, 0.7], "limit": 3, "with_payload": true}'
Query pointsのlimitは省略すると10、with_payloadは省略するとfalseです。結果にタイトルが出ないときは、まずwith_payloadの付け忘れを疑います。
次元数とdistanceの指定ミスで起きるエラーと作り直しの判断
入門段階で最も多い失敗は、コレクションのsizeと埋め込みモデルの出力次元が合っていないことです。ベクトルの長さが違うとupsertは次元不一致のエラーで拒否されます。次元数と距離関数はコレクション作成時に固定されるため、モデルを変えたら新しいコレクションを作って入れ直すしかありません。
そこで本番では、コレクション名にdocs_v2のような版を付け、入れ直しが終わってから公式Collectionsページにあるエイリアスを切り替える運用にします。距離は、正規化済みの埋め込みならCosineかDotで結果の順位は同じになります。モデルの説明書に指定があればそれに従ってください。インデックスのmやef_constructの決め方はHNSWとは?M・ef_constructionの決め方で解説しています。
Qdrant Dockerを社内検証から本番へ進めるときの認証・バックアップ・監視
手元で動いたQdrantを社内の検証サーバーや本番に置くときは、認証・退避・監視の順に固めます。公式のInstallationページも、Docker Composeで本番運用する場合の条件として、性能の出る永続ストレージ、セキュリティ設定、バックアップと障害復旧の計画、監視との連携を挙げています。
APIキーと読み取り専用キーを分けて渡す設定とTLSが要る理由
公式のSecurityページによると、管理用のapi_keyと読み取り専用のread_only_api_keyは同時に設定できます。上のComposeで2つを分けたのはこのためで、検索だけを行うチャットアプリには読み取り専用キーを渡し、データ投入のバッチだけに管理用キーを持たせます。アプリの不具合でコレクションを消される事故を防ぐための分担です。
同じページは、TLSを使わないとAPIキーが平文で流れると警告しています。Qdrant自身のenable_tlsで証明書を持たせるか、前段のnginxやロードバランサで終端してください。v1.20.0からは、APIキーを設定した分散構成でノード間の内部gRPC(6335)でも認証が既定で有効になりました。単一ノードには内部APIが無いため影響しません。
スナップショットAPIでコレクションを退避・復元する手順と保存先
公式のSnapshotsページによると、コレクション単位のスナップショットは設定・ポイント・ペイロードを含み、Dockerイメージでは既定で/qdrant/snapshotsに保存されます。Composeでこのパスをボリュームにしたのは、コンテナを作り直しても退避ファイルを残すためです。
# スナップショットを作る(同期処理で .snapshot ファイルが生成される)
curl -X POST http://localhost:6333/collections/docs/snapshots -H "api-key: ${QDRANT_API_KEY}"
# 一覧で名前を確かめ、ホストへダウンロードする
curl http://localhost:6333/collections/docs/snapshots -H "api-key: ${QDRANT_API_KEY}"
curl -o docs.snapshot -H "api-key: ${QDRANT_API_KEY}" \
http://localhost:6333/collections/docs/snapshots/<スナップショット名>
復元はPUT /collections/{collection_name}/snapshots/recoverに、URLかfile:///形式の場所を渡します。注意点は版の制約です。公式は、取得元と同じminor版か次のminor版のクラスタにしか戻せないとしており、v1.18.1で取ったものはv1.18.1以降の1.18系か1.19系にしか入りません。版を2段以上飛ばして上げる計画なら、中間の版で取り直す手順を組み込みます。
Too many files openとmetricsの監視で詰まりを早めに見つける方法
コレクションやセグメントが増えると、ログにToo many files open (OS error 24)が出ることがあります。公式のSolving common errorsは、docker run --ulimit nofile=10000:10000で上限を上げる対処を示しており、上のComposeのulimitsは同じ設定です。
監視は6333の/metricsをPrometheusに取り込む形が基本です。Monitoringページによると、この値は接続したノードの分だけを返し、?per_collection=trueを付けるとコレクション別のAPI応答数も出ます。死活監視には/readyzを使い、APIキーを設定した後もこれらの状態確認用エンドポイントに監視サーバーから届くかを、本番前に確かめておきます。
Qdrant Docker単体運用とCloud・Kubernetes移行の判断基準
Docker単体で動くことと、業務で使い続けられることは別の話です。公式のInstallationページも、本番では原則としてKubernetesかQdrant Cloudを勧め、Dockerで運用する場合は冗長化やバックアップを自分で用意するよう求めています。
単一ノードのDocker運用で足りる業務条件と採用を見送るべき場面
単一ノードのDockerで足りるのは、次の条件がそろう場合です。検索が数時間止まっても業務が回る社内向けの用途であること、ベクトルが1台のメモリとディスクに収まる規模であること、日次のスナップショットから戻せば済む更新頻度であること。社内規程の検索や、PoC段階のRAGがこれに当たります。
反対に、顧客向けサービスの検索や、問い合わせ対応のチャットボットのように止まると売上や対応に直結する用途では、単一ノードのDocker運用は採用しません。分散構成を自前で組むと6335の保護やノードごとのスナップショット取得まで運用の負担が増えるため、その段階ではQdrant Cloudかマネージドの他製品と費用を比べます。マネージド版のクラスタ作成とDocker版からの移行手順はQdrant Cloudの使い方:クラスタ作成・APIキー・Python接続とDockerからの移行で扱っています。料金体系の比較はベクトルデータベースの価格とおすすめの記事で整理済みです。既にPostgreSQLを運用しているなら、別サーバーを増やさないpgvectorのDocker Compose構成も候補になります。
RAG基盤の構築で外部に任せる作業範囲と社内で持つ判断範囲の線引き
Qdrantを立てる作業そのものは、この記事のコマンドとComposeファイルで済みます。手間がかかるのはその先で、文書の分割単位、埋め込みモデルの選定と入れ替え時の再投入、権限に応じたペイロードでの絞り込み、検索精度の評価こそが実際の論点です。ハイブリッド検索とは?BM25とベクトル検索の統合のように、ベクトル検索だけでは拾えない語句への対策も設計に入ってきます。
社内に残すべきなのは、どの文書を誰に見せてよいかという権限の定義と、回答の正しさを判定する評価データです。サーバー構築・取り込みバッチ・精度改善の繰り返しは外部に任せても判断を失いません。社内文書を対象にした検索基盤をQdrantで組みたい場合は、RAG構築支援で要件の整理から相談できます。全体の進め方はRAG構築の手順とは?データ整備から本番運用までも参考になります。立てたQdrantをClaude CodeなどのAIエージェントの記憶ストアとしてつなぐ設定はQdrant MCPの使い方:mcp-server-qdrantをClaude Codeにつなぐ設定と記憶ストア化で解説しています。DifyのベクトルストアをQdrantにする手順はDify Qdrant切り替え手順:1.19.0の.env設定とvdb-migrateによる既存ナレッジ移行にまとめています。
よくある質問
Qdrant Dockerの構築と使い方について、つまずきやすい質問に答えます。
Dockerを使わずにQdrantを試す方法はありますか?
Pythonだけで試すことも可能です。qdrant-clientのREADMEによると、QdrantClient(":memory:")でメモリ上に、QdrantClient(path="path/to/db")でディスクに保存するローカルモードが使え、サーバー版と同じAPIを呼べます。開発やテスト、試作向けの機能なので、データ量が増えたり複数のプロセスから使ったりする段階で、Dockerのサーバーへ移すのが目安です。コードは接続先の指定を変えるだけで流用できます。
qdrant-clientとサーバーのバージョンはどこまで揃える必要がありますか?
majorが同じで、minorの差が1以内であれば互換とみなされます。qdrant-clientの版確認の実装がこの判定を行い、外れると接続時に警告を出します。たとえばサーバーがv1.20.0なら、クライアントは1.19系から1.21系までが範囲です。警告はcheck_compatibility=Falseで消せますが、消すのではなく版を合わせるのが筋です。
latestタグのままバージョンアップしても問題ありませんか?
おすすめしません。latestはdocker compose pullのたびに中身が変わり、気づかないうちにminor版を2つ以上飛ばすことがあります。スナップショットは同じminor版か次のminor版にしか戻せないため、上げた後で問題が出ても、古い版へは戻せません。タグをv1.20.0のように固定し、上げる前にスナップショットを取り、リリースノートで破壊的変更を確かめてから1段ずつ上げます。
PythonからはRESTとgRPCのどちらで接続すべきですか?
最初はRESTで十分です。qdrant-clientのREADMEは、QdrantClient(host="localhost", grpc_port=6334, prefer_grpc=True)とするとgRPCで接続でき、コレクションへの登録が一般に速くなると説明しています。大量のベクトルを投入するバッチだけgRPCにし、検索APIはRESTのままにする分け方も選択肢です。gRPCを使う場合は、Dockerの起動時に6334も公開しておく必要があります。
QdrantとpgvectorはDockerで動かすならどちらを選ぶべきですか?
既にPostgreSQLでアプリのデータを管理しているなら、pgvectorから始めるのが無難です。ベクトルと業務データを同じトランザクションで扱え、バックアップの仕組みも1つで済みます。ペイロードでの絞り込みを多用する検索や、ベクトル件数が増えて検索専用のサーバーに分けたい場合はQdrantを選びます。構築手順の違いはpgvectorとは?インストール手順と使い方と比べてみてください。
関連記事
- ベクトルDBとは?仕組み・インデックス構造・製品比較とpgvectorでの作り方【2026年版】:Qdrantを含むベクトルDBの仕組みと製品の違い
- pgvectorとは?インストール手順(Windows・Ubuntu・Docker Compose)と使い方【0.8.7対応】:PostgreSQLの拡張でベクトル検索を組む場合の手順
- Pythonでembeddingを生成する方法|OpenAI Embeddings APIとsentence-transformersの実装:Qdrantへ入れるベクトルの作り方
- HNSWとは?階層グラフの仕組みとM・ef_constructionの決め方を実装目線で解説【2026年版】:Qdrantが使うインデックスの調整方法
- RAG構築の手順とは?データ整備から精度向上・本番運用までの進め方:検索基盤を組んだ後のRAG全体の進め方