制品(Artifact)是构建的产出物——Docker镜像、JAR包、npm包、Helm Chart等。制品管理确保每次构建的产出被唯一标识、安全存储、可追溯、可复用。
本地文件 → FTP/NFS → Nexus/Artifactory → Harbor(Docker) → OCI标准统一 → Cosign签名+SBOM供应链安全
| 类型 | 代表 | 用途 | 协议 |
|---|---|---|---|
| 通用制品仓库 | Nexus Repository OSS | Maven/npm/PyPI/raw | HTTP |
| 企业制品平台 | JFrog Artifactory | 全语言+高级特性 | HTTP |
| 容器镜像仓库 | Harbor | Docker镜像+Helm+OCI | Registry API |
| 公共镜像服务 | Docker Hub/GHCR | 开源镜像分发 | Registry API |
| 云厂商仓库 | ECR/ACR/CR | 云原生集成 | 云API+Registry API |
# Docker部署Nexus
docker run -d --name nexus -p 8081:8081 \
-v nexus-data:/nexus-data --restart unless-stopped \
sonatype/nexus3:latest
# 等待启动
docker logs -f nexus 2>&1 | grep "Started Sonatype Nexus OSS"
# 获取初始密码
docker exec nexus cat /nexus-data/admin.password
# 修改密码
curl -u admin:$(docker exec nexus cat /nexus-data/admin.password) \
-X PUT "http://localhost:8081/service/rest/v1/security/users/admin/change-password" \
-H "Content-Type: text/plain" -d "MyNewPass123!"
# 创建npm hosted仓库
curl -u admin:MyNewPass123! \
-X POST "http://localhost:8081/service/rest/v1/repositories/npm/hosted" \
-H "Content-Type: application/json" \
-d '{
"name": "npm-hosted",
"online": true,
"storage": {
"blobStoreName": "default",
"strictContentTypeValidation": true,
"writePolicy": "ALLOW_ONCE"
}
}'
# 创建npm proxy仓库(代理淘宝源)
curl -u admin:MyNewPass123! \
-X POST "http://localhost:8081/service/rest/v1/repositories/npm/proxy" \
-H "Content-Type: application/json" \
-d '{
"name": "npm-proxy",
"online": true,
"storage": {"blobStoreName": "default", "strictContentTypeValidation": true},
"proxy": {"remoteUrl": "https://registry.npmmirror.com", "contentMaxAge": 1440}
}'
# 创建group仓库
curl -u admin:MyNewPass123! \
-X POST "http://localhost:8081/service/rest/v1/repositories/npm/group" \
-H "Content-Type: application/json" \
-d '{
"name": "npm-group",
"online": true,
"storage": {"blobStoreName": "default"},
"group": {"memberNames": ["npm-hosted", "npm-proxy"]}
}'
# 配置Maven settings.xml
mkdir -p ~/.m2
cat > ~/.m2/settings.xml << 'SETTINGS'
<settings>
<servers>
<server>
<id>nexus-releases</id>
<username>admin</username>
<password>MyNewPass123!</password>
</server>
<server>
<id>nexus-snapshots</id>
<username>admin</username>
<password>MyNewPass123!</password>
</server>
</servers>
<mirrors>
<mirror>
<id>nexus-public</id>
<mirrorOf>*</mirrorOf>
<url>http://localhost:8081/repository/maven-public/</url>
</mirror>
</mirrors>
</settings>
SETTINGS
# 发布Release
mvn clean deploy -DskipTests \
-DaltDeploymentRepository=nexus-releases::default::http://localhost:8081/repository/maven-releases/
# 发布Snapshot
mvn clean deploy -DskipTests \
-DaltDeploymentRepository=nexus-snapshots::default::http://localhost:8081/repository/maven-snapshots/
# 搜索制品
curl -u admin:MyNewPass123! \
"http://localhost:8081/service/rest/v1/search?repository=maven-releases&name=my-app" | jq '.'
# 下载Harbor
wget https://github.com/goharbor/harbor/releases/download/v2.10.0/harbor-offline-installer-v2.10.0.tgz
tar xzf harbor-offline-installer-v2.10.0.tgz && cd harbor
# 配置harbor.yml
cp harbor.yml.tmpl harbor.yml
cat > harbor.yml << 'EOF'
hostname: harbor.mycompany.com
http:
port: 80
https:
port: 443
certificate: /etc/harbor/cert/server.crt
private_key: /etc/harbor/cert/server.key
harbor_admin_password: HarborAdmin123!
data_volume: /data/harbor
trivy:
ignore_unfixed: true
skip_update: false
security_check: vuln
log:
level: info
local:
rotate_count: 50
rotate_size: 200M
location: /var/log/harbor
EOF
# 生成自签名证书
mkdir -p /etc/harbor/cert
openssl req -x509 -nodes -days 3650 -newkey rsa:4096 \
-keyout /etc/harbor/cert/server.key \
-out /etc/harbor/cert/server.crt \
-subj "/CN=harbor.mycompany.com"
# 安装(含Trivy扫描器+ChartMuseum)
./install.sh --with-trivy --with-chartmuseum
# 查看状态
docker compose ps
# 登录Harbor
docker login harbor.mycompany.com -u admin -p HarborAdmin123!
# 构建并推送
docker build -t harbor.mycompany.com/devops/myapp:v1.2.3 .
docker push harbor.mycompany.com/devops/myapp:v1.2.3
# 推送多架构镜像
docker buildx build --platform linux/amd64,linux/arm64 \
-t harbor.mycompany.com/devops/myapp:v1.2.3 --push .
# 查看漏洞扫描结果
curl -u admin:HarborAdmin123! -k \
"https://harbor.mycompany.com/api/v2.0/projects/devops/repositories/myapp/artifacts/v1.2.3?with_scan_overview=true" | jq '.scan_overview'
# 触发漏洞扫描
curl -u admin:HarborAdmin123! -k -X POST \
"https://harbor.mycompany.com/api/v2.0/projects/devops/repositories/myapp/artifacts/v1.2.3/scan"
# 设置镜像不可变标签(防覆盖)
curl -u admin:HarborAdmin123! -k -X POST \
"https://harbor.mycompany.com/api/v2.0/projects/devops/immutabletagrules" \
-H "Content-Type: application/json" \
-d '{"tag_filter":"**","scope_selector":{"kind":"repo","decoration":"repoMatches","pattern":"**"}}'
# 安装Cosign
curl -L -o /usr/local/bin/cosign \
https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64
chmod +x /usr/local/bin/cosign
# 生成密钥对
cosign generate-key-pair
# 输入密码 → 生成 cosign.key + cosign.pub
# 对镜像签名
cosign sign --key cosign.key harbor.mycompany.com/devops/myapp:v1.2.3
# 验证签名
cosign verify --key cosign.pub harbor.mycompany.com/devops/myapp:v1.2.3
# 安装Syft生成SBOM
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
syft harbor.mycompany.com/devops/myapp:v1.2.3 -o spdx-json > sbom.spdx.json
# 附加SBOM到镜像
cosign attach sbom --sbom sbom.spdx.json harbor.mycompany.com/devops/myapp:v1.2.3
# 推送Helm Chart到Harbor OCI
helm package ./mychart
helm push mychart-1.0.0.tgz oci://harbor.mycompany.com/devops
# 拉取OCI Chart
helm pull oci://harbor.mycompany.com/devops/mychart --version 1.0.0
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
│ Git Push │───▶│ CI Pipeline │───▶│ Build Artifacts│
└─────────────┘ └──────────────┘ └────────┬────────┘
│
┌─────────────────────────────────┐│
│ ▼▼
┌─────▼─────┐ ┌────────────────┐
│ Nexus │ │ Harbor │
│ (Maven/ │ │ (Docker/OCI) │
│ npm/PyPI) │ │ +Trivy扫描 │
└─────┬──────┘ └────────┬───────┘
│ │
┌─────▼────────────────────────────────────▼───────┐
│ 制品安全验证层 │
│ Cosign签名验证 → SBOM检查 → 漏洞门禁 │
└─────┬────────────────────────────────────────────┘
│
┌─────▼──────┐
│ Deployment │
└────────────┘
# 检查磁盘
df -h /nexus-data
du -sh /nexus-data/blobs/default/
# 创建清理策略:保留7天的snapshot
curl -u admin:MyNewPass123! \
-X POST "http://localhost:8081/service/rest/v1/cleanup-policies" \
-H "Content-Type: application/json" \
-d '{"name":"cleanup-snapshots","format":"maven2","mode":"delete","criteria":{"releaseType":"SNAPSHOTS","lastDownloaded":"604800000"}}'
# 手动触发清理任务(在Nexus UI绑定策略到仓库后执行)
# 紧急清理blob:Nexus UI → System → Tasks → Admin - Compact blob store
# 检查Docker登录
cat ~/.docker/config.json | jq '.auths'
# 重新登录
docker logout harbor.mycompany.com
docker login harbor.mycompany.com -u admin -p HarborAdmin123!
# 检查项目存在
curl -u admin:HarborAdmin123! -k \
"https://harbor.mycompany.com/api/v2.0/projects/" | jq '.[].name'
# 创建项目
curl -u admin:HarborAdmin123! -k -X POST \
"https://harbor.mycompany.com/api/v2.0/projects" \
-H "Content-Type: application/json" \
-d '{"project_name":"devops","public":false}'
# 自签名证书信任
mkdir -p /etc/docker/certs.d/harbor.mycompany.com
cp /etc/harbor/cert/server.crt /etc/docker/certs.d/harbor.mycompany.com/ca.crt
systemctl restart docker
MAJOR.MINOR.PATCH
YYYY.MINOR.MICRO
branch-shortHash
掌握Nexus多格式仓库、Harbor镜像安全扫描、Cosign签名、SBOM生成——制品安全是供应链的根基。