.NET の開発現場で「ネットワークにつながらない/つなげたくない」状況は珍しくありません。ビルドサーバーが閉域網だったり、複数ユーザーの端末に同じ NuGet パッケージを繰り返しダウンロードしたくなかったり。この記事では、NuGet パッケージを一度だけ取得し、複数プロジェクト/複数ユーザーでオフライン再利用するための手順と運用の要点を、Visual Studio と CLI 両方の視点で徹底解説します。
この記事で解決すること
- オンライン接続なしで NuGet パッケージをインストールできる環境を作る
- 依存パッケージの不足やバージョン不整合で失敗しないための具体的なコツ
- ユーザーごとのキャッシュに依存せず、PC 内/組織内で共有できる構成
- Visual Studio の「Microsoft Visual Studio Offline Packages」を正しく活用する方法
- CI/閉域網での復元、セキュリティ検証、アップデート運用の型
先に要点(最短ルート)
- 必要パッケージを一括取得:オンライン環境で必要なパッケージとすべての依存関係を空のフォルダーへまとめてダウンロード(.nupkg をそのまま保管)。
- ローカル ソース登録:Visual Studio の「パッケージ ソース」に上記フォルダーを追加し、nuget.org を一時的に無効化してローカル限定で解決。
- プロジェクトにインストール:対象プロジェクトでローカル ソースを選択してインストール。足りない依存があれば .nupkg を追加。
- 共有オフライン化:収集した .nupkg を
%ProgramFiles(x86)%\Microsoft SDKs\NuGetPackages(既定のオフライン パッケージ フォルダー)や共有ドライブに配置。 - 全ユーザー有効化:Visual Studio の「Microsoft Visual Studio Offline Packages」にチェック。以降はオフラインで再利用可能。
前提知識:NuGet の保存場所と役割
NuGet の「保存場所」を理解すると、どこに何を置けば再利用できるかが明確になります。
| 場所 | 例 | 中身 | 用途/ポイント |
|---|---|---|---|
| パッケージ ソース(フィード) | フォルダー:C:\Packages\OfflineFeed既定のオフライン: %ProgramFiles(x86)%\Microsoft SDKs\NuGetPackages | .nupkg(パッケージ本体) | インストール元として参照される。.nupkg を置くだけでよい(展開は不要)。 |
| グローバル パッケージ フォルダー | %userprofile%\.nuget\packages(ユーザーごと)または環境変数 NUGET_PACKAGES で共有場所へ変更 | 展開済みフォルダー+ .nupkg/.sha512 | 復元結果のキャッシュ。ユーザー別が既定。共有向きにしたい場合は場所を変更する。 |
| プロジェクト ローカル(packages.config 系) | ソリューション直下の packages フォルダー 等 | 展開済みフォルダー | 旧来の管理方式で使用。PackageReference 主流の現在は登場頻度は減少。 |
今回のゴールは、パッケージ ソース(フォルダー)を自前で用意し、そこへ一度だけ .nupkg を集めておく方式です。Visual Studio ではこのフォルダーを「オフライン ソース」として登録・有効化するだけで、ネットワークなしで復元が通ります。
手順:.nupkg を依存関係ごと一括取得する
方法 A:プロジェクト/ソリューションから必要物を丸ごと収集(推奨)
実際に使うプロジェクト(PackageReference)から復元を一度だけオンラインで実行し、収集専用のキャッシュ フォルダーへダウンロードします。
- 収集先を作成(例):
C:\Packages\Staging - 一度だけオンラインで復元(PowerShell/コマンド プロンプト):
set NUGET_PACKAGES=C:\Packages\Staging dotnet restore .\YourSolution.sln※ 上記により、必要な直・間接依存すべての .nupkg と .sha512 がC:\Packages\Staging配下に集まります。 - 集めた .nupkg だけを平置きにコピー(フォルダーをまたいで 1 か所へ集約):
# PowerShell 例:.nupkg を 1 フォルダーへ集約 $src = "C:\Packages\Staging" $dst = "C:\Packages\OfflineFeed" New-Item -ItemType Directory -Force -Path $dst | Out-Null Get-ChildItem $src -Recurse -Filter *.nupkg | Copy-Item -Destination $dst -Force
方法 B:個別のパッケージを指定してダウンロード
製品チームで使う社内標準パッケージ群が決まっている場合は、nuget.exe の install を使って依存込みで取得し、.nupkg を取り出します。
# 例:Newtonsoft.Json 13.0.3 を依存関係込みで取得
nuget install Newtonsoft.Json -Version 13.0.3 -OutputDirectory C:\Packages\Staging -DependencyVersion Highest
# 収集した .nupkg を OfflineFeed へ集約
Get-ChildItem C:\Packages\Staging -Recurse -Filter *.nupkg | Copy-Item -Destination C:\Packages\OfflineFeed -Force
複数の ID/バージョンを扱う場合は、上記をスクリプト化して繰り返します。
ポイント
- ファイル名は変更しない(
PackageId.Version.nupkgをそのまま)。 - 対象の .NET(TFM)と SDK バージョンに対して互換のある組み合わせかを事前に確認。
- パッケージのバージョン固定(後述の
packages.lock.json)を併用すると、オフラインでも復元の再現性が高まります。
Visual Studio にローカル パッケージ ソースを登録する
- Visual Studio → [オプション]>[NuGet パッケージ マネージャー]>[パッケージ ソース] を開く。
- 「+」を押して「名前(例:OfflineFeed)」と「ソース(例:
C:\Packages\OfflineFeed)」を入力して追加。 - 一時的にオンライン ソース(nuget.org)のチェックを外して、検索・解決をローカル限定にする。
これで UI からローカル フォルダー内のパッケージが検索・インストール可能になります。依存が足りない場合は、該当 .nupkg を OfflineFeed に追加すれば解決します。
プロジェクトへのインストール(オフライン)
- 対象プロジェクトを開き、[プロジェクト]>[NuGet パッケージの管理] を開く。
- 右上のソース ドロップダウンで新規ローカル ソース(OfflineFeed)を選択。
- 必要なパッケージを選んでインストール。依存不足のエラーになったら、OfflineFeed に不足 .nupkg を追加したうえで再試行。
CLI 派は、復元時に --source でローカル ソースのみを指定できます。
dotnet restore .\YourSolution.sln --source C:\Packages\OfflineFeed --disable-parallel
全ユーザーで再利用:既定のオフライン ソースを使う
Visual Studio は既定で 「Microsoft Visual Studio Offline Packages」 をパッケージ ソースとして持っています。場所は次の通りです。
%ProgramFiles(x86)%\Microsoft SDKs\NuGetPackages
ここへ .nupkg を配置すると、その PC のすべてのユーザーから参照可能になります。管理者権限で以下を実行します。
# 収集済み .nupkg を OS 既定のオフライン フォルダーへ配置(要管理者)
Copy-Item C:\Packages\OfflineFeed\*.nupkg `
"$env:ProgramFiles(x86)\Microsoft SDKs\NuGetPackages" -Force
その後、Visual Studio の「パッケージ ソース」で Microsoft Visual Studio Offline Packages にチェックを入れて有効化します。以降、オフラインでも同じパッケージ群をユーザー横断で再利用できます。
注意:このフォルダーは.nupkg ファイルを前提とする「フォルダー フィード」です。展開済みフォルダーを丸ごと置く必要はありません(置いても参照されません)。
ユーザー固有キャッシュを共有に寄せる(任意)
ユーザー プロファイル削除の影響を避けたい場合や、ビルド速度を安定させたい場合は、グローバル パッケージ フォルダーを共有ドライブに変更します。
| 方法 | 具体例 | メリット | 注意点 |
|---|---|---|---|
| 環境変数で変更 | setx NUGET_PACKAGES D:\NuGetCache | ツール全体に効く。手軽。 | パスは短く・高速なディスク推奨(Dev Drive など)。 |
| nuget.config で変更 | <configuration> <config> <add key="globalPackagesFolder" value="D:\NuGetCache" /> </config> </configuration> | リポジトリ単位で完結。CI にも安全。 | 既存キャッシュを移行する場合は手動コピーが必要。 |
推奨の nuget.config サンプル(ローカル限定で確実に復元)
<configuration>
<packageSources>
<clear />
<add key="Offline" value="C:\Packages\OfflineFeed" />
<add key="VSOffline" value="%ProgramFiles(x86)%\Microsoft SDKs\NuGetPackages" />
</packageSources>
<clear /> でオンライン ソースを外し、ローカルだけを解決元にします。packageSourceMapping はパッケージを特定ソースに固定し、思わぬソースへ取りに行くのを防止します。
CI/ビルド サーバー(閉域網)での運用
- ビルド エージェントへ OfflineFeed を配布(アーティファクト管理でも可)。
- リポジトリに置いた
nuget.configにより、オンライン ソースを無効化。 packages.lock.jsonをコミットしてバージョン固定(下記参照)。
# ロック モードで復元(ロックが変わる場合は失敗)
dotnet restore --locked-mode --source C:\Packages\OfflineFeed
この構成なら、閉域網でも再現性の高いビルドが得られます。
依存関係・バージョン管理を堅牢にする(packages.lock.json)
PackageReference を使用している場合、ロック ファイルを導入するとオンライン確認なしで同じ依存グラフを再現できます。
- オンラインで一度だけロック ファイルを生成:
dotnet restore --use-lock-file - 生成された
packages.lock.jsonをコミット。 - 以降はオフラインでも
--locked-modeで同一バージョンを強制できます。
セキュリティと監査(署名検証・信頼済み発行者)
オフライン環境だからこそ、取り込む段階で検証しておくことが重要です。
- 署名検証:収集した .nupkg を取り込む前に検証(署名付きパッケージの場合)。
# 例:署名検証(nuget.exe) nuget verify C:\Packages\OfflineFeed\*.nupkg -All - 信頼済み発行者の設定:
nuget.configのtrustedSignersを使い、許可された発行者の署名のみ通す。 - 配布権限:OfflineFeed へコピーできるのは管理者/ビルド担当に限定(書き込み権限を制御)。
よくあるつまずきと対策(実践メモ)
| 症状 | 原因 | 対策 |
|---|---|---|
| 「依存パッケージが見つかりません」 | OfflineFeed に依存 .nupkg がない | オンラインで再度収集し、足りない .nupkg を追加。 最短は「方法 A」でプロジェクトから丸ごと収集。 |
| nuget.org に取りに行ってしまう | オンライン ソースが有効のまま | nuget.config の <clear />、または VS のパッケージ ソースでオフラインのみを有効化。 |
| ユーザーを変えると復元が遅い | ユーザーごとのグローバル キャッシュを毎回構築 | NUGET_PACKAGES または globalPackagesFolder を共有ディスクに設定。 |
| 同じパッケージを何度も収集してしまう | 収集場所の重複管理 | 収集用(Staging)と配布用(OfflineFeed)を分離し、 配布用は重複を上書き( -Force)で一本化。 |
| TFM 違いでビルド不可 | 対象フレームワークの違いを見落とし | 必ず実プロジェクト/ソリューションで復元して収集(方法 A)。 |
| パッケージ更新が追えない | オフラインのみで運用し続ける | 更新時だけオンラインで収集し直す運用にする。packages.lock.json の更新差分でレビュー。 |
運用の型:更新サイクルと後片付け
更新サイクル(おすすめ)
- 月次または四半期で「収集用ブランチ」を切る。
- オンラインで
dotnet restore --use-lock-file→ OfflineFeed を 別フォルダーに仮更新。 - 検証環境でビルド+テスト。
- 問題なければ本番 OfflineFeed に昇格(差し替え)。
後片付け
- 収集に使った一時フォルダー(Staging)は配布へコピー後に削除して OK。
- 不要になったローカル ソースは VS の「パッケージ ソース」から削除。
- キャッシュが肥大化したら:
# キャッシュ確認とクリア nuget locals global-packages -list nuget locals global-packages -clear nuget locals http-cache -clear
サンプル:組織内共有ドライブでのオフライン フィード
全開発者が参照する社内共有を用意し、そこを 唯一のソースとしてマッピングします。
# 1) 共有ドライブ(読み取り専用)例
\\fileserver\NuGet\OfflineFeed
# 2) 開発者側 nuget.config(リポジトリ直下)
# 3) CI 側:同じ構成でロック モード復元
dotnet restore --locked-mode
この方式なら、インターネットに出られない端末でも、全員が同じセットのパッケージを安定して利用できます。
トラブルシューティング:最短チェックリスト
- VS の「パッケージ ソース」:オフライン ソースのみ有効か?
- OfflineFeed に 対象バージョンの .nupkg は揃っているか?
packages.lock.jsonを使っているなら –locked-mode で復元しているか?- グローバル パッケージ フォルダーが破損していないか?
nuget localsでクリアして再試行。 - CPU アーキテクチャ違い/TFM 違いはないか?(x86/x64、net6.0/net8.0 など)
まとめ
- オフライン利用の肝は、.nupkg を 1 箇所に集めた「フォルダー フィード」を作ること。
- Visual Studio 既定の Microsoft Visual Studio Offline Packages を活用すれば、PC 内ユーザー横断で再利用可能。
- プロジェクトから丸ごと収集(方法 A)+
packages.lock.jsonで、依存関係と再現性の悩みを解消。 - 共有ドライブ/Dev Drive へキャッシュを集約すると、ビルド速度とディスク効率が向上。
- 更新は「収集 → 検証 → 昇格」の定常運用で、セキュアかつ安定したオフライン開発基盤を維持できる。
クイックリファレンス
| やりたいこと | コマンド/操作 |
|---|---|
| プロジェクト依存をまとめて収集 | set NUGET_PACKAGES=C:\Packages\Staging dotnet restore .\YourSolution.sln |
| .nupkg を 1 か所に集約 | Get-ChildItem C:\Packages\Staging -Recurse -Filter *.nupkg ` | Copy-Item -Destination C:\Packages\OfflineFeed -Force |
| 既定のオフライン ソースへ配置 | Copy-Item C:\Packages\OfflineFeed\*.nupkg ` "$env:ProgramFiles(x86)\Microsoft SDKs\NuGetPackages" -Force |
| ローカル ソースのみで復元 | dotnet restore --source C:\Packages\OfflineFeed --locked-mode |
| キャッシュ掃除 | nuget locals global-packages -clear nuget locals http-cache -clear |

コメント