artifact-management

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Artifact Management

制品管理

Overview

概述

Implement comprehensive artifact management strategies for storing, versioning, and distributing built binaries, Docker images, and packages across environments.
实施全面的制品管理策略,用于在不同环境中存储、版本控制和分发构建好的二进制文件、Docker镜像和包。

When to Use

适用场景

  • Docker image registry management
  • Package publication and versioning
  • Build artifact storage and retrieval
  • Container image optimization
  • Artifact retention policies
  • Multi-registry distribution
  • Dependency caching
  • Docker镜像仓库管理
  • 包发布与版本控制
  • 构建产物的存储与检索
  • 容器镜像优化
  • 制品保留策略
  • 多仓库分发
  • 依赖缓存

Implementation Examples

实现示例

1. Docker Registry Configuration

1. Docker Registry配置

dockerfile
undefined
dockerfile
undefined

Dockerfile with multi-stage build for optimization

Dockerfile with multi-stage build for optimization

FROM node:18-alpine AS dependencies WORKDIR /app COPY package*.json ./ RUN npm ci --only=production
FROM node:18-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build
FROM node:18-alpine AS runtime WORKDIR /app COPY --from=dependencies /app/node_modules ./node_modules COPY --from=builder /app/dist ./dist COPY package*.json ./
EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3
CMD node healthcheck.js
CMD ["node", "dist/server.js"]
LABEL org.opencontainers.image.version="1.0.0"
org.opencontainers.image.description="Production application"
org.opencontainers.image.authors="DevOps Team"
undefined
FROM node:18-alpine AS dependencies WORKDIR /app COPY package*.json ./ RUN npm ci --only=production
FROM node:18-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build
FROM node:18-alpine AS runtime WORKDIR /app COPY --from=dependencies /app/node_modules ./node_modules COPY --from=builder /app/dist ./dist COPY package*.json ./
EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3
CMD node healthcheck.js
CMD ["node", "dist/server.js"]
LABEL org.opencontainers.image.version="1.0.0"
org.opencontainers.image.description="Production application"
org.opencontainers.image.authors="DevOps Team"
undefined

2. GitHub Container Registry (GHCR) Push

2. GitHub容器注册表(GHCR)推送

yaml
undefined
yaml
undefined

.github/workflows/publish-image.yml

.github/workflows/publish-image.yml

name: Publish to GHCR
on: push: tags: ['v*'] branches: [main]
env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }}
jobs: publish: runs-on: ubuntu-latest permissions: contents: read packages: write
steps:
  - uses: actions/checkout@v3

  - name: Set up Docker Buildx
    uses: docker/setup-buildx-action@v2

  - name: Log in to registry
    uses: docker/login-action@v2
    with:
      registry: ${{ env.REGISTRY }}
      username: ${{ github.actor }}
      password: ${{ secrets.GITHUB_TOKEN }}

  - name: Extract metadata
    id: meta
    uses: docker/metadata-action@v4
    with:
      images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
      tags: |
        type=ref,event=branch
        type=semver,pattern={{version}}
        type=semver,pattern={{major}}.{{minor}}
        type=sha

  - name: Build and push
    uses: docker/build-push-action@v4
    with:
      context: .
      file: ./Dockerfile.prod
      push: true
      tags: ${{ steps.meta.outputs.tags }}
      labels: ${{ steps.meta.outputs.labels }}
      cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache
      cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max
undefined
name: Publish to GHCR
on: push: tags: ['v*'] branches: [main]
env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }}
jobs: publish: runs-on: ubuntu-latest permissions: contents: read packages: write
steps:
  - uses: actions/checkout@v3

  - name: Set up Docker Buildx
    uses: docker/setup-buildx-action@v2

  - name: Log in to registry
    uses: docker/login-action@v2
    with:
      registry: ${{ env.REGISTRY }}
      username: ${{ github.actor }}
      password: ${{ secrets.GITHUB_TOKEN }}

  - name: Extract metadata
    id: meta
    uses: docker/metadata-action@v4
    with:
      images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
      tags: |
        type=ref,event=branch
        type=semver,pattern={{version}}
        type=semver,pattern={{major}}.{{minor}}
        type=sha

  - name: Build and push
    uses: docker/build-push-action@v4
    with:
      context: .
      file: ./Dockerfile.prod
      push: true
      tags: ${{ steps.meta.outputs.tags }}
      labels: ${{ steps.meta.outputs.labels }}
      cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache
      cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max
undefined

3. npm Package Publishing

3. npm包发布

json
{
  "name": "@myorg/awesome-library",
  "version": "1.2.3",
  "description": "Awesome library for developers",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "files": [
    "dist",
    "README.md",
    "LICENSE"
  ],
  "publishConfig": {
    "registry": "https://npm.pkg.github.com",
    "access": "public"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/myorg/awesome-library.git"
  },
  "scripts": {
    "prepublishOnly": "npm run build && npm run test",
    "prepack": "npm run build"
  }
}
json
{
  "name": "@myorg/awesome-library",
  "version": "1.2.3",
  "description": "Awesome library for developers",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "files": [
    "dist",
    "README.md",
    "LICENSE"
  ],
  "publishConfig": {
    "registry": "https://npm.pkg.github.com",
    "access": "public"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/myorg/awesome-library.git"
  },
  "scripts": {
    "prepublishOnly": "npm run build && npm run test",
    "prepack": "npm run build"
  }
}

4. Artifact Retention Policy

4. 制品保留策略

yaml
undefined
yaml
undefined

.github/workflows/cleanup-artifacts.yml

.github/workflows/cleanup-artifacts.yml

name: Cleanup Old Artifacts
on: schedule: - cron: '0 2 * * *' # Daily at 2 AM workflow_dispatch:
jobs: cleanup: runs-on: ubuntu-latest steps: - name: Delete artifacts older than 30 days uses: geekyeggo/delete-artifact@v2 with: name: '*' minCreatedTime: 30d failOnError: false
undefined
name: Cleanup Old Artifacts
on: schedule: - cron: '0 2 * * *' # Daily at 2 AM workflow_dispatch:
jobs: cleanup: runs-on: ubuntu-latest steps: - name: Delete artifacts older than 30 days uses: geekyeggo/delete-artifact@v2 with: name: '*' minCreatedTime: 30d failOnError: false
undefined

5. Artifact Versioning

5. 制品版本控制

bash
#!/bin/bash
bash
#!/bin/bash

artifact-version.sh

artifact-version.sh

BUILD_DATE=$(date -u +'%Y%m%d') GIT_HASH=$(git rev-parse --short HEAD) VERSION=$(grep '"version"' package.json | sed 's/."version": "([^"])".*/\1/')
BUILD_DATE=$(date -u +'%Y%m%d') GIT_HASH=$(git rev-parse --short HEAD) VERSION=$(grep '"version"' package.json | sed 's/."version": "([^"])".*/\1/')

Full version tag

Full version tag

FULL_VERSION="${VERSION}-${BUILD_DATE}.${GIT_HASH}"
FULL_VERSION="${VERSION}-${BUILD_DATE}.${GIT_HASH}"

Create artifact with version

Create artifact with version

docker build -t myapp:${FULL_VERSION} . docker tag myapp:${FULL_VERSION} myapp:latest
echo "Built artifact version: ${FULL_VERSION}"
undefined
docker build -t myapp:${FULL_VERSION} . docker tag myapp:${FULL_VERSION} myapp:latest
echo "Built artifact version: ${FULL_VERSION}"
undefined

10. GitLab Package Registry

10. GitLab包注册表

yaml
undefined
yaml
undefined

.gitlab-ci.yml

.gitlab-ci.yml

publish-package: stage: publish script: - npm config set @myorg:registry https://gitlab.example.com/api/v4/packages/npm/ - npm config set '//gitlab.example.com/api/v4/packages/npm/:_authToken' "${CI_JOB_TOKEN}" - npm publish only: - tags
undefined
publish-package: stage: publish script: - npm config set @myorg:registry https://gitlab.example.com/api/v4/packages/npm/ - npm config set '//gitlab.example.com/api/v4/packages/npm/:_authToken' "${CI_JOB_TOKEN}" - npm publish only: - tags
undefined

Best Practices

最佳实践

✅ DO

✅ 建议

  • Use semantic versioning for artifacts
  • Implement image scanning before deployment
  • Set retention policies for old artifacts
  • Use multi-stage builds for Docker images
  • Sign and verify artifacts
  • Implement artifact immutability
  • Document artifact metadata
  • Use specific base image versions
  • Implement vulnerability scanning
  • Cache layers aggressively
  • Tag images with commit SHA
  • Compress artifacts for storage
  • 对制品使用语义化版本控制
  • 在部署前实施镜像扫描
  • 为旧制品设置保留策略
  • 对Docker镜像使用多阶段构建
  • 签名并验证制品
  • 实现制品不可变性
  • 记录制品元数据
  • 使用特定的基础镜像版本
  • 实施漏洞扫描
  • 积极缓存镜像层
  • 用提交SHA标记镜像
  • 压缩制品以节省存储空间

❌ DON'T

❌ 避免

  • Use
    latest
    tag as sole identifier
  • Store secrets in artifacts
  • Push artifacts without scanning
  • Use untrusted base images
  • Skip artifact verification
  • Overwrite published artifacts
  • Mix binary and source artifacts
  • Ignore image layer optimization
  • Store build logs with sensitive data
  • 仅使用
    latest
    标签作为唯一标识符
  • 在制品中存储密钥
  • 未扫描就推送制品
  • 使用不可信的基础镜像
  • 跳过制品验证
  • 覆盖已发布的制品
  • 混合二进制制品和源制品
  • 忽略镜像层优化
  • 存储包含敏感数据的构建日志

Artifact Storage Standards

制品存储标准

bash
undefined
bash
undefined

Naming convention

Naming convention

{registry}/{org}/{repo}/{service}:{version}-{build}-{commit}
{registry}/{org}/{repo}/{service}:{version}-{build}-{commit}

Examples

Examples

docker.io/myorg/web-app:1.2.3-123-abc1234 ghcr.io/myorg/api-service:2.0.0-456-def5678 artifactory.example.com/releases/core:3.1.0-789-ghi9012
undefined
docker.io/myorg/web-app:1.2.3-123-abc1234 ghcr.io/myorg/api-service:2.0.0-456-def5678 artifactory.example.com/releases/core:3.1.0-789-ghi9012
undefined

Resources

参考资源