見出し画像

TimelinizeをDockerで導入

はじめに

個人の写真や位置情報、SNSの記録をひとつの時系列にまとめて閲覧できるオープンソース「Timelinize」を、MacBook ProでDocker運用するところまでを実体験ベースでまとめました。ChatGPT先生とやり取りしながらバイブコーディングしています。細かい技術的なことは一旦すみません…

また、これらは2025/10/11時点の内容です。バージョンアップによって変わっているかもしれませんのでご了承ください。

今回は「起動してUIが開き、ローカル写真の取り込みまで」の範囲です。クラウド連携は現状WIP(Work In Progress:作業中)のため、当面は各サービスの「エクスポート→ローカル取り込み」が基本運用になります。

導入のポイント

  1. 設定はDockerのNamed Volumeに保存(ホスト権限の影響を受けにくい)

  2. データはBind Mountでホストの任意フォルダと接続(/repo, /imports)

  3. コンテナ内のHOMEとXDG_CONFIG_HOMEを固定(HOME=/app, XDG_CONFIG_HOME=/app/.config)

  4. 必要に応じてコンテナの実行ユーザーをホストのUID/GIDに合わせる(--user "$(id -u):$(id -g)")

準備(初回のみ)

以下をターミナルにコピペします。ホーム直下に作業フォルダを作る構成です。

mkdir -p ~/Timelinize/{repo,imports}
docker volume create timelinize_config

コンテナ起動

自分のユーザー権限で動かし、コンテナ内HOMEを固定します。

export UID=$(id -u) GID=$(id -g)
docker run -d --name timelinize \
  --restart unless-stopped \
  --user "${UID}:${GID}" \
  -e HOME=/app \
  -e XDG_CONFIG_HOME=/app/.config \
  -p 12002:12002 \
  -v timelinize_config:/app/.config/timelinize \
  -v ~/Timelinize/repo:/repo \
  -v ~/Timelinize/imports:/imports:ro \
  ghcr.io/timelinize/timelinize

docker logs -f timelinize   # Listening... が出ればOK(Ctrl+Cで抜ける)

UIでタイムラインを新規作成

  1. ブラウザで http://localhost:12002 を開きます。

  2. 「Open or create timeline」→ Browse… → /repoと入力します。

  3. 「Create timeline here」をクリックしてから Continue を押します。

  4. メイン画面が出たら、右上の「+ Import」→ /imports を選ぶと、imports以下に配置したZIPやフォルダが認識されそこから取り込みできます。

画像
こんな感じです

今回実際に遭遇したエラーと解決策

同じ壁にぶつかったとき、下の対処を上から順に試せば解決できます。

1.permission denied: /app/.config/timelinize/config.json
原因:設定Volumeの所有権が合っていない、あるいはコンテナが非rootで書けない状態です。
対処:一度だけrootでVolume内の所有者を自分のUID/GIDに変更します。

docker run --rm -u 0:0 \
  -e TUID=$(id -u) -e TGID=$(id -g) \
  -v timelinize_config:/cfg \
  alpine sh -lc 'chown -R ${TUID}:${TGID} /cfg; ls -la /cfg'

加えて、HOMEとXDG_CONFIG_HOMEの固定を忘れないようにします(起動コマンド参照)。

2.mkdir /.config: permission denied
原因:コンテナ内のHOMEが未設定で、~/.config が /.config に評価されてしまう症状です。
対処:起動時に -e HOME=/app -e XDG_CONFIG_HOME=/app/.config を必ず付けます。

3.unexpected end of JSON input
原因:設定Volume内の config.json が空ファイルで壊れている状態です。
対処:config.json を最小の {} に差し替えます。

docker run --rm -u 0:0 -v timelinize_config:/cfg \
  alpine sh -lc 'printf "{}\n" > /cfg/config.json; ls -la /cfg'

4.unable to open database file: no such file or directory
原因:「Open」で既存DBを開こうとしているのに、timeline.db がまだ存在しないことによるものです。
対処:必ず「Create timeline here」をクリックし、新規作成フローで進めます。

5./repo で Permission denied
現象:docker exec で mkdir -p /repo が Permission denied。UIで作成しても失敗する。
原因:Bind Mount先(ホスト側フォルダ)が自分ユーザーで書き込み不可になっていました。
対処:ホスト側の所有者と権限を修復します。

# 推奨のホーム直下構成で運用する場合
mkdir -p ~/Timelinize/{repo,imports}
sudo chown -R "$USER":staff ~/Timelinize
chmod -R u+rwX ~/Timelinize

# すでに別パスで運用している場合(例:/Users/<ユーザー名>/Applications/Timelinize)
mkdir -p "/Users/<ユーザー名>/Applications/Timelinize/{repo,imports}"
sudo chown -R "$USER":staff "/Users/<ユーザー名>/Applications/Timelinize"
chmod -R u+rwX "/Users/<ユーザー名>/Applications/Timelinize/repo" \
               "/Users/<ユーザー名>/Applications/Timelinize/imports"
# 必要に応じてACLをクリア(ない環境では何も起きません)
chmod -RN "/Users/<ユーザー名>/Applications/Timelinize/repo" 2>/dev/null || true

確認はコンテナ内からの書き込みテストで行います。

docker exec -it timelinize sh -lc 'touch /repo/_write_test && echo WRITE_OK'

WRITE_OK が出れば権限は修復されています。なお、最終手段として一度だけrootで /repo を作り、すぐ所有権を戻す方法も有効です。

docker exec -it -u 0:0 timelinize sh -lc 'mkdir -p /repo'
docker exec -it -u 0:0 timelinize sh -lc "chown -R $(id -u):$(id -g) /repo"

取り込みとサムネイル生成の現状

取り込み後、Timelinizeは内部でサムネイルや検索用の埋め込みを自動生成します。大量データでは完了まで時間がかかり、UIでサムネイルが「ぐるぐる」に見えることがあります。結局、私の今の環境ではここを解決できていません。

所感

なかなか今回導入するのには何度もエラーが出て、ChatGPT先生とやりとりして起動するところまで来ました。しかし正直言えば現状はまだまだ実用的なものとは言えません。(まだ開発中とのことですし)

取り込めるデータもPCからのImportなのでたくさんのデータをいれるには作業的に辛いものがあります。冒頭に書いたようにクラウドサービスとの連携は今後とのことで、これが対応されると連携すれば取り込みや内容のアップデートも自動化するでしょうし、この対応でかなり実用性が見えてくるのではないでしょうか。非常に楽しみです!

いいなと思ったら応援しよう!

ピックアップされています

雑記・その他

  • 269本

コメント

コメントするには、 ログイン または 会員登録 をお願いします。
TimelinizeをDockerで導入|ハヤシタカサン
word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word

mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1