2026年9月22日火曜日

Sonatype Nexus Repository を DGX Spark に構築する

1. 概要

DGX Spark 上に Sonatype Nexus Repository 3 を Docker で構築し、Maven / npm / Docker のキャッシュ(プロキシ)リポジトリを構築する。

目的

  • Maven Central、npm registry、Docker Hub、APT のプロキシ兼キャッシュを構築する
  • 社内やローカル環境から高速にパッケージを取得できるようにする

前提と確認済み事項

項目
ホスト gx10-6acc.local(DGX Spark)
OS / アーキテクチャ Ubuntu / aarch64 (ARM64)
Docker 29.2.1
Docker Compose v5.0.2
Nexus イメージ sonatype/nexus3:latest
ポート 18081(Nexus UI / API)、15000(Docker registry)
認証 匿名アクセス
データ置き場 当面はシステムディスク上の /mnt/repo/nexus-data、SSD 調達後に /mnt/repo を SSD にマウントし直して移行

docker.io からログアウトしておくこと。そうしないと上手く Nexus を利用してくれないっぽい

全体の流れ

  1. 事前準備(SSH 接続、ディレクトリと設定ファイルの作成)
  2. Nexus のデプロイ
  3. リポジトリ作成(Maven / npm / Docker / APT)
  4. クライアント設定
  5. 動作検証
  6. (後日)SSD 調達後の /mnt/repo 移行

2. 事前準備

2.1 SSH 接続

ssh gx10-6acc.local

2.2 作業ディレクトリの作成

Nexus の設定ファイルを置くディレクトリを作成する。

mkdir -p ~/project/nexus
cd ~/project/nexus

2.3 データディレクトリの作成

Nexus のデータを保存するディレクトリを作成する。

sudo mkdir -p /mnt/repo/nexus-data
sudo chown -R 200:200 /mnt/repo/nexus-data
  • 200:200 は Nexus コンテナ内の実行ユーザー(UID/GID 200)である。
  • Nexus がデータディレクトリに書き込めるよう、所有権を合わせる。
  • SSD 移行について: 現時点では /mnt/repo/nexus-data はシステムディスク上に作成する。
  • SSD 調達後は、このディレクトリを SSD にマウントし直すことで、データをそのまま移行できる(詳細は「7. SSD 調達後の移行」参照)。

3. Nexus のデプロイ

3.1 compose.yaml の作成

~/project/nexus/compose.yaml を作成する。

services:
  nexus:
    image: sonatype/nexus3:latest
    container_name: nexus
    restart: always
    ports:
      - "0.0.0.0:18081:8081"   # Nexus UI / API
      - "0.0.0.0:15000:15000"  # Docker registry
    volumes:
      - /mnt/repo/nexus-data:/nexus-data
    environment:
      - INSTALL4J_ADD_VM_PARAMS=-Xms1g -Xmx2g -XX:MaxDirectMemorySize=1g
  • INSTALL4J_ADD_VM_PARAMS で JVM ヒープを設定する。
  • DGX Spark は残メモリが約 4GB なので、ヒープ 2GB + ダイレクトメモリ 1GB の合計約 3GB から始める。
  • /mnt/repo/nexus-data が Nexus のデータディレクトリである。

3.2 Nexus の起動

cd ~/project/nexus
docker compose up -d

起動状態を確認する。

docker compose ps

3.3 起動完了の待機

Nexus は初回起動に数分かかる。 ログを確認して、起動完了を待つ。

docker compose logs -f

ログに Started Sonatype Nexus OSS が表示されたら起動完了である。

3.4 admin パスワードの取得

初回起動時、admin パスワードは自動生成され、コンテナ内のファイルに保存される。

docker exec nexus cat /nexus-data/admin.password

このパスワードを控えておく。

3.5 初期設定(Web UI)

ブラウザで http://gx10-6acc.local:18081 にアクセスし、以下を設定する。

  1. admin / 上記のパスワードでログイン
  2. 新しい admin パスワードを設定
  3. ウィザードが表示されるので、それに従って進める
    • 匿名アクセスを有効化(「Enable anonymous access」を選択)

※ 匿名アクセス: 認証なしでリポジトリを参照できるようにする。

4. リポジトリの作成

4.1 基本情報の定義

これから Web API でリポジトリを作成するため、以下の情報を定義しておく。

NEXUS_URL="http://gx10-6acc.local:18081"
NEXUS_USER="admin"
 NEXUS_PASS='<YOUR_ADMIN_PASSWORD>'
BLOB_STORE="default"
  • <YOUR_ADMIN_PASSWORD> は 3.5 で設定した admin パスワードに置き換える。

4.2 Maven プロキシリポジトリ

Web API で maven2 (proxy) 形式のリポジトリを作成する。

項目
Name maven-central
Remote storage https://repo1.maven.org/maven2/
Blob store default
その他 既定値のまま

プロキシリポジトリは、リモート(Maven Central)から取得したパッケージをローカルにキャッシュする。

実行コマンド

curl -u ${NEXUS_USER}:${NEXUS_PASS} -X POST \
  ${NEXUS_URL}/service/rest/v1/repositories/maven/proxy \
  -H "Content-Type: application/json" \
  -d '{
    "name": "maven-central",
    "online": true,
    "storage": { "blobStoreName": "default", "strictContentTypeValidation": true },
    "proxy": { "remoteUrl": "https://repo1.maven.org/maven2/", "contentMaxAge": 1440, "metadataMaxAge": 1440 },
    "negativeCache": { "enabled": true, "timeToLive": 1440 },
    "httpClient": { "blocked": false, "autoBlock": true },
    "maven": { "versionPolicy": "RELEASE", "layoutPolicy": "PERMISSIVE" }
  }'

4.3 npm プロキシリポジトリ

Web API で npm (proxy) 形式のリポジトリを作成する。

項目
Name npmjs
Remote storage https://registry.npmjs.org/
Blob store default
その他 既定値のまま

実行コマンド

curl -u ${NEXUS_USER}:${NEXUS_PASS} -X POST \
  ${NEXUS_URL}/service/rest/v1/repositories/npm/proxy \
  -H "Content-Type: application/json" \
  -d '{
    "name": "npmjs",
    "online": true,
    "storage": { "blobStoreName": "default", "strictContentTypeValidation": true },
    "proxy": { "remoteUrl": "https://registry.npmjs.org/", "contentMaxAge": 1440, "metadataMaxAge": 1440 },
    "negativeCache": { "enabled": true, "timeToLive": 1440 },
    "httpClient": { "blocked": false, "autoBlock": true }
  }'

4.4 Docker プロキシリポジトリ

Web API で docker (proxy) 形式のリポジトリを作成する。

項目
Name docker-hub
Remote storage https://registry-1.docker.io/
HTTP port 15000
HTTPS port (空のまま)
Blob store default
  • Docker プロキシは HTTP ポート 15000 で公開する。
  • ローカル(HTTP)で使うため、HTTPS ポートは設定しない。

実行コマンド

リポジトリ作成

curl -u ${NEXUS_USER}:${NEXUS_PASS} -X POST \
  ${NEXUS_URL}/service/rest/v1/repositories/docker/proxy \
  -H "Content-Type: application/json" \
  -d '{
    "name": "docker-hub",
    "online": true,
    "storage": { "blobStoreName": "default", "strictContentTypeValidation": true },
    "proxy": { "remoteUrl": "https://registry-1.docker.io/", "contentMaxAge": 1440, "metadataMaxAge": 1440 },
    "negativeCache": { "enabled": true, "timeToLive": 1440 },
    "httpClient": { "blocked": false, "autoBlock": true },
    "docker": { "v1Enabled": false, "forceBasicAuth": false, "httpPort": 15000 },
    "dockerProxy": { "indexType": "HUB", "cacheForeignLayers": false }
  }'
  • forceBasicAuth: 匿名アクセスを有効にする場合は false に設定する

匿名アクセス用 Realm を追加

curl -sS -u "${NEXUS_USER}:${NEXUS_PASS}" \
  "${NEXUS_URL}/service/rest/v1/security/realms/active" \
  | jq 'if index("DockerToken") then . else . + ["DockerToken"] end' \
  | curl -sS -u "${NEXUS_USER}:${NEXUS_PASS}" \
      -X PUT \
      -H 'Content-Type: application/json' \
      --data-binary @- \
      "${NEXUS_URL}/service/rest/v1/security/realms/active"

匿名ユーザーアクセスの有効化

匿名アクセスは 3.5 の初期設定ウィザードで既に有効化済みである。

ここでの API 呼び出しは、その設定を確認・確実にするためのもので、既に有効なら何も変わらない(冪等)。

curl -sS -u "${NEXUS_USER}:${NEXUS_PASS}" \
  -X PUT \
  -H 'Content-Type: application/json' \
  "${NEXUS_URL}/service/rest/v1/security/anonymous" \
  -d '{
    "enabled": true,
    "userId": "anonymous",
    "realmName": "NexusAuthorizingRealm"
  }'

4.5 APT プロキシリポジトリ

Ubuntu archive

curl -u ${NEXUS_USER}:${NEXUS_PASS} \
  -X POST \
  "${NEXUS_URL}/service/rest/v1/repositories/apt/proxy" \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "ubuntu-archive",
    "online": true,
    "storage": {
      "blobStoreName": "'"${BLOB_STORE}"'",
      "strictContentTypeValidation": true
    },
    "proxy": {
      "remoteUrl": "http://archive.ubuntu.com/ubuntu/",
      "contentMaxAge": 1440,
      "metadataMaxAge": 60
    },
    "negativeCache": {
      "enabled": true,
      "timeToLive": 1440
    },
    "httpClient": {
      "blocked": false,
      "autoBlock": true
    },
    "apt": {
      "distribution": "",
      "flat": false,
      "enforceDistribution": false
    }
  }'

Ubuntu security

curl -u ${NEXUS_USER}:${NEXUS_PASS} \
  -X POST \
  "${NEXUS_URL}/service/rest/v1/repositories/apt/proxy" \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "ubuntu-security",
    "online": true,

    "storage": {
      "blobStoreName": "'"${BLOB_STORE}"'",
      "strictContentTypeValidation": true
    },
    "proxy": {
      "remoteUrl": "http://security.ubuntu.com/ubuntu/",
      "contentMaxAge": 1440,
      "metadataMaxAge": 60
    },
    "negativeCache": {
      "enabled": true,
      "timeToLive": 1440
    },
    "httpClient": {
      "blocked": false,
      "autoBlock": true
    },
    "apt": {
      "distribution": "",
      "flat": false,
      "enforceDistribution": false
    }
  }'

4.6 作成後の確認

作成したリポジトリが一覧に表示されていることを確認する。

  • maven-central
  • npmjs
  • docker-hub
  • ubuntu-archive
  • ubuntu-security

リポジトリ一覧の確認

# 全リポジトリの一覧(名前・形式・タイプ・URL)
curl -u ${NEXUS_USER}:${NEXUS_PASS} \
  ${NEXUS_URL}/service/rest/v1/repositories

特定リポジトリの詳細確認

# Maven
curl -u ${NEXUS_USER}:${NEXUS_PASS} \
  ${NEXUS_URL}/service/rest/v1/repositories/maven/proxy/maven-central

# npm
curl -u ${NEXUS_USER}:${NEXUS_PASS} \
  ${NEXUS_URL}/service/rest/v1/repositories/npm/proxy/npmjs

# Docker
curl -u ${NEXUS_USER}:${NEXUS_PASS} \
  ${NEXUS_URL}/service/rest/v1/repositories/docker/proxy/docker-hub

# APT
curl -u ${NEXUS_USER}:${NEXUS_PASS} \
  ${NEXUS_URL}/service/rest/v1/repositories/apt/proxy/ubuntu-archive

# APT security
curl -u ${NEXUS_USER}:${NEXUS_PASS} \
  ${NEXUS_URL}/service/rest/v1/repositories/apt/proxy/ubuntu-security

キャッシュ状況の確認

取得後に、Nexus の blob store にキャッシュが溜まっているかを確認できる。

# 各リポジトリのキャッシュ状況(asset 数など)
curl -u ${NEXUS_USER}:${NEXUS_PASS} \
  ${NEXUS_URL}/service/rest/v1/repositories/maven/proxy/maven-central

5. クライアント設定

作成したリポジトリを各クライアントから参照するための設定である。

5.1 Maven

~/.m2/settings.xml にミラー設定を追加する。

<settings>
  <mirrors>
    <mirror>
      <id>nexus</id>
      <mirrorOf>*</mirrorOf>
      <url>http://gx10-6acc.local:18081/repository/maven-central/</url>
    </mirror>
  </mirrors>
</settings>

mirrorOf* にすると、すべての Maven リポジトリを Nexus 経由にする。

5.2 npm

npm のレジストリを Nexus に向ける。

npm config set registry http://gx10-6acc.local:18081/repository/npmjs/

確認:

npm config get registry

5.3 Docker

Docker は HTTP(非 TLS)のレジストリを使うため、daemon 側で insecure registry を許可する必要がある。

/etc/docker/daemon.json に以下を追加する。

{
  "registry-mirrors": ["http://gx10-6acc.local:15000"],
  "insecure-registries": ["gx10-6acc.local:15000"]
}
  • registry-mirrors は Docker Hub へのアクセスを Nexus 経由にするための設定である。
  • insecure-registries は HTTP(非 TLS)でのアクセスを許可するための設定である。

Docker を再起動する。

sudo systemctl restart docker

5.4 APT

既存の sources をバックアップ。

sudo cp \
  /etc/apt/sources.list.d/ubuntu.sources \
  /etc/apt/sources.list.d/ubuntu.sources.bak

Nexus 用に sources を更新。

sudo tee /etc/apt/sources.list.d/ubuntu.sources >/dev/null <<'EOF'
Types: deb
URIs: http://gx10-6acc.local:18081/repository/ubuntu-archive/
Suites: noble noble-updates noble-backports
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

Types: deb
URIs: http://gx10-6acc.local:18081/repository/ubuntu-security/
Suites: noble-security
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
EOF

6. 動作検証

各リポジトリが正しくキャッシュできるか確認する。

6.1 Maven

mvn dependency:get -Dartifact=junit:junit:4.13.2

Nexus の Web UI で maven-central リポジトリに junit がキャッシュされていることを確認する。

6.2 npm

npm view lodash version

Nexus の Web UI で npmjs リポジトリに lodash がキャッシュされていることを確認する。

6.3 Docker

5.3 で設定した registry-mirrors により、Docker Hub への pull は Nexus 経由になる。そのため、通常の docker pull alpine で検証できる。

docker pull alpine

Nexus の Web UI で docker-hub リポジトリに alpine がキャッシュされていることを確認する。

registry-mirrors 経由では、docker pull alpine は自動的に Docker Hub の library/alpine として解決される。library/ プレフィックスを明示する必要はない。

6.4 APT

apt update で Nexus 経由でのパッケージリスト取得を確認する。

sudo apt update

これで一通りのキャシュ検証完了。以上。

0 件のコメント:

コメントを投稿