閉域網・オフライン環境へのAI/データサイエンス環境配布という悪夢
こんにちは、テックリードの皆さん。
セキュアな閉域網(エアギャップ環境)、工場やプラントのEdgeデバイス、あるいはインターネット接続が制限されたオンプレミスサーバーへのAI・データサイエンス環境のデプロイで、頭を抱えた経験はないでしょうか。
「`pip install` や `conda install` を走らせたら、社内プロキシやファイアウォールで弾かれた」
「`requirements.txt` や `environment.yml` を持っていったのに、ターゲットマシンのOSやlibcのバージョン差異、そして何よりPyPIやAnacondaリポジトリ側の裏で動くC言語・Fortranの依存関係解決地獄(SATソルバーの衝突)により、ビルドが永遠に終わらない、あるいはセグメンテーション違反で爆死する」
こうした現場の絶望を、一撃で、美しく解決するのが `conda-pack` です。
本記事では、単なるコマンドの羅列ではなく、「なぜConda-Packが優れているのか」「内部でどのようなバイナリ置換(Shebang書換え)が行われているのか」というアーキテクチャの理解から踏み込み、Jupyter Labを絡めたオフラインポータブル環境の構築、そしてチーム開発を加速させる実践的なベストプラクティスまでを完全解説します。
—
なぜ `environment.yml` では不十分なのか?
一般的なPython開発では、以下のような `environment.yml` を共有するのが定石です。
name: ds-project
channels:
- conda-forge
dependencies:
- python=3.10
- numpy=1.24.3
- pandas=2.0.2
- scikit-learn=1.2.2
- jupyterlab=3.6.3
このアプローチには、「ターゲット環境でもインターネット接続とCondaの依存解決エンジンが正常に稼働すること」という暗黙の前提があります。
しかし、完全オフライン環境(インターネット遮断)では、この前提が完全に崩壊します。Condaはパッケージをインストールする際、リモートのメタデータを取得して依存関係のグラフを解決しようとします。ローカルキャッシュ(`pkgs` ディレクトリ)を持ち込む手もありますが、OSアーキテクチャ(Linux x86_64, ARM64, macOSなど)やCランタイム(glibcのバージョン)がわずかに異なるだけで、解決不能なコンフリクトを引き起こします。
Conda-Packの思想:動く状態の「スナップショット」を丸ごと凍結する
これに対し、`conda-pack` は「すでに正常に動作しているConda仮想環境のディレクトリツリーそのものをtar.gzやzipとして固め(アーカイブ化)、別のマシンで展開すれば、即座にそのまま動く状態にする」という極めてアグレッシブかつ合理的なアプローチを取ります。
[開発マシン (ネット接続あり)]
Conda環境構築 -> 動作確認 -> conda-packで固める (.tar.gz)
│
▼ (USBメモリ / 内部共有ストレージ等で物理・論理移行)
[本番・閉域網マシン (完全オフライン)]
アーカイブを展開 -> 即座にPython / Jupyter Labが稼働
依存関係の解決(計算コストの高いSAT問題の処理)は、すべてネット接続された開発マシン側で完了させているため、ターゲットマシン側ではコンパイルもネット通信も一切不要です。
—
実践:Conda-Packによる環境のパッケージングとデプロイ
ここからは、実際に手を動かすための手順を、トラブルシューティングの知見を交えて解説します。
ステップ1: 開発環境の構築と `conda-pack` のインストール
まずは開発用マシンにて、ターゲット環境と同一のOS・アーキテクチャ(※ここが重要です。Linuxで動かすならLinux上で打包する必要があります)を用意し、環境を構築します。
conda-pack自体のインストール(conda-forgeからの取得を推奨)
conda install -c conda-forge conda-pack
専用の仮想環境を作成
conda create -n ai-offline-env python=3.10 numpy pandas scikit-learn jupyterlab -y
環境を有効化
conda activate ai-offline-env
ステップ2: アーカイブの生成(Pack)
環境が整ったら、`conda-pack` コマンドでアーカイブを作成します。
出力先のディレクトリを作成
mkdir -p ./output
仮想環境 ‘ai-offline-env’ を tar.gz として圧縮
conda pack -n ai-offline-env -o ./output/ai-offline-env.tar.gz
💡 アーキテクトの裏技:不要なキャッシュの除外と容量削減
AI系パッケージ(PyTorchやTensorFlowなど)を入れると、環境サイズが数GBに膨れ上がります。配布をスムーズにするため、テスト用のキャッシュや不要なドキュメント、静的ライブラリを除外してパックすることも可能です。
圧縮率を高めつつ、pycファイルやテストコードを除外してパックする場合
conda pack -n ai-offline-env \
–output ./output/ai-offline-env.tar.gz \
–exclude “.pyc” \
–exclude “share/doc” \
–exclude “share/man”
ステップ3: オフライン環境へのデプロイとバイナリ修復(Unpack)
作成した `ai-offline-env.tar.gz` を、ターゲットマシン(オフライン)に持ち込みます。ターゲット側には、あらかじめPythonが入っていなくても構いません(Conda-PackにはスタンドアロンのPythonバイナリが含まれています)。
ターゲットマシン側での配置用ディレクトリを作成
mkdir -p /opt/conda/envs/ai-offline-env
アーカイブを展開
tar -xzf ai-offline-env.tar.gz -C /opt/conda/envs/ai-offline-env
⚠️ 最重要:Shebang(シバン)の書き換え処理
Conda環境内のPythonスクリプトやバイナリ(Jupyterなどの実行ファイル)の先頭行には、ビルド時の絶対パス(例: `#!/home/developer/miniconda3/envs/ai-offline-env/bin/python`)がハードコードされています。
これをターゲットマシンのパス(例: `/opt/conda/envs/ai-offline-env/bin/python`)に自動書き換えしなければ、コマンドを実行した瞬間に `Bad interpreter: No such file or directory` が発生します。
Conda-Packを展開した後は、必ず以下のスクリプトを実行してパスの修復を行ってください。
スクリプトやバイナリ内のパスを現在のインストール先パスに自動置換する
/opt/conda/envs/ai-offline-env/bin/conda-unpack
この内部処理により、環境内の全実行ファイルのプレフィックスパスが安全に書き換えられます。
—
オフライン環境での Jupyter Lab 運用ベストプラクティス
環境の展開が完了したら、インターネット接続のない閉域網で Jupyter Lab を起動し、データサイエンス作業を行えるようにします。
1. 起動スクリプトの作成
現場の非エンジニアや他のメンバーが迷わないよう、環境のアクティベートとJupyter Labの起動をラップしたシェルスクリプトを用意するのがプロの作法です。
`start_jupyter.sh`
!/bin/bash
エラー発生時に即座にスクリプトを終了
set -e
このスクリプトが存在するディレクトリを基準にパスを解決
ENV_PATH=”$(cd “$(dirname “$0″)”; pwd)”
ポータブル環境のPythonおよびJupyterバイナリのパスを指定
JUPYTER_BIN=”$ENV_PATH/bin/jupyter”
echo “==================================================”
echo ” Starting Offline Jupyter Lab…”
echo ” Environment Path: $ENV_PATH”
echo “==================================================”
外部からのアクセスを許可しつつ、トークン認証付きでJupyter Labを起動
(必要に応じて –ip=127.0.0.1 に変更してください)
“$JUPYTER_BIN” lab \
–ip=0.0.0.0 \
–port=8888 \
–no-browser \
–allow-root
2. Jupyter Labを飛躍的に効率化する設定ファイル(`jupyter_lab_config.py`)
チーム開発や閉域網サーバーでの運用において、Jupyter Labの設定を固定化することはセキュリティと利便性の両面で極めて重要です。環境内に以下の設定ファイルを配置します。
構成例: `etc/jupyter/jupyter_lab_config.py`
==========================================
Jupyter Lab エンタープライズ設定ファイル
==========================================
import os
セキュリティ: パスワードハッシュの設定(例: ‘password’ の場合のハッシュ)
共有サーバーとして運用する場合、プレーンテキストのトークンではなくパスワードを推奨
c.ServerApp.password = ‘argon2:$argon2id$v=19$m=10240,t=10,p=8$…’
ネットワーク設定
閉域網内の別端末からアクセスできるよう全インターフェースにバインド
c.ServerApp.ip = ‘0.0.0.0’
c.ServerApp.port = 8888
ブラウザの自動起動を無効化(ヘッドレスサーバー運用のため必須)
c.ServerApp.open_browser = False
ワークスペース(ノートブックのルートディレクトリ)の指定
ポータブル環境内の特定ディレクトリをプロジェクトのルートとする
c.ServerApp.root_dir = os.path.expanduser(‘~/workspaces’)
セキュリティ: 外部からのiframe埋め込みを制限(Clickjacking対策)
c.ServerApp.tornado_settings = {
‘headers’: {
‘Content-Security-Policy’: “frame-ancestors ‘self'”
}
}
チェックポイント(.ipynb_checkpoints)の肥大化を防ぐため世代数を制限
c.FileContentsManager.delete_to_trash = False
c.FileContentsManager.checkpoint_interval = 1
—
チーム開発・CI/CDパイプラインへの組み込み
手動で `conda pack` を行うのはヒューマンエラーの元です。GitリポジトリとCI/CD(GitHub ActionsやGitLab CI)を連携させ、メインブランチへのマージ時に自動でポータブルなtar.gzをビルドし、内部のアーティファクトストレージ(ArtifactoryやNexusなど)にアップロードする仕組みを構築しましょう。
以下は、Linux (x86_64) 環境をターゲットとした GitHub Actions ワークフローのベストプラクティス例です。
`.github/workflows/package_env.yml`
name: Build Portable Conda Environment
on:
push:
branches:
- main
paths:
- ‘environment.yml’
jobs:
build-pack:
runs-on: ubuntu-latest
steps:
# リポジトリのチェックアウト
- name: Checkout Repository
uses: actions/checkout@v4
# Miniforge(軽量なConda環境)のセットアップ
- name: Setup Miniforge
uses: conda-incubator/setup-miniconda@v3
with:
auto-update-conda: true
python-version: “3.10”
activate-environment: “ds-project”
environment-file: “environment.yml”
auto-activate-base: false
# conda-packの導入
- name: Install Conda-Pack
shell: bash -l {0}
run: |
conda install -c conda-forge conda-pack -y
# 環境のパッケージング実行
- name: Run Conda-Pack
shell: bash -l {0}
run: |
# 仮想環境をパックしてアーカイブを生成
conda pack -n ds-project -o ds-project-portable.tar.gz –compress-level 6
# ビルドされたアーカイブをアーティファクトとして保存(またはS3や社内サーバーへ転送)
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: portable-environment
path: ds-project-portable.tar.gz
—
まとめ:プロのテックリードが知るべき教訓
インターネットが使えない現場へのPython/AI環境のデプロイは、往々にしてエンジニアの時間を奪う不毛なトラブルシューティングの連続になりがちです。
- 「ネットがないなら、動く環境を丸ごとコピーすればいい」 というシンプルかつ強力な発想。
- `conda-pack` を用いたバイナリレベルでの環境凍結。
- 展開後の `conda-unpack` による厳密なShebangパス修復。
- チーム全体で迷わないための起動スクリプトと設定ファイルのコード化。
これらを体系的にプロジェクトへ導入することで、環境差異に起因するバグやデプロイ時のトラブルをゼロにし、データサイエンティストやエンジニアが「本来のコードを書く・モデルをチューニングする」という創造的な作業に集中できる環境を創り出すことができます。
現場の生産性を極限まで高めるこの手法、ぜひ次のプロジェクトのオフライン要件でお試しください。