新しいカテゴリ「天書」を設けることにした。url-slug は「黄石公」
完全に AI が生成したチュートリアルを置くためのカテゴリだ
これがその最初の記事だ
Docker Hub が使えない環境で Mihomo プロキシをコンテナ化してデプロイする
想定環境
サーバーがほぼ外部ネットワークにアクセスできず、Docker Hub が使えない(またはどのイメージも pull できない)環境です。Podman、宝塔面板、直接インストールした Docker Engine のいずれでも動作します。
基本方針
- サーバーにすでにある任意の Alpine イメージ(例:
redis:alpine)をビルド時の CA 証明書の取得元として使い、最終イメージはscratchをベースに構築するため、追加のイメージ pull が発生しない。 - 追加するファイルはすべて
/root/mihomo/ディレクトリにまとめ、サーバーの他の場所を汚さない。 - プロキシを使うのは対象のコンテナだけ。ホストや他のコンテナには影響しない。
ステップ1: ファイルの準備
以下のファイルは個人 PC(GitHub にアクセスできる環境)でダウンロードしておき、サーバーの /root/mihomo/ ディレクトリに配置してください。
| ファイル | 役割 | 入手方法 |
|---|---|---|
mihomo(バイナリ) | プロキシ本体 | GitHub Releases から mihomo-linux-amd64-v*.gz をダウンロードし、解凍して mihomo にリネームする |
geoip.metadb | GeoIP ルールデータベース | meta-rules-dat Releases から geoip.metadb をダウンロードし、data/ サブディレクトリに配置する |
config.yaml | プロキシ設定 | 後述 |
Dockerfile | イメージ構築 | 後述 |
docker-compose.yml | コンテナ構成 | 後述 |
最終的なディレクトリ構成:
/root/mihomo/
├── mihomo # 二进制文件
├── config.yaml # 代理配置
├── Dockerfile
├── docker-compose.yml
└── data/
└── geoip.metadb # GeoIP 数据库
ステップ2: config.yaml
基本的な考え方: 購読 URL が返す完全な設定から、DNS と rules の部分を抜き出して config.yaml に直接入れます。プロキシノードは proxy-providers で購読 URL を参照させ、mihomo が毎日自動的に更新を取得するようにします。
一部の項目はサービスプロバイダによって異なるため、プロバイダから渡された購読 URL 内の対応する固定部分を記入します。ここは AI に任せてしまって構いません。
url:にはあなたの購読アドレスを入れます。URL 自体に認証情報(パス内のランダムなトークン)が含まれているため、追加の認証は不要です。
# 端口与模式
port: 7890
socks-port: 7891
allow-lan: true
mode: Rule
log-level: info
external-controller: 0.0.0.0:9090
# DNS(从订阅返回内容中提取)
dns:
enable: true
# ... 完整内容从订阅 URL 拉取后填入
# 每日自动从订阅地址拉取最新节点
proxy-providers:
sub:
type: http
url: "https://你的订阅地址?clash=3"
interval: 86400
path: ./providers/sub.yaml
health-check:
enable: true
url: https://cp.cloudflare.com
interval: 300
# 自动选择最快节点
proxy-groups:
- name: 🔰 选择节点
type: url-test
use: [sub]
url: https://www.gstatic.com/generate_204
interval: 300
# 规则(从订阅返回内容中提取)
rules:
- GEOIP,CN,DIRECT
- MATCH,🔰 选择节点
ステップ3: Dockerfile
FROM redis:alpine AS certs
FROM scratch
COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY mihomo /mihomo
ENTRYPOINT ["/mihomo"]
CMD ["-d", "/etc/mihomo"]
- 1 段階目の
FROM redis:alpine: サーバーにすでにあるイメージを使い、CA ルート証明書だけを取り出します。 - 2 段階目の
FROM scratch: 空のイメージです。最終成果物は mihomo バイナリと CA 証明書だけなので、クリーンで無駄がありません。 redis:alpineはビルドの材料として参照しているだけで、実行も変更もされません。サーバー上にある任意の Alpine 系イメージに置き換えても構いません。
ステップ4: docker-compose.yml
services:
mihomo:
build: .
container_name: mihomo
restart: unless-stopped
volumes:
- ./config.yaml:/etc/mihomo/config.yaml:ro
- ./data:/etc/mihomo
ports:
- "7890:7890"
- "9090:9090"
build: .はローカルの Dockerfile を使ってビルドするので、外部イメージを pull する必要がありません。9090ポートは REST API 用です(任意。ホットリロードや状態確認に使用します)。
ステップ5: ビルドと起動
cd /root/mihomo
# 确保二进制文件存在且可执行
chmod +x mihomo
# 构建并启动
docker compose build
docker compose up -d
プロキシが動作するか確認します:
curl -x http://localhost:7890 https://www.google.com -o /dev/null -w "%{http_code}"
200 が返れば成功です。
ステップ6: 他のコンテナにプロキシを経由させる
ブログのバックエンドコンテナを例に、その docker-compose.yml に環境変数を追加します:
environment:
HTTP_PROXY: "http://172.17.0.1:7890"
HTTPS_PROXY: "http://172.17.0.1:7890"
NO_PROXY: "localhost,127.0.0.1"
172.17.0.1 は Docker のデフォルトの bridge ゲートウェイです。コンテナはここを経由して、ホスト上の mihomo がマッピングしている 7890 ポートにアクセスします。バックエンドがカスタムネットワークを使っている場合は、docker inspect <容器名> | grep Gateway で実際のゲートウェイアドレスを確認してください。
対象コンテナを作り直したら、コンテナ内に入って確認します:
docker exec <容器名> curl -x http://172.17.0.1:7890 https://www.google.com -o /dev/null -w "%{http_code}"
200 が返れば完了です。
mx-space の OAuth について
mx-space は better-auth パッケージを使って OAuth 認証を行いますが、このパッケージは既定ではコンテナのプロキシを通りません。そのため、JS を注入する追加対応が必要です。
問題
HTTP_PROXY 環境変数を設定すれば、curl のような従来型ツールはプロキシを通ります。しかし better-auth や Google OAuth など、Node.js 標準の fetch() を使うパッケージは、依然として直接接続してしまいます。fetch() の内部では undici が使われており、HTTP_PROXY 環境変数を読み込まないためです。
解決策
手順は次の3つです。注入スクリプト → 依存関係の宣言 → デプロイ。
1. proxy-patch.mjs を作成する
import { ProxyAgent, setGlobalDispatcher } from 'undici';
const proxy = process.env.HTTP_PROXY || process.env.HTTPS_PROXY;
if (proxy) {
setGlobalDispatcher(new ProxyAgent(proxy));
}
2. コンテナの docker-compose.yml に追記する
environment:
NODE_OPTIONS: "--import /app/proxy-patch.mjs"
# HTTP_PROXY 和 HTTPS_PROXY 已有
volumes:
- ./proxy-patch.mjs:/app/proxy-patch.mjs:ro
- ./undici:/app/node_modules/undici:ro # 如果镜像内未预装 undici
3. イメージ内に undici が入っていない場合
個人 PC で undici の npm パッケージをダウンロードし、コンテナのプロジェクトディレクトリに置きます:
# 在 PC 上(需要 npm)
npm pack undici --pack-destination .
tar -xzf undici-*.tgz
mv package undici
undici/ ディレクトリをコンテナのプロジェクトと一緒にサーバーへアップロードすれば OK です。
最終的な構成は次のようになります。
mx-core/
├── docker-compose.yml
├── proxy-patch.mjs
├── undici/ # undici 8.9.0 完整包
└── data/
検証
コンテナに入って、次のコマンドを実行します:
node -e "fetch('https://www.google.com').then(r => console.log(r.status))"
200 が返れば、プロキシが有効になっています。