データベース

Apache Jena Fusekiとは?Jena 6の変更点とインストール・Docker運用を実装目線で解説

Apache Jena Fusekiとは?Jena 6の変更点とインストール・Docker運用を実装目線で解説

Apache Jena Fusekiとは、RDFデータをHTTP経由のSPARQLエンドポイントとして公開するサーバーです。Javaで書かれたRDF処理フレームワークであるApache Jenaの一部として配布され、ライセンスはApache License 2.0です。展開して1コマンド叩けば、ブラウザから使えるクエリ画面付きのトリプルストアが立ち上がります。

ただし2026年2月のJena 6.0.0で、配布と運用の前提が大きく変わりました。Java 21が必須になり、Tomcatに載せるWARファイル版は廃止され、TDB1は非推奨になっています。この記事は6.2.0(2026年7月31日リリース)を実際に起動して、導入からデータ投入、永続化、認証、サービス化までを検証した記録です。公式ドキュメントに残っている記述と現物が食い違う箇所も、実測したエラーメッセージ付きで示します。

まとめ:Apache Jena Fusekiの要点

  • FusekiはSPARQLサーバーです。1つのデータセットに対してSPARQL Query、SPARQL Update、Graph Store Protocol(読み書き)、RDF Patchの各エンドポイントをHTTPで提供します。SPARQL 1.1に対応し、6.1.0以降はRDF 1.2とSPARQL 1.2の書式にも追随しています。
  • 現行版は6.2.0(2026年7月31日リリース)です。Jena 6系はJava 21以上が必須で、Java 17では動きません。
  • Jena 6.0.0でWARファイル版(jena-fuseki-webapp/jena-fuseki-war)が廃止されました。最後にWARが作られたのは5.6.0です。公式ドキュメントのFuseki Serverのページには今もWAR運用の説明が残っているので、そこを読んで進めると入手先で行き詰まります。
  • TDB1はJena 6.0.0で非推奨になりました(削除はされていません)。新規構築は既定のTDB2を使います。
  • Docker Hubに公式イメージはありません。Apacheが配っているのはイメージを作るためのキットで、自分でビルドする前提です。
  • 既定のセキュリティ設定は「管理機能だけlocalhost限定、データの読み書きは誰でも可」です。外部に出す前に必ず変更してください。

Apache Jena Fusekiとは:Jenaプロジェクトの中でのSPARQLサーバー

Apache Jenaは、RDF(Resource Description Framework)で表現されたデータを読み書きし、SPARQLで問い合わせるためのJava製フレームワークです。Fusekiはその中で「HTTPの口を開ける」役割を担当します。Jena本体がライブラリとしてJavaアプリケーションに組み込まれるのに対し、Fusekiは独立したプロセスとして動き、言語を問わずHTTPクライアントから利用できるようにします。

コンポーネント 役割 配布形態
Fuseki SPARQLサーバー(HTTP公開) apache-jena-fuseki
ARQ SPARQLクエリエンジン apache-jena
TDB2 ネイティブRDFストア(永続化) apache-jena
RIOT RDFの入出力・書式変換 apache-jena
SHACL/ShEx RDFグラフの形状検証 apache-jena
GeoSPARQL 地理空間データの拡張 Maven(jena-geosparql)

クエリ言語そのものの書き方はSPARQLとは?RDFを検索するクエリ言語の書き方とSQLとの違いを実行例で解説【2026年版】で扱っています。データにどう意味を与えるかという上位の設計はオントロジーとは?RDFとOWLで意味を定義する実装手順【2026年版】を参照してください。

1データセットに立つ5系統のエンドポイント

Fusekiが何を公開しているかは、起動後に管理用エンドポイントへ問い合わせれば確認できます。以下は6.2.0を --update --mem /ds で起動した直後の応答を抜粋したものです。

$ curl -s 'http://localhost:3030/$/server'
{
  "version" : "6.2.0" ,
  "startDateTime" : "2026-09-07T22:45:56.475+00:00" ,
  "uptime" : 9 ,
  "datasets" : [
      {
        "ds.name" : "/ds" ,
        "ds.state" : true ,
        "ds.services" : [
            { "srv.type" : "gsp-r" ,  "srv.endpoints" : [ "get" ] } ,
            { "srv.type" : "query" ,  "srv.endpoints" : [ "sparql", "query", "" ] } ,
            { "srv.type" : "gsp-rw" , "srv.endpoints" : [ "data", "" ] } ,
            { "srv.type" : "update" , "srv.endpoints" : [ "", "update" ] } ,
            { "srv.type" : "patch" ,  "srv.endpoints" : [ "patch", "" ] }
          ]
      }
    ]
}

srv.endpoints に空文字列が含まれている点に注意してください。これはデータセットのURL自体(この例では /ds)でもその操作を受け付けるという意味です。つまり /ds/sparql でも /ds でも検索でき、Content-Typeによって更新かどうかが判別されます。

Jena 6で変わった点:Java 21必須、WAR廃止、TDB1非推奨

4系や5系の解説を読んで作業すると詰まる箇所があるので、先に版差を押さえます。以下はApache Jenaのリポジトリにある CHANGES.txt の記載に基づきます。

版 リリース日 主な変更
6.0.0 2026-02-04 Java 21必須、WAR廃止、TDB1非推奨
6.1.0 2026-05-11 RDF 1.2構文の入出力に対応
6.2.0 2026-07-31 Shiro利用時のメモリリーク修正

6.0.0の節にはMinimum Java version: Java 21、Retired - the Fuseki WAR file, jena-fuseki-webapp, jena-fuseki-war、Deprecation of TDB1 (but not removed)、Reloading data into TDB2 is recommended の4行が並んでいます。WARの廃止についてはApache Jenaのissue #3537に The last release producing the WAR file was Jena 5.6.0. と明記されており、Maven Centralでも jena-fuseki-war と jena-fuseki-webapp は5.6.0で更新が止まっています。同じ時期のリリースでも jena-fuseki-server は6.2.0まで出ているので、成果物ごとに追随状況が違う点は確認してから移行計画を立ててください。

ここで注意が要るのが、公式ドキュメントが追随していないことです。Fuseki Serverのページには現在も「Fuseki as a Web Application」という節があり、WARをダウンロードしてTomcatに配置する手順が書かれています。しかし6系のダウンロードページにWARはありません。5.6.0以前のWARはApacheのアーカイブから取得できますが、Java 21移行と同時に進めるなら、スタンドアロンサーバーへ切り替えるほうが素直です。

Java 21必須というのは推奨ではなく物理的な制約です。6.2.0の fuseki-server.jar に入っているクラスファイルはバージョン65(Java 21)でコンパイルされているため、Java 17で起動すると UnsupportedClassVersionError で読み込みに失敗します。既存サーバーのJavaを上げずに6系へ移ることはできません。

TDB2については、6.0.0でxsd:decimalの扱いに修正が入ったため、既存データベースの再ロードが推奨されています。小数値を格納しているデータセットを6系に載せ替えるときは、そのままディレクトリを持ち込まず、一度エクスポートしてから読み直してください。

インストールと起動:tar.gz展開から1コマンド起動まで

Fusekiの導入はアーカイブを展開するだけです。事前にJava 21以上を用意してください。

$ curl -LO https://dlcdn.apache.org/jena/binaries/apache-jena-fuseki-6.2.0.tar.gz
$ tar zxf apache-jena-fuseki-6.2.0.tar.gz
$ cd apache-jena-fuseki-6.2.0
$ ./fuseki-server --update --mem /ds

Windowsでは同梱の fuseki-server.bat を使います。起動すると次のようなログが出ます。

07:45:56 INFO  Fuseki          :: Apache Jena Fuseki 6.2.0
07:45:56 INFO  Config          :: Fuseki Base = /tmp/jenachk/work/run
07:45:56 INFO  Config          :: Database: /ds
07:45:57 INFO  Config          :: UI Base: fuseki-server.jar
07:45:57 INFO  Shiro           :: Shiro configuration: file:/tmp/jenachk/work/run/shiro.ini
07:45:58 INFO  Server          :: Path = /ds
07:45:58 INFO  Server          :: System
07:45:58 INFO  Server          ::   Memory: 4.0 GiB
07:45:58 INFO  Server          ::   PID:    61041
07:45:58 INFO  Server          ::   Port:   http=3030
07:45:58 INFO  Server          :: Start Fuseki

ブラウザで http://localhost:3030/ を開くと管理画面が出ます。「UI Base: fuseki-server.jar」とあるとおり、6系では画面のファイル一式もjarの中に入っており、外部ディレクトリを配置する必要はありません。

配布物の中身:12エントリだけの構成

6.2.0のtar.gzを展開して得られるのは、LICENSE・NOTICE・READMEを含めて12エントリだけです。4系のようにwebappディレクトリやshiro.iniが最初から置かれているわけではありません。

ファイル 用途
fuseki-server UI付きで起動する起動スクリプト
fuseki-plain UIなしで起動する起動スクリプト
fuseki-server.bat Windows用の起動スクリプト
fuseki-server.jar サーバー本体(UIを内包)
fuseki-backup バックアップを起動するシェルスクリプト
log4j2.properties ログ設定の既定値
service/service/fuseki.service systemdのユニットファイル
service/service/fuseki.initd init.d用の起動スクリプト

fuseki-serverとfuseki-plainの違い

2つの起動スクリプトは同じjarを呼び、環境変数 MAIN でエントリポイントを切り替えているだけです。UIと管理機能が要るかどうかで選びます。

MAINの値 UI 管理作業領域 想定用途
serverUI(既定) あり あり 開発・運用の通常構成
plain なし なし コンテナ・組み込み
main なし なし モジュールを使わない最小構成
basic なし なし 追加機能なしの検証

ここで1つ落とし穴があります。fuseki-plain の中身は exec fuseki-server という1行で、パスを付けずに呼び出しています。そのため配布ディレクトリがPATHに入っていない状態で絶対パス指定して実行すると、次のエラーで落ちます。

/tmp/jenachk/apache-jena-fuseki-6.2.0/fuseki-plain: line 21: exec: fuseki-server: not found

配布ディレクトリに移動してから ./fuseki-plain と叩くか、PATHへ追加してください。この挙動は6.2.0の配布物で確認したものです。

環境変数で押さえるべき4つ

変数 既定値 意味
FUSEKI_HOME スクリプトのあるディレクトリ 展開先
FUSEKI_BASE カレントディレクトリ配下のrun 作業領域
JVM_ARGS -Xmx4G JVMへ渡す引数
MAIN serverUI エントリポイント

公式ドキュメントは作業領域について「カレントディレクトリ」と書いていますが、6.2.0の fuseki-server スクリプトが実際に設定しているのはカレントディレクトリ直下の run です。この run の中に、設定ファイル、データベース、バックアップ、ログ、そして後述する shiro.ini が初回起動時に自動生成されます。コンテナで動かすときにどこを永続化ボリュームにするかは、この位置を基準に決めてください。

ヒープの既定値が4GBである点にも注意してください。-Xmx は上限なので起動時に4GBを確保するわけではありませんが、メモリ上限の小さいコンテナで動かすと、ヒープが伸びた時点でJVMが上限に達する前にコンテナごと停止させられます。コンテナのメモリ上限からヒープ外領域とOS分を差し引いた値を -Xmx に設定し、起動ログのMemory欄が意図した値になっているかを確認してください。

Docker運用:公式イメージの不在とビルドキット

「apache jena fuseki docker」で調べると出てくる手順の多くが古くなっています。まず事実確認から始めます。2026年9月8日時点で、Docker Hubに apache/jena-fuseki も apache/jena も存在しません(APIはいずれも object not found を返します)。Apacheが配布しているのはイメージそのものではなく、イメージを作るためのキット jena-fuseki-docker です。これはMaven Centralに置かれており、6.2.0も公開されています。

$ curl -LO https://repo1.maven.org/maven2/org/apache/jena/jena-fuseki-docker/6.2.0/jena-fuseki-docker-6.2.0.zip
$ unzip jena-fuseki-docker-6.2.0.zip
$ cd jena-fuseki-docker-6.2.0
$ docker compose build --build-arg JENA_VERSION=6.2.0
$ docker compose run --rm --service-ports fuseki --mem /ds

ビルド時にはMaven Centralからサーバーのバイナリを取得し、SHA1チェックサムと突き合わせます。バージョン番号は必ず引数で渡してください。キットのREADMEに載っている例は6.2.0版でも JENA_VERSION=5.3.0 のままなので、そのままコピーすると意図しない版が入ります。同梱のdocker-compose.yamlはカレントディレクトリの databases と logs をコンテナ内へマウントする設定なので、TDB2データベースをここに置けばコンテナを消してもデータは残ります。なおREADMEのコマンドは docker-compose 表記のままですが、Compose v2の docker compose でも同じように扱えます。

このイメージはFuseki Plainをベースにしているため管理画面は付きません。データセットの作成もデータ投入も、設定ファイルとHTTPだけで行うことになります。ブラウザから操作したい用途には向きません。

第三者イメージを使うときの確認点

自前ビルドを避けたい場合は有志のイメージを使うことになりますが、更新状況に大きな差があります。

イメージ 最新のJenaタグ リポジトリ最終更新
stain/jena-fuseki 5.1.0 2024-07-31
secoresearch/fuseki 6.2.0 2026-08-14

解説記事でよく名前が挙がるのは stain/jena-fuseki ですが、latestタグの実体は2024年7月で止まった5.1.0です。そのまま docker pull すると、Java 21必須化もWAR廃止も入っていない5.1.0が手元に来ます。検証目的なら問題ありませんが、6系向けの手順どおりに動かして挙動が違うと悩む原因になります。使う前にタグの更新日を必ず確認してください。

データセットの3つの作り方:メモリ、ディレクトリ、設定ファイル

コマンドラインからの起動は3通りあります。

$ ./fuseki-server --mem /ds                    # メモリ上、常に更新可、終了で消える
$ ./fuseki-server --loc=DB2 --update /ds        # ディレクトリ上のTDB2、更新可
$ ./fuseki-server --file=data.ttl /ds           # ファイルを読み込んで読み取り専用で公開

--loc は既定でTDB2のデータベースとして扱われます。TDB1にしたい場合だけ --tdb1 を付けますが、前述のとおり非推奨なので新規では選びません。

--locのディレクトリ事前作成という前提

ここは公式の説明と実際の挙動が食い違う箇所です。--help の説明文は Use an existing TDB database (or create if does not exist) となっており、無ければ作ってくれるように読めます。しかし6.2.0で存在しないディレクトリを指定すると、データベースを作らずに終了します。

$ ./fuseki-server --loc=DBnew --port 3031 --update /ds2
07:46:52 INFO  Fuseki          :: Apache Jena Fuseki 6.2.0
07:46:52 ERROR Fuseki          :: Directory does not exist: DBnew

空のディレクトリを先に作ってから指定すれば、その中にTDB2のデータベースファイルが生成されます。コンテナやsystemdから --loc を使うと、マウント前にディレクトリが用意されているかどうかで起動可否が変わるため、初回デプロイでつまずきやすい箇所です。

設定ファイルによるエンドポイント定義

エンドポイント名や読み取り専用の制御まで決めたいときは、Turtle形式の設定ファイルを --config で渡します。以下は6.2.0で起動を確認した最小構成です。

PREFIX fuseki: <http://jena.apache.org/fuseki#>
PREFIX rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX tdb2:   <http://jena.apache.org/2016/tdb#>
PREFIX :       <#>

:service rdf:type fuseki:Service ;
    fuseki:name "books" ;
    fuseki:endpoint [ fuseki:operation fuseki:query  ; fuseki:name "sparql" ] ;
    fuseki:endpoint [ fuseki:operation fuseki:update ; fuseki:name "update" ] ;
    fuseki:endpoint [ fuseki:operation fuseki:gsp_rw ; fuseki:name "data" ] ;
    fuseki:dataset :dataset ;
    .

:dataset rdf:type tdb2:DatasetTDB2 ;
    tdb2:location "/var/lib/fuseki/DB2" ;
    .
$ ./fuseki-server --config=config.ttl

読み取り専用で公開したいときは fuseki:update と fuseki:gsp_rw のエンドポイントを外し、fuseki:gsp_r だけを残します。fuseki:operation を使うこの記法が現行のもので、公式ドキュメントによれば古い fuseki:serviceQuery 形式も引き続きサポートされています。ただしjarに同梱されている雛形(config-tdb2など)は旧記法のままなので、雛形をコピーして書き足すと記法が混在します。新規に書くなら fuseki:endpoint で統一してください。

RDFデータの投入とSPARQLの実行

ここからは --update --mem /ds で起動したサーバーに対して、実際に叩いた結果を示します。投入する書籍データは次のTurtleファイルです。

@prefix ex: <http://example.org/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

ex:book1 rdf:type ex:Book ;
    ex:title "Effective Java" ;
    ex:author "Joshua Bloch" .

ex:book2 rdf:type ex:Book ;
    ex:title "Java Concurrency in Practice" ;
    ex:author "Brian Goetz" .

Graph Store Protocolによるデータ投入

デフォルトグラフへの投入は data エンドポイントにPOSTします。応答として取り込んだトリプル数が返るので、投入できたかどうかがその場で分かります。

$ curl -X POST -H 'Content-Type: text/turtle' --data-binary @books.ttl \
    'http://localhost:3030/ds/data?default'
{
  "count" : 6 ,
  "tripleCount" : 6 ,
  "quadCount" : 0
}

SPARQLでの検索

$ curl -H 'Accept: application/sparql-results+json' \
    --data-urlencode 'query=PREFIX ex: <http://example.org/> SELECT ?title ?author WHERE { ?b a ex:Book ; ex:title ?title ; ex:author ?author } ORDER BY ?title' \
    http://localhost:3030/ds/sparql
{ "head": {
    "vars": [ "title" , "author" ]
  } ,
  "results": {
    "bindings": [
      {
        "title": { "type": "literal" , "value": "Effective Java" } ,
        "author": { "type": "literal" , "value": "Joshua Bloch" }
      } ,
      {
        "title": { "type": "literal" , "value": "Java Concurrency in Practice" } ,
        "author": { "type": "literal" , "value": "Brian Goetz" }
      }
    ]
  }
}

Acceptヘッダを text/csv にすればCSVで返ります。件数だけ確認したいときはこちらのほうが扱いやすくなります。

SPARQL Updateでの書き換え

更新は update エンドポイントへ、Content-Typeを application/sparql-update にしてPOSTします。成功時のステータスは204で、本文は返りません。

$ curl -X POST -H 'Content-Type: application/sparql-update' \
    --data 'PREFIX ex: <http://example.org/> INSERT DATA { ex:book3 a ex:Book ; ex:title "Java Puzzlers" ; ex:author "Joshua Bloch" }' \
    http://localhost:3030/ds/update

--update の効き方はデータセットの種類で変わります。--mem のメモリ上データセットは常に更新可能で、--update を付けなくても更新は204で通ります。一方 --loc のTDB2データセットで --update を付けずに起動すると、更新もGraph Store Protocolの書き込みも405を返し、検索だけが通ります。読み取り専用で公開したつもりがメモリ上のデータセットだったという取り違えは起こり得るので、公開前に更新リクエストを1本投げて405が返ることを確かめてください。

大量データのtdb2.tdbloaderによる投入

まとまった量を投入するときは、HTTPではなくバルクローダーを使います。ローダーはFusekiではなく apache-jena 側のアーカイブに入っています。

$ mkdir -p DB2
$ apache-jena-6.2.0/bin/tdb2.tdbloader --loc DB2 books.ttl
07:47:37 INFO  loader          :: Loader = LoaderPhased
07:47:37 INFO  loader          :: Start: books.ttl
07:47:37 INFO  loader          :: Finished: books.ttl: 6 tuples in 0.09s (Avg: 69)
07:47:37 INFO  loader          :: Finish - index SPO
07:47:37 INFO  loader          :: Index set:  SPO => SPO->POS, SPO->OSP

ローダーは --loader で選べます。既定は上のログにも出ている phased で、性能とハードウェア要求のバランス型です。既存データベースへ安全に追加したいときは、単一トランザクションで走る basic を選びます。公式ドキュメントは「fully transactional なのは basic と sequential だけで、それ以外は速い代わりに低レベルのデータ構造を直接操作するため、途中で失敗するとデータベースが中途半端な状態になり得る」と明記しています。Wikidata級の巨大データには tdb2.xloader が用意されています。いずれのローダーもデータベースを排他ロックするので、Fusekiを起動したまま実行することはできません。大きなファイルは先に riot --validate で構文を確認しておくと、途中で失敗してインデックスが壊れる事故を避けられます。

アプリケーションからの呼び出し

Fusekiは普通のHTTPサーバーなので、Jenaのクライアントライブラリを使わずとも呼び出せます。「apache jena python」で探している場合、Pythonから使うのにSPARQL専用のドライバは要りません。ただしHTTPクライアントは別途入れます。以下は実際に上記のサーバーへ実行した例です。

$ python3 -m pip install requests
import requests

ENDPOINT = "http://localhost:3030/ds/sparql"
QUERY = """
PREFIX ex: <http://example.org/>
SELECT ?title ?author WHERE {
  ?b a ex:Book ; ex:title ?title ; ex:author ?author .
} ORDER BY ?title
"""

res = requests.post(
    ENDPOINT,
    data={"query": QUERY},
    headers={"Accept": "application/sparql-results+json"},
    timeout=10,
)
res.raise_for_status()
for row in res.json()["results"]["bindings"]:
    print(row["title"]["value"], "/", row["author"]["value"])
$ python3 query.py
Effective Java / Joshua Bloch
Java Concurrency in Practice / Brian Goetz

すでにrequestsを使っているアプリケーションなら、SPARQL専用ライブラリを足さずにJSON結果を取得できます。標準ライブラリだけに絞りたい場合は urllib.request でも同じことができ、結果の整形まで任せたい場合は SPARQLWrapper を使います。Javaから使う場合はJena本体のRDFConnectionを使うと、リモートのFusekiでもローカルのデータセットでも同じAPIで扱えます。

TDB2での永続化・バックアップ・ディスク消費

永続化にはTDB2を使います。--loc で指定したディレクトリの中に Data-0001 のような世代ディレクトリが作られ、その中にインデックスファイルが並びます。

HTTPから起動する無停止バックアップ

サーバーを止めずにバックアップを取れます。管理エンドポイントにPOSTするとタスクIDが返り、実際の処理は非同期で走ります。

$ curl -X POST 'http://localhost:3030/$/backup/ds'
{
  "taskId" : "1" ,
  "requestId" : 7
}

$ curl -s 'http://localhost:3030/$/tasks'
[ {
    "task" : "Backup" ,
    "taskId" : "1" ,
    "started" : "2026-09-08T07:46:23.418+09:00" ,
    "finished" : "2026-09-08T07:46:23.475+09:00" ,
    "success" : true
  }
]

$ ls run/backups/
ds_2026-09-08_07-46-23.nq.gz

出力はN-Quadsをgzip圧縮したもので、作業領域の backups ディレクトリに置かれます。POSTしただけでは完了を待たないため、バッチから呼ぶときは /$/tasks をポーリングして finished と success を確認してください。配布物の fuseki-backup スクリプトも、この2つのURLを叩いているだけです。

6トリプルで192MiBというディスク消費

TDB2はインデックスファイルをあらかじめまとまった単位で確保します。6トリプルしか入っていないデータベースでも、世代ディレクトリの実サイズは192MiBありました(8MiBのファイルが24個)。さらに tdb2.tdbcompact で圧縮すると新しい世代が作られますが、--deleteOld を付けない限り古い世代は残るため、実行直後は合計384MiBになります。

$ apache-jena-6.2.0/bin/tdb2.tdbcompact --loc DB2
Compacted in 2.162s

$ ls DB2
Data-0001
Data-0002
tdb.lock

ボリュームサイズを見積もるときは、この最低ラインと圧縮時の一時的な倍増を織り込んでください。小さなデータセットを多数作る設計にすると、データ量に対してディスクだけが増えていきます。

認証とアクセス制御:既定は管理機能だけlocalhost

ここが最も事故につながる箇所です。Fusekiを初めて起動すると、作業領域に shiro.ini が自動生成されます。6.2.0が生成する内容は次のとおりです。

[main]
ssl.enabled = false

plainMatcher=org.apache.shiro.authc.credential.SimpleCredentialsMatcher
localhostFilter=org.apache.jena.fuseki.authz.LocalhostFilter

[users]
user1=passwd1

[roles]

[urls]
## Control functions open to anyone
/$/server  = anon
/$/ping    = anon
/$/metrics = anon

## and the rest are restricted to localhost.
/$/** = localhostFilter

# Everything else
/**=anon

最後の1行が要点です。/$/ で始まる管理機能はlocalhostからしか叩けませんが、それ以外のすべて、つまりデータセットのクエリと更新のエンドポイントは誰でもアクセスできます。--update を付けて起動したサーバーをそのままインターネットに露出させると、第三者がSPARQL Updateでデータを消せる状態になります。ローカルホスト限定だから安全、という理解は管理機能についてのみ正しく、データについては当てはまりません。

方法1:shiro.iniによるBasic認証

生成されたファイルのコメントに手順が書かれています。[users] にまともなパスワードを設定し、[urls] の記述を書き換えます。

[users]
admin=(十分な長さのパスワード)

[urls]
/$/server = anon
/$/ping   = anon
/$/** = authcBasic,user[admin]
/** = authcBasic,user[admin]

平文で書きたくない場合はApache Shiroのハッシュに対応しており、argon2id形式の文字列を [users] に置いてPasswordMatcherを有効にする書き方が公式ドキュメントに載っています。

方法2:--passwdによるパスワードファイル指定

設定ファイルを書かずに済ませたいなら、起動オプションでパスワードファイルを指定するだけでもBasic認証がかかります。UIが不要な構成と組み合わせるとコンテナ向きです。

$ cat passwd.txt
admin: pw123

$ ./fuseki-plain --loc=DB2 --passwd=passwd.txt --port 3032 /ds3
$ curl -s -o /dev/null -w '%{http_code}\n' \
    --data-urlencode 'query=SELECT (COUNT(*) AS ?n) WHERE{?s ?p ?o}' \
    http://localhost:3032/ds3/sparql
401

$ curl -s -u admin:pw123 -H 'Accept: text/csv' \
    --data-urlencode 'query=SELECT (COUNT(*) AS ?n) WHERE{?s ?p ?o}' \
    http://localhost:3032/ds3/sparql
n
6

認証なしでは401、正しい資格情報を付けると結果が返ります。これに加えて、データセットやグラフの単位で読み書きを分けたい場合はData Access Controlという別の仕組みが用意されています。HTTPSは --https に証明書の場所とパスワードを書いたJSONファイルを渡して有効にします。HTTPS用ポートの既定値は3043です。逆に、外部に出す予定がないなら --localhost を付けてループバックだけで待ち受けるのが最も確実です。

systemdでのサービス常駐

Linuxで常駐させる場合、ユニットファイルを自分で書く必要はありません。配布物の service/service/fuseki.service をそのまま使えます。

[Unit]
Description=Fuseki

[Service]
Environment=FUSEKI_HOME=/opt/fuseki
Environment=FUSEKI_BASE=/etc/fuseki
Environment=JVM_ARGS=-Xmx4G
ExecStart=/opt/fuseki/fuseki-server
User=fuseki
Restart=on-abort
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

このファイルを /etc/systemd/system/ に置き、fusekiという名前のシステムユーザーを作って設定とデータベースへのアクセス権を与え、パスを環境に合わせてから有効化します。SuccessExitStatus=143 はJavaプロセスがSIGTERMで終了するときの終了コードが143になるためで、これを書かないと正常な停止が失敗として記録されます。ログは既定でjournalctlに出ます。

他のRDFストア・グラフDBとの使い分け

Fusekiを選ぶかどうかは、扱うデータモデルと運用形態で決まります。RDFとSPARQLの標準に沿って自前運用したいならFusekiが素直な選択です。

製品 データモデル クエリ言語 提供形態
Apache Jena Fuseki RDF SPARQL 自前運用(OSS)
Neo4j プロパティグラフ Cypher 自前運用/マネージド
Amazon Neptune RDF/プロパティグラフ SPARQL/Gremlin/openCypher マネージド

語彙を他組織と共有する、公開データを取り込む、W3C標準の形式で配布するといった要件があるならRDF側、アプリケーション内部の関係をノードとリレーションシップの属性として持ち、Cypher中心でたどる要件ならプロパティグラフ側が候補になります。性能は同じデータと代表クエリで測って判断してください。両者の構造的な違いはNeo4jとは?グラフデータベースの構造とCypher・エディション選定を実装視点で解説【2026年版】とAmazon Neptuneとは|3つのクエリ言語・Analyticsとの違い・料金モデルを実装目線で解説【2026年版】で扱っています。RAGの文脈でベクトル検索と併用する設計を検討している場合はベクトルデータベースとグラフデータベースの違い|比較表と使い分け・GraphRAGでの併用【2026年版】が参考になります。

よくある質問

Apache Jena Fusekiとは何をするソフトウェアですか?

RDFデータをHTTP経由のSPARQLエンドポイントとして公開するサーバーです。SPARQL Query、SPARQL Update、Graph Store Protocol、RDF Patchのエンドポイントを提供し、管理画面も内蔵しています。ライセンスはApache License 2.0です。

Fusekiの最新バージョンとJavaの要件は?

2026年9月時点の最新は6.2.0(2026年7月31日リリース)です。Jena 6系はJava 21以上を必須としており、Java 17以下では起動しません。

Docker公式イメージはありますか?

ありません。Apacheが配っているのはMaven Central上のビルドキット jena-fuseki-docker です。有志のイメージを使う場合、stain/jena-fuseki は2024年7月の5.1.0で止まっているので、6系が必要なら別のイメージを選ぶか自分でビルドしてください。

TDB1とTDB2はどちらを使うべきですか?

新規はTDB2です。--loc で指定した場所は既定でTDB2として扱われるため、意識しなければTDB2になります。既存のTDB2データベースを6系へ移す場合は、小数値の扱いに修正が入っているため再ロードが推奨されています。

WARファイルでTomcatに載せられますか?

6系ではできません。WARが作られた最後のリリースは5.6.0です。公式ドキュメントにはWAR運用の説明が残っていますが、6系のダウンロードページにWARは置かれていないため、スタンドアロンサーバーかコンテナへ移行してください。

そのままインターネットに公開して大丈夫ですか?

危険です。既定の shiro.ini は管理機能をlocalhostに限定する一方、データセットのエンドポイントは /**=anon で誰にでも開いています。--update 付きで公開すると第三者がデータを更新・削除できます。公開する前に shiro.ini でBasic認証をかけるか、--passwd でパスワードファイルを指定するか、--localhost で待ち受けを制限してください。

関連記事

お気に入りに入れた記事の一覧

資料請求

RELATED POSTS 関連記事

目次