はじめに
自前の画像ホスティングやプライベートクラウドストレージのソリューションを探すとき、MinIO がよく選ばれますが、個人開発者や中小規模のチームにとっては、Garage はより軽量で高性能、かつ設定が柔軟な代替案です。Rust で書かれており、リソース消費が非常に少なく、AWS S3 プロトコルと完全に互換性があります。
この記事では、1Panel パネル上で Docker Compose を使って、本番環境で使用可能な Garage オブジェクトストレージサービスをデプロイする方法を詳しく記録します。よくある設定の落とし穴(CORS クロスドメイン、WebUI 認証、ドメインバインドなど)を解決し、安全で使いやすいプライベート OSS を構築します。
0 準備
- サーバーOS: Debian 12 (推奨) / Ubuntu 22.04+
- 管理パネル: 1Panel (OpenResty/Nginx インストール済み)
- コアツール: Docker & Docker Compose
- 計画するドメイン:
s3.example.com—— S3 API エンドポイント (アップロード/管理ツール用)img.example.com—— 公開アクセス用ドメイン (ブログ/サイトで画像を参照する用)admin.example.com—— Web 管理画面 (WebUI)
1 設定ファイルの準備 (garage.toml)
- 1Panel でディレクトリを作成:
/opt/garage/config。 - ファイル
garage.tomlを作成し、以下を記入する:
metadata_dir = "/var/lib/garage/meta"
data_dir = "/var/lib/garage/data"
db_engine = "lmdb"
# シングルノード配置の場合は必ず 1 に設定;マルチノードの場合は必要に応じて調整
replication_factor = 1
# 32バイトのランダムキー (openssl rand -hex 32 で生成)
rpc_secret = "c9a4b8d7e6f5a1c2b3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6"
rpc_bind_addr = "[::]:3901"
rpc_public_addr = "127.0.0.1:3901"
[s3_api]
s3_region = "garage"
api_bind_addr = "[::]:3900"
root_domain = "s3.example.com" # あなたのAPIドメインを入力
[s3_web]
bind_addr = "[::]:3902"
root_domain = "img.example.com" # あなたの公開アクセスドメインを入力
index = "index.html"
[admin]
api_bind_addr = "[::]:3903"
metrics_token = "change_me_please" # metrics 取得用トークン
admin_token = "change_me_please" # 管理者トークン、WebUI が自動で読み取る
2 オーケストレーションファイルの作成 (docker-compose.yml)
重要なポイント:
- WebUI の設定マウント: WebUI コンテナは
garage.tomlをマウントしてadmin_tokenを自動読み取りする必要があります。 - パスワードのエスケープ: YAML では、Bcrypt パスワードハッシュ内の
$記号は$$と書く必要があります。
1Panel でオーケストレーション garage-stack を作成し、以下の内容を記入します:
services:
garage:
image: dxflrs/garage:v2.2.0 # 比較的新しいバージョン
container_name: garage
restart: always
network_mode: host # Host モード、ホストのポートを直接使用
volumes:
- /opt/garage/config/garage.toml:/etc/garage.toml
- /opt/garage/meta:/var/lib/garage/meta
- /opt/garage/data:/var/lib/garage/data
garage-webui:
image: khairul169/garage-webui:latest
container_name: garage-webui
restart: always
network_mode: host # WebUI も Host モードで通信を容易に
volumes:
# 設定ファイルをマウント必須、さもないと WebUI が自動認証できない
- /opt/garage/config/garage.toml:/etc/garage.toml:ro
environment:
API_BASE_URL: "http://127.0.0.1:3903"
S3_ENDPOINT_URL: "http://127.0.0.1:3900"
# ネイティブログイン設定: ユーザー名:Bcryptハッシュ ($$ エスケープに注意)
# 生成コマンド: python3 -c "import bcrypt; print(bcrypt.hashpw(b'あなたのパスワード', bcrypt.gensalt()).decode())"
# 以下のサンプルパスワードは 123456
AUTH_USER_PASS: 'admin:$$2b$$12$$zm7W20msXJc5fVgj.fjGR.GfGQS2M1abvQf5k.aWZTQBZGv4QexpC'
オーケストレーションを起動し、両方のコンテナが「実行中」と表示されることを確認します。
3 ノードレイアウトの初期化 (Layout)
起動直後の Garage は「役割未割り当て」状態なので、初期化が必要です。
ノードIDを確認:
1Panel ターミナルまたは SSH で以下を実行:
docker exec -it garage /garage status
表示された Node ID をコピーします (例: a8795c63e0c82b0b)。
- スペースの割り当てと設定の適用:
# 500GB の論理スペースを割り当て (すぐにディスクを占有しない)
docker exec -it garage /garage layout assign -z dc1 -c 500G <あなたのNodeID>
# 変更を適用
docker exec -it garage /garage layout apply --version 1
この時点で WebUI をリフレッシュすると、ステータスが緑色の Healthy に変わります。
4 ストレージバケットの作成と権限設定
画像ホスティングとして使用するために、バケットを作成し、公開アクセスを許可します。
1. バケットの作成
WebUI で Buckets -> Create Bucket をクリックし、名前を photo とします。
2. 公開ドメインのバインド (Alias) と Website モードの有効化
これにより、https://img.example.com/xxx.jpg で画像に直接アクセスできるようになります。
# 1. ドメインエイリアスをバインド (Garage にこのドメインが photo バケットに対応することを知らせる)
docker exec -it garage /garage bucket alias set photo img.example.com
# 2. Website モードを有効化 (匿名 GET リクエストを許可)
docker exec -it garage /garage bucket website --allow photo --index index.html
WebUI で直接 Alias を設定し、Website にチェックを入れることもできます。

WebUI インターフェース
3. API キーの作成
- WebUI で Keys -> Create Key をクリック (名前は
blog-keyなど)。 - ポップアップ表示された Access Key ID と Secret Access Key を すぐに保存。
- キーの右側にある Permissions をクリックし、
photoバケットの Read/Write 権限にチェックを入れる。- またはコマンドラインで権限付与:
docker exec -it garage /garage bucket allow --read --write --key blog-key photo
- またはコマンドラインで権限付与:
5 リバースプロキシと HTTPS の設定 (1Panel)
1Panel の「サイト」機能で、以下の3つのリバースプロキシを作成する必要があります:
| ドメイン | プロキシアドレス | 用途 |
|---|---|---|
s3.example.com | http://127.0.0.1:3900 | S3 API (PicList/Lsky はこちらを入力) |
admin.example.com | http://127.0.0.1:3903 | WebUI 管理画面 |
img.example.com | http://127.0.0.1:3902 | 公開画像アクセス (ポートは 3902 に注意) |
すべてのドメインで HTTPS 証明書を申請し、有効にしてください。
セキュリティヒント: Host モードを使用する場合、1Panel のファイアウォールまたはクラウドサービスのセキュリティグループで、Nginx の 80/443 ポートのみ許可することを推奨します。Garage の 3900-3903 ポートを直接外部に公開せず、すべてのリクエストが Nginx リバースプロキシを経由するようにするとより安全です。
6 CORS クロスドメイン問題の解決
ブログや他のサイトで画像を参照する場合、ブラウザがクロスドメインリクエストをブロックします。img.example.com の Nginx 設定で CORS を許可する必要があります。
1Panel サイト設定 -> 設定ファイル で、location / ブロックを見つけ、以下を追加します:
location / {
# CORS 設定
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, HEAD' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
# その他の設定
}
}
保存して Nginx をリロードします。
7 クライアント接続設定
これでサービスは完全に準備完了です。画像ホスティングツールに以下の設定を入力します:
- S3 Endpoint (エンドポイント):
https://s3.example.com - Bucket (バケット名):
photo - Access Key ID: (第4ステップで取得した ID)
- Secret Access Key: (第4ステップで取得した Secret)
- Region (リージョン):
garage(デフォルト) - Force Path Style (強制パススタイル): 有効 (True)
- Custom Domain (カスタムドメイン):
https://img.example.com