CLOVER🍀

That was when it all began.

Sonatype Nexus 3でコンポーネントをREST APIで削除する

これは、なにをしたくて書いたもの?

Sonatype Nexus 3を使ってリポジトリーにアップロードをしていると、時々削除したくなります。

特にSonatype Nexus自体の環境を作っていたり、コンテナイメージを作成するテストをしている時などに。

Sonatype NexusのWeb UIから削除できるのですが、面倒になってきたのでREST APIで削除する方法を調べてみました。

Sonatype NexusREST API

REST APIのリファレンス、いわゆるSwaggerはこちらですね。

Nexus Repository API Reference

Base URLは、Sonatype NexusにログインしてSetting → System → APIから確認できます。

環境

今回の環境。

Sonatype Nexusは3.84.0-01を使います。

リポジトリーはTerraformで作成します。

$ terraform version
Terraform v1.13.3
on linux_amd64

対象はDockerにします。

$ docker version
Client: Docker Engine - Community
 Version:           28.4.0
 API version:       1.51
 Go version:        go1.24.7
 Git commit:        d8eb465
 Built:             Wed Sep  3 20:57:32 2025
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          28.4.0
  API version:      1.51 (minimum version 1.24)
  Go version:       go1.24.7
  Git commit:       249d679
  Built:            Wed Sep  3 20:57:32 2025
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.7.27
  GitCommit:        05044ec0a9a75232cad458027ca83437aae3f4da
 runc:
  Version:          1.2.5
  GitCommit:        v1.2.5-0-g59923ef
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

準備

まずはSonatype Nexus上にリポジトリーを作成します。

今回はDockerレジストリーとします。

main.tf

terraform {
  required_version = "v1.13.3"

  required_providers {
    nexus = {
      source  = "datadrivers/nexus"
      version = "2.6.0"
    }
  }
}

provider "nexus" {
  username = "admin"
  password = "password"
  url      = "http://172.17.0.2:8081"
  insecure = true
}

resource "nexus_security_realms" "this" {
  active = [
    "NexusAuthenticatingRealm",
    "DockerToken",
  ]
}

resource "nexus_repository_docker_proxy" "dockerhub" {
  name   = "docker-dockerhub-proxy"
  online = true

  docker {
    force_basic_auth = false
    v1_enabled       = false
  }

  docker_proxy {
    index_type = "HUB"
  }

  storage {
    blob_store_name                = "default"
    strict_content_type_validation = true
  }

  proxy {
    remote_url       = "https://registry-1.docker.io"
    content_max_age  = 1440
    metadata_max_age = 1440
  }

  negative_cache {
    enabled = true
    ttl     = 1440
  }

  http_client {
    blocked    = false
    auto_block = true
  }
}

resource "nexus_repository_docker_hosted" "this" {
  name   = "docker-hosted"
  online = true

  docker {
    force_basic_auth = true
    http_port        = 5000
    v1_enabled       = false
  }

  storage {
    blob_store_name                = "default"
    strict_content_type_validation = true
    write_policy                   = "ALLOW_ONCE" ## 再デプロイ不可
    latest_policy                  = true         ## latestタグのみ再デプロイ可
  }
}

resource "nexus_repository_docker_group" "this" {
  name   = "docker-group"
  online = true

  docker {
    force_basic_auth = false
    http_port        = 15000
    v1_enabled       = false
  }

  group {
    member_names = [
      nexus_repository_docker_hosted.this.name,
      nexus_repository_docker_proxy.dockerhub.name,
    ]
  }

  storage {
    blob_store_name                = "default"
    strict_content_type_validation = true
  }
}

よくあるGroup、Hosted、Proxy(Docker Hub)の構成です。

作成。

$ terraform init
$ terraform apply

作成したDockerレジストリーは、ローカルのDockerのinsecure registryとして登録しておきます。

/etc/docker/daemon.json
{
  "insecure-registries": [
    "172.17.0.2:5000",
    "172.17.0.2:15000"
  ]
}

あとはコンテナイメージをpushしておきましょう。

nginxのコンテナイメージをDocker Hubから取得して

$ docker image pull nginx:1.29.1-bookworm

別のタグを付けます。

$ docker image tag nginx:1.29.1-bookworm 172.17.0.2:5000/my-nginx:1.29.1-bookworm

先ほど作成したHostedリポジトリーにログインして、pushします。

$ docker login 172.17.0.2:5000
$ docker image push 172.17.0.2:5000/my-nginx:1.29.1-bookworm

もう2つ追加しておきましょう。

$ docker image pull nginx:1.28.0-bookworm
$ docker image tag nginx:1.28.0-bookworm 172.17.0.2:5000/my-nginx:1.28.0-bookworm
$ docker image push 172.17.0.2:5000/my-nginx:1.28.0-bookworm


$ docker image pull eclipse-temurin:21.0.8_9-jdk-noble
$ docker image tag eclipse-temurin:21.0.8_9-jdk-noble 172.17.0.2:5000/my-eclipse-temurin:21.0.8_9-jdk-noble
$ docker image push 172.17.0.2:5000/my-eclipse-temurin:21.0.8_9-jdk-noble

これで準備完了です。

コンポーネントREST APIで削除する

それでは、REST APIでアクセスしていきます。

Nexus Repository API Reference

今回の目的は削除なのですが、まずはコンポーネントのidを特定する必要がありそうです。

ここではSearch APIを使います。

Search API

特にパラメーターなしで実行。

$ curl 172.17.0.2:8081/service/rest/v1/search

どうやらすべてのリポジトリーのコンポーネントが返ってくるようです。
※ページングあり

{
  "items" : [ {
    "id" : "ZG9ja2VyLWhvc3RlZDo0ZjFiYmNkZA",
    "repository" : "docker-hosted",
    "format" : "docker",
    "group" : "",
    "name" : "my-nginx",
    "version" : "1.29.1-bookworm",
    "assets" : [ {
      "downloadUrl" : "http://172.17.0.2:8081/repository/docker-hosted/v2/my-nginx/manifests/1.29.1-bookworm",
      "path" : "/v2/my-nginx/manifests/1.29.1-bookworm",
      "id" : "ZG9ja2VyLWhvc3RlZDoxNzE1NjBhMg",
      "repository" : "docker-hosted",
      "format" : "docker",
      "checksum" : {
        "sha1" : "69fa1bb0f06fe9292d4b45a3ae7a803231635491",
        "sha256" : "ebe6b7ee1206828d80eabed09809e94222d09fba59c7cda15da41962e06b088e"
      },
      "contentType" : "application/vnd.docker.distribution.manifest.v2+json",
      "lastModified" : "2025-09-23T08:10:28.778+00:00",
      "lastDownloaded" : null,
      "uploader" : "admin",
      "uploaderIp" : "172.17.0.1",
      "fileSize" : 1778,
      "blobCreated" : null,
      "blobStoreName" : null,
      "docker" : { }
    } ]
  }, {
    "id" : "ZG9ja2VyLWhvc3RlZDo5ZTM3NzliYQ",
    "repository" : "docker-hosted",
    "format" : "docker",
    "group" : "",
    "name" : "my-nginx",
    "version" : "1.28.0-bookworm",
    "assets" : [ {
      "downloadUrl" : "http://172.17.0.2:8081/repository/docker-hosted/v2/my-nginx/manifests/1.28.0-bookworm",
      "path" : "/v2/my-nginx/manifests/1.28.0-bookworm",
      "id" : "ZG9ja2VyLWhvc3RlZDpkZjBmMDQ2Nw",
      "repository" : "docker-hosted",
      "format" : "docker",
      "checksum" : {
        "sha1" : "c007ca8b2d1f20b432fc8d56f05c9a1b64ea6f58",
        "sha256" : "9b2b3f1618c2af647886a88d95467ad59554780cb8cbcad57435f16ca27c84bf"
      },
      "contentType" : "application/vnd.docker.distribution.manifest.v2+json",
      "lastModified" : "2025-09-23T08:11:41.591+00:00",
      "lastDownloaded" : null,
      "uploader" : "admin",
      "uploaderIp" : "172.17.0.1",
      "fileSize" : 1778,
      "blobCreated" : null,
      "blobStoreName" : null,
      "docker" : { }
    } ]
  }, {
    "id" : "ZG9ja2VyLWhvc3RlZDplZDUzMzY5Nw",
    "repository" : "docker-hosted",
    "format" : "docker",
    "group" : "",
    "name" : "my-eclipse-temurin",
    "version" : "21.0.8_9-jdk-noble",
    "assets" : [ {
      "downloadUrl" : "http://172.17.0.2:8081/repository/docker-hosted/v2/my-eclipse-temurin/manifests/21.0.8_9-jdk-noble",
      "path" : "/v2/my-eclipse-temurin/manifests/21.0.8_9-jdk-noble",
      "id" : "ZG9ja2VyLWhvc3RlZDo1N2VjZWI0Zg",
      "repository" : "docker-hosted",
      "format" : "docker",
      "checksum" : {
        "sha1" : "eae97f083090d98b8649953824840abe4bc6a226",
        "sha256" : "0c8afdf0dc838711039d20bb517ef120856186a84500687b1d398965b578943c"
      },
      "contentType" : "application/vnd.docker.distribution.manifest.v2+json",
      "lastModified" : "2025-09-23T08:13:55.754+00:00",
      "lastDownloaded" : null,
      "uploader" : "admin",
      "uploaderIp" : "172.17.0.1",
      "fileSize" : 1369,
      "blobCreated" : null,
      "blobStoreName" : null,
      "docker" : { }
    } ]
  } ],
  "continuationToken" : null
}

検索条件を付けてみます。

リポジトリーとコンポーネント名。

$ curl '172.17.0.2:8081/service/rest/v1/search?repository=docker-hosted&name=my-nginx'
{
  "items" : [ {
    "id" : "ZG9ja2VyLWhvc3RlZDo0ZjFiYmNkZA",
    "repository" : "docker-hosted",
    "format" : "docker",
    "group" : "",
    "name" : "my-nginx",
    "version" : "1.29.1-bookworm",
    "assets" : [ {
      "downloadUrl" : "http://172.17.0.2:8081/repository/docker-hosted/v2/my-nginx/manifests/1.29.1-bookworm",
      "path" : "/v2/my-nginx/manifests/1.29.1-bookworm",
      "id" : "ZG9ja2VyLWhvc3RlZDoxNzE1NjBhMg",
      "repository" : "docker-hosted",
      "format" : "docker",
      "checksum" : {
        "sha1" : "69fa1bb0f06fe9292d4b45a3ae7a803231635491",
        "sha256" : "ebe6b7ee1206828d80eabed09809e94222d09fba59c7cda15da41962e06b088e"
      },
      "contentType" : "application/vnd.docker.distribution.manifest.v2+json",
      "lastModified" : "2025-09-23T08:10:28.778+00:00",
      "lastDownloaded" : null,
      "uploader" : "admin",
      "uploaderIp" : "172.17.0.1",
      "fileSize" : 1778,
      "blobCreated" : null,
      "blobStoreName" : null,
      "docker" : { }
    } ]
  }, {
    "id" : "ZG9ja2VyLWhvc3RlZDo5ZTM3NzliYQ",
    "repository" : "docker-hosted",
    "format" : "docker",
    "group" : "",
    "name" : "my-nginx",
    "version" : "1.28.0-bookworm",
    "assets" : [ {
      "downloadUrl" : "http://172.17.0.2:8081/repository/docker-hosted/v2/my-nginx/manifests/1.28.0-bookworm",
      "path" : "/v2/my-nginx/manifests/1.28.0-bookworm",
      "id" : "ZG9ja2VyLWhvc3RlZDpkZjBmMDQ2Nw",
      "repository" : "docker-hosted",
      "format" : "docker",
      "checksum" : {
        "sha1" : "c007ca8b2d1f20b432fc8d56f05c9a1b64ea6f58",
        "sha256" : "9b2b3f1618c2af647886a88d95467ad59554780cb8cbcad57435f16ca27c84bf"
      },
      "contentType" : "application/vnd.docker.distribution.manifest.v2+json",
      "lastModified" : "2025-09-23T08:11:41.591+00:00",
      "lastDownloaded" : null,
      "uploader" : "admin",
      "uploaderIp" : "172.17.0.1",
      "fileSize" : 1778,
      "blobCreated" : null,
      "blobStoreName" : null,
      "docker" : { }
    } ]
  } ],
  "continuationToken" : null
}


$ curl '172.17.0.2:8081/service/rest/v1/search?repository=docker-hosted&name=my-eclipse-temurin'
{
  "items" : [ {
    "id" : "ZG9ja2VyLWhvc3RlZDplZDUzMzY5Nw",
    "repository" : "docker-hosted",
    "format" : "docker",
    "group" : "",
    "name" : "my-eclipse-temurin",
    "version" : "21.0.8_9-jdk-noble",
    "assets" : [ {
      "downloadUrl" : "http://172.17.0.2:8081/repository/docker-hosted/v2/my-eclipse-temurin/manifests/21.0.8_9-jdk-noble",
      "path" : "/v2/my-eclipse-temurin/manifests/21.0.8_9-jdk-noble",
      "id" : "ZG9ja2VyLWhvc3RlZDo1N2VjZWI0Zg",
      "repository" : "docker-hosted",
      "format" : "docker",
      "checksum" : {
        "sha1" : "eae97f083090d98b8649953824840abe4bc6a226",
        "sha256" : "0c8afdf0dc838711039d20bb517ef120856186a84500687b1d398965b578943c"
      },
      "contentType" : "application/vnd.docker.distribution.manifest.v2+json",
      "lastModified" : "2025-09-23T08:13:55.754+00:00",
      "lastDownloaded" : null,
      "uploader" : "admin",
      "uploaderIp" : "172.17.0.1",
      "fileSize" : 1369,
      "blobCreated" : null,
      "blobStoreName" : null,
      "docker" : { }
    } ]
  } ],
  "continuationToken" : null
}

リポジトリー、コンポーネント名、バージョン指定。

$ curl '172.17.0.2:8081/service/rest/v1/search?repository=docker-hosted&name=my-nginx&version=1.28.0-bookworm'
{
  "items" : [ {
    "id" : "ZG9ja2VyLWhvc3RlZDo5ZTM3NzliYQ",
    "repository" : "docker-hosted",
    "format" : "docker",
    "group" : "",
    "name" : "my-nginx",
    "version" : "1.28.0-bookworm",
    "assets" : [ {
      "downloadUrl" : "http://172.17.0.2:8081/repository/docker-hosted/v2/my-nginx/manifests/1.28.0-bookworm",
      "path" : "/v2/my-nginx/manifests/1.28.0-bookworm",
      "id" : "ZG9ja2VyLWhvc3RlZDpkZjBmMDQ2Nw",
      "repository" : "docker-hosted",
      "format" : "docker",
      "checksum" : {
        "sha1" : "c007ca8b2d1f20b432fc8d56f05c9a1b64ea6f58",
        "sha256" : "9b2b3f1618c2af647886a88d95467ad59554780cb8cbcad57435f16ca27c84bf"
      },
      "contentType" : "application/vnd.docker.distribution.manifest.v2+json",
      "lastModified" : "2025-09-23T08:11:41.591+00:00",
      "lastDownloaded" : null,
      "uploader" : "admin",
      "uploaderIp" : "172.17.0.1",
      "fileSize" : 1778,
      "blobCreated" : null,
      "blobStoreName" : null,
      "docker" : { }
    } ]
  } ],
  "continuationToken" : null
}

これで検索できそうですね。

次に、Component APIを見てみます。

Components API

コンポーネントの一覧は、リポジトリーを指定して取得するようです。

$ curl 172.17.0.2:8081/service/rest/v1/components?repository=docker-hosted
{
  "items" : [ {
    "id" : "ZG9ja2VyLWhvc3RlZDo0ZjFiYmNkZA",
    "repository" : "docker-hosted",
    "format" : "docker",
    "group" : "",
    "name" : "my-nginx",
    "version" : "1.29.1-bookworm",
    "assets" : [ {
      "downloadUrl" : "http://172.17.0.2:8081/repository/docker-hosted/v2/my-nginx/manifests/1.29.1-bookworm",
      "path" : "/v2/my-nginx/manifests/1.29.1-bookworm",
      "id" : "ZG9ja2VyLWhvc3RlZDoxNzE1NjBhMg",
      "repository" : "docker-hosted",
      "format" : "docker",
      "checksum" : {
        "sha1" : "69fa1bb0f06fe9292d4b45a3ae7a803231635491",
        "sha256" : "ebe6b7ee1206828d80eabed09809e94222d09fba59c7cda15da41962e06b088e"
      },
      "contentType" : "application/vnd.docker.distribution.manifest.v2+json",
      "lastModified" : "2025-09-23T08:10:28.778+00:00",
      "lastDownloaded" : null,
      "uploader" : "admin",
      "uploaderIp" : "172.17.0.1",
      "fileSize" : 1778,
      "blobCreated" : "2025-09-23T08:10:28.779+00:00",
      "blobStoreName" : null,
      "docker" : { }
    } ]
  }, {
    "id" : "ZG9ja2VyLWhvc3RlZDo5ZTM3NzliYQ",
    "repository" : "docker-hosted",
    "format" : "docker",
    "group" : "",
    "name" : "my-nginx",
    "version" : "1.28.0-bookworm",
    "assets" : [ {
      "downloadUrl" : "http://172.17.0.2:8081/repository/docker-hosted/v2/my-nginx/manifests/1.28.0-bookworm",
      "path" : "/v2/my-nginx/manifests/1.28.0-bookworm",
      "id" : "ZG9ja2VyLWhvc3RlZDpkZjBmMDQ2Nw",
      "repository" : "docker-hosted",
      "format" : "docker",
      "checksum" : {
        "sha1" : "c007ca8b2d1f20b432fc8d56f05c9a1b64ea6f58",
        "sha256" : "9b2b3f1618c2af647886a88d95467ad59554780cb8cbcad57435f16ca27c84bf"
      },
      "contentType" : "application/vnd.docker.distribution.manifest.v2+json",
      "lastModified" : "2025-09-23T08:11:41.591+00:00",
      "lastDownloaded" : null,
      "uploader" : "admin",
      "uploaderIp" : "172.17.0.1",
      "fileSize" : 1778,
      "blobCreated" : "2025-09-23T08:11:41.592+00:00",
      "blobStoreName" : null,
      "docker" : { }
    } ]
  }, {
    "id" : "ZG9ja2VyLWhvc3RlZDplZDUzMzY5Nw",
    "repository" : "docker-hosted",
    "format" : "docker",
    "group" : "",
    "name" : "my-eclipse-temurin",
    "version" : "21.0.8_9-jdk-noble",
    "assets" : [ {
      "downloadUrl" : "http://172.17.0.2:8081/repository/docker-hosted/v2/my-eclipse-temurin/manifests/21.0.8_9-jdk-noble",
      "path" : "/v2/my-eclipse-temurin/manifests/21.0.8_9-jdk-noble",
      "id" : "ZG9ja2VyLWhvc3RlZDo1N2VjZWI0Zg",
      "repository" : "docker-hosted",
      "format" : "docker",
      "checksum" : {
        "sha1" : "eae97f083090d98b8649953824840abe4bc6a226",
        "sha256" : "0c8afdf0dc838711039d20bb517ef120856186a84500687b1d398965b578943c"
      },
      "contentType" : "application/vnd.docker.distribution.manifest.v2+json",
      "lastModified" : "2025-09-23T08:13:55.754+00:00",
      "lastDownloaded" : null,
      "uploader" : "admin",
      "uploaderIp" : "172.17.0.1",
      "fileSize" : 1369,
      "blobCreated" : "2025-09-23T08:13:55.755+00:00",
      "blobStoreName" : null,
      "docker" : { }
    } ]
  } ],
  "continuationToken" : null
}

これでもリポジトリー内のコンポーネントは取得できそうですね。

ただ、リポジトリー以上の検索条件は指定できないみたいなので、今回のように一意に特定したい場合はSearch APIですね。

idを指定してコンポーネントをひとつ取得。

$ curl 172.17.0.2:8081/service/rest/v1/components/ZG9ja2VyLWhvc3RlZDo5ZTM3NzliYQ
{
  "id" : "ZG9ja2VyLWhvc3RlZDo5ZTM3NzliYQ",
  "repository" : "docker-hosted",
  "format" : "docker",
  "group" : "",
  "name" : "my-nginx",
  "version" : "1.28.0-bookworm",
  "assets" : [ {
    "downloadUrl" : "http://172.17.0.2:8081/repository/docker-hosted/v2/my-nginx/manifests/1.28.0-bookworm",
    "path" : "/v2/my-nginx/manifests/1.28.0-bookworm",
    "id" : "ZG9ja2VyLWhvc3RlZDpkZjBmMDQ2Nw",
    "repository" : "docker-hosted",
    "format" : "docker",
    "checksum" : {
      "sha1" : "c007ca8b2d1f20b432fc8d56f05c9a1b64ea6f58",
      "sha256" : "9b2b3f1618c2af647886a88d95467ad59554780cb8cbcad57435f16ca27c84bf"
    },
    "contentType" : "application/vnd.docker.distribution.manifest.v2+json",
    "lastModified" : "2025-09-23T08:11:41.591+00:00",
    "lastDownloaded" : null,
    "uploader" : "admin",
    "uploaderIp" : "172.17.0.1",
    "fileSize" : 1778,
    "blobCreated" : "2025-09-23T08:11:41.592+00:00",
    "blobStoreName" : null,
    "docker" : { }
  } ]
}

このidは、Search APIで取得したものです。

$ curl -s '172.17.0.2:8081/service/rest/v1/search?repository=docker-hosted&name=my-nginx&version=1.28.0-bookworm' | jq -r '.items[].id'
ZG9ja2VyLWhvc3RlZDo5ZTM3NzliYQ

これを組み合わせると、検索してコンポーネントの取得ができます。

$ curl 172.17.0.2:8081/service/rest/v1/components/$(curl -s '172.17.0.2:8081/service/rest/v1/search?repository=docker-hosted&name=my-nginx&version=1.28.0-bookworm' | jq -r '.items[].id')
{
  "id" : "ZG9ja2VyLWhvc3RlZDo5ZTM3NzliYQ",
  "repository" : "docker-hosted",
  "format" : "docker",
  "group" : "",
  "name" : "my-nginx",
  "version" : "1.28.0-bookworm",
  "assets" : [ {
    "downloadUrl" : "http://172.17.0.2:8081/repository/docker-hosted/v2/my-nginx/manifests/1.28.0-bookworm",
    "path" : "/v2/my-nginx/manifests/1.28.0-bookworm",
    "id" : "ZG9ja2VyLWhvc3RlZDpkZjBmMDQ2Nw",
    "repository" : "docker-hosted",
    "format" : "docker",
    "checksum" : {
      "sha1" : "c007ca8b2d1f20b432fc8d56f05c9a1b64ea6f58",
      "sha256" : "9b2b3f1618c2af647886a88d95467ad59554780cb8cbcad57435f16ca27c84bf"
    },
    "contentType" : "application/vnd.docker.distribution.manifest.v2+json",
    "lastModified" : "2025-09-23T08:11:41.591+00:00",
    "lastDownloaded" : null,
    "uploader" : "admin",
    "uploaderIp" : "172.17.0.1",
    "fileSize" : 1778,
    "blobCreated" : "2025-09-23T08:11:41.592+00:00",
    "blobStoreName" : null,
    "docker" : { }
  } ]
}

削除してみましょう。

$ curl -X DELETE 172.17.0.2:8081/service/rest/v1/components/$(curl -s '172.17.0.2:8081/service/rest/v1/search?repository=docker-hosted&name=my-nginx&version=1.28.0-bookworm' | jq -r '.items[].id') -i
HTTP/1.1 403 Forbidden
Server: Nexus/3.84.1-01 (COMMUNITY)
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src http: data: blob: 'unsafe-inline'; script-src http: 'unsafe-inline' 'unsafe-eval'
X-Siesta-FaultId: 0484b316-502f-426b-91bb-e4eb0ded4e9a
Content-Length: 0

ログイン必須なので、403になりました。

ではBasic認証でユーザー名とパスワードを指定して実行。

$ curl -u admin:password -X DELETE 172.17.0.2:8081/service/rest/v1/components/$(curl -s '172.17.0.2:8081/service/rest/v1/search?repository=docker-hosted&name=my-nginx&version=1.28.0-bookworm' | jq -r '.items[].id') -i
HTTP/1.1 204 No Content
Server: Nexus/3.84.1-01 (COMMUNITY)
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src http: data: blob: 'unsafe-inline'; script-src http: 'unsafe-inline' 'unsafe-eval'

今度は削除できました。

検索結果からもいなくなっています。

$ curl '172.17.0.2:8081/service/rest/v1/search?repository=docker-hosted&name=my-nginx'
{
  "items" : [ {
    "id" : "ZG9ja2VyLWhvc3RlZDo0ZjFiYmNkZA",
    "repository" : "docker-hosted",
    "format" : "docker",
    "group" : "",
    "name" : "my-nginx",
    "version" : "1.29.1-bookworm",
    "assets" : [ {
      "downloadUrl" : "http://172.17.0.2:8081/repository/docker-hosted/v2/my-nginx/manifests/1.29.1-bookworm",
      "path" : "/v2/my-nginx/manifests/1.29.1-bookworm",
      "id" : "ZG9ja2VyLWhvc3RlZDoxNzE1NjBhMg",
      "repository" : "docker-hosted",
      "format" : "docker",
      "checksum" : {
        "sha1" : "69fa1bb0f06fe9292d4b45a3ae7a803231635491",
        "sha256" : "ebe6b7ee1206828d80eabed09809e94222d09fba59c7cda15da41962e06b088e"
      },
      "contentType" : "application/vnd.docker.distribution.manifest.v2+json",
      "lastModified" : "2025-09-23T08:10:28.778+00:00",
      "lastDownloaded" : null,
      "uploader" : "admin",
      "uploaderIp" : "172.17.0.1",
      "fileSize" : 1778,
      "blobCreated" : null,
      "blobStoreName" : null,
      "docker" : { }
    } ]
  } ],
  "continuationToken" : null
}

OKですね。

オマケ

こういうのはスクリプト化したくなるものです。

delete-nexus-component.sh

#!/bin/bash

REPOSITORY_NAME=$1
COMPONENT_NAME=$2
COMPONENT_VERSION=$3

CREDENTIAL="admin:password"
NEXUS_BASE_URL=http://172.17.0.2:8081/service/rest

curl -u ${CREDENTIAL} -i  -X DELETE ${NEXUS_BASE_URL}/v1/components/$(curl -s "${NEXUS_BASE_URL}/v1/search?repository=${REPOSITORY_NAME}&name=${COMPONENT_NAME}&version=${COMPONENT_VERSION}" | jq -r '.items[].id')

実行例。

$ chmod +x delete-nexus-component.sh
$ ./delete-nexus-component.sh docker-hosted my-nginx 1.29.1-bookworm

こんなところでしょうか。

おわりに

Sonatype Nexus 3でコンポーネントREST APIで削除してみました。

REST APIに関する情報を調べるところからになりましたが、これでやりたいことはできそうなのでOKでしょう。