1Panel + Docker で高性能オブジェクトストレージ Garage (S3 互換) をデプロイ
はじめに
自作の画像ホスティングやプライベートクラウドストレージソリューションを探す際、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—— 公開アクセス用ドメイン (ブログ/Webサイトでの画像引用用)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コンテナは、
admin_tokenを自動的に読み取るためにgarage.tomlをマウントする必要があります。 - パスワードのエスケープ: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.バケット (Bucket) の作成
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. Webサイトモードを有効化 (匿名 GET リクエストを許可)
docker exec -it garage /garage bucket website --allow photo --index index.html
WebUI で直接 Alias を設定し、Website の有効化にチェックを入れることも可能です。

webui 界面
3. API キー (Key) の作成
- WebUI で Keys -> Create Key をクリックします (名前は
blog-keyなど)。 - ポップアップ表示される Access Key ID と Secret Access Key を すぐに保存 してください。
- Key の右側にある Permissions をクリックし、
photoバケットの Read/Write 権限にチェックを入れます。- またはコマンドラインで権限付与:
docker exec -it garage /garage bucket allow --read --write --key blog-key photo
- またはコマンドラインで権限付与:
5リバースプロキシと HTTPS 設定 (1Panel)
1Panel の「Webサイト」機能で、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クロスドメイン問題の解決
ブログや他のWebサイトで画像を引用する場合、ブラウザはクロスドメインリクエストをブロックします。img.example.com の Nginx 設定で CORS を強制的に許可する必要があります。
1Panel のWebサイト設定 -> 設定ファイル で、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: (第四ステップで取得した ID)
- Secret Access Key: (第四ステップで取得した Secret)
- Region (リージョン):
garage(デフォルト) - Force Path Style (パススタイル強制): 有効 (True)
- Custom Domain (カスタムドメイン):
https://img.example.com