Artifact Management
Learn artifact management with Nexus and JFrog Artifactory. Understand repository types, versioning, and integrating with CI/CD pipelines.
Learn artifact management with Nexus and JFrog Artifactory. Understand repository types, versioning, and integrating with CI/CD pipelines. This hands-on tutorial focuses on practical implementation of artifact management concepts.
Artifact Management
Artifact repositories store and manage build outputs (JARs, Docker images, npm packages) enabling versioning, sharing, and traceability across the DevOps pipeline.
Why Artifact Management?
┌────────────────────────────────────────────────────────────────┐
│ Artifact Repository │
├────────────────────────────────────────────────────────────────┤
│ │
│ Build Server ──> Store Artifact ──> Deploy to Staging │
│ │ │ │ │
│ │ ┌────┴────┐ │ │
│ │ │ Nexus │ │ │
│ └──────────>│ Artifactory│<──────────┘ │
│ │ DockerHub │ │
│ └───────────┘ │
│ │
│ Benefits: │
│ ✓ Version control of binaries │
│ ✓ Centralized storage │
│ ✓ Dependency caching │
│ ✓ Access control │
│ ✓ Audit trail │
└────────────────────────────────────────────────────────────────┘
Repository Types
By Format
| Format | Artifacts | Tools |
|---|---|---|
| Maven | JAR, WAR, POM | Nexus, Artifactory |
| npm | JavaScript packages | npm registry, Nexus |
| Docker | Container images | DockerHub, ECR, Nexus |
| PyPI | Python packages | PyPI, Artifactory |
| NuGet | .NET packages | NuGet Gallery, Nexus |
| Helm | Kubernetes charts | ChartMuseum, Artifactory |
By Purpose
- Hosted (Local): Store internal artifacts
- Proxy (Remote): Cache external repositories
- Group (Virtual): Combine multiple repositories
┌──────────────────────────────────────────────┐
│ Virtual Repository │
│ (Group: maven-public) │
├──────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Hosted │ │ Proxy │ │
│ │maven-releases│ │maven-central │ │
│ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ │
│ │ Hosted │ │
│ │maven-snapshots│ │
│ └──────────────┘ │
│ │
└──────────────────────────────────────────────┘
Sonatype Nexus
Installation
# Docker (Recommended)
docker run -d -p 8081:8081 --name nexus sonatype/nexus3
# Docker with volume
docker run -d \
-p 8081:8081 \
--name nexus \
-v nexus-data:/nexus-data \
sonatype/nexus3
# Default credentials
# admin / Password from: /nexus-data/admin.password
Repository Configuration
Maven Repositories:
-
maven-releases (Hosted)
- Version policy: Release
- Deployment policy: Disable redeploy
-
maven-snapshots (Hosted)
- Version policy: Snapshot
- Allow redeploy
-
maven-central (Proxy)
- Remote URL: https://repo1.maven.org/maven2/
- Cache enabled
-
maven-public (Group)
- Includes: maven-releases, maven-snapshots, maven-central
Maven Integration
<!-- pom.xml -->
<distributionManagement>
<repository>
<id>nexus-releases</id>
<url>http://nexus:8081/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>nexus-snapshots</id>
<url>http://nexus:8081/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
<!-- ~/.m2/settings.xml -->
<settings>
<servers>
<server>
<id>nexus-releases</id>
<username>admin</username>
<password>{your-password}</password>
</server>
<server>
<id>nexus-snapshots</id>
<username>admin</username>
<password>{your-password}</password>
</server>
</servers>
<mirrors>
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://nexus:8081/repository/maven-public/</url>
</mirror>
</mirrors>
</settings>
# Deploy to Nexus
mvn clean deploy
# Deploy skip tests
mvn clean deploy -DskipTests
npm Integration
# Configure npm registry
npm config set registry http://nexus:8081/repository/npm-group/
# Or use .npmrc
echo "registry=http://nexus:8081/repository/npm-group/" > .npmrc
# Authenticate
npm login --registry=http://nexus:8081/repository/npm-hosted/
# Publish
npm publish --registry=http://nexus:8081/repository/npm-hosted/
Docker Integration
# Configure Docker daemon (/etc/docker/daemon.json)
{
"insecure-registries": ["nexus:8082"]
}
# Login
docker login nexus:8082
# Tag image
docker tag myapp:1.0 nexus:8082/repository/docker-hosted/myapp:1.0
# Push
docker push nexus:8082/repository/docker-hosted/myapp:1.0
# Pull
docker pull nexus:8082/repository/docker-hosted/myapp:1.0
JFrog Artifactory
Installation
# Docker
docker run -d --name artifactory \
-p 8082:8082 -p 8081:8081 \
-v artifactory-data:/var/opt/jfrog/artifactory \
docker.bintray.io/jfrog/artifactory-oss:latest
# Default URL: http://localhost:8082
# Default credentials: admin / password
Repository Structure
Default Repositories:
libs-release-local- Release artifactslibs-snapshot-local- Snapshot artifactslibs-release- Virtual for releaseslibs-snapshot- Virtual for snapshotsjcenter- Proxy for JCenterremote-repos- Group for remote repos
Maven Integration
<!-- settings.xml -->
<settings>
<profiles>
<profile>
<repositories>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>libs-release</name>
<url>http://artifactory:8082/artifactory/libs-release</url>
</repository>
</repositories>
</profile>
</profiles>
<servers>
<server>
<username>${security.getCurrentUsername()}</username>
<password>${security.getEscapedEncryptedPassword()}</password>
<id>central</id>
</server>
</servers>
</settings>
REST API Examples
# Upload artifact
curl -u admin:password \
-X PUT \
-T myapp-1.0.jar \
"http://artifactory:8082/artifactory/libs-release-local/com/example/myapp/1.0/"
# Download artifact
curl -u admin:password \
-O \
"http://artifactory:8082/artifactory/libs-release-local/com/example/myapp/1.0/myapp-1.0.jar"
# Delete artifact
curl -u admin:password \
-X DELETE \
"http://artifactory:8082/artifactory/libs-release-local/com/example/myapp/1.0/myapp-1.0.jar"
# Search artifacts
curl -u admin:password \
"http://artifactory:8082/artifactory/api/search/gavc?g=com.example&a=myapp&v=1.0"
CI/CD Integration
Jenkins Pipeline with Nexus
pipeline {
agent any
environment {
NEXUS_URL = 'http://nexus:8081'
NEXUS_REPO = 'maven-releases'
}
stages {
stage('Build') {
steps {
sh 'mvn clean package'
}
}
stage('Upload to Nexus') {
steps {
nexusArtifactUploader(
nexusVersion: 'nexus3',
protocol: 'http',
nexusUrl: "${NEXUS_URL}",
groupId: 'com.example',
version: "${BUILD_NUMBER}",
repository: "${NEXUS_REPO}",
credentialsId: 'nexus-credentials',
artifacts: [
[artifactId: 'myapp',
classifier: '',
file: 'target/myapp.jar',
type: 'jar']
]
)
}
}
stage('Deploy') {
steps {
sh """
curl -o app.jar \
${NEXUS_URL}/repository/${NEXUS_REPO}/com/example/myapp/${BUILD_NUMBER}/myapp-${BUILD_NUMBER}.jar
# Deploy to server
"""
}
}
}
}
GitHub Actions with Artifactory
name: Build and Deploy
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Build
run: mvn clean package
- name: Upload to Artifactory
run: |
curl -u ${{ secrets.ARTIFACTORY_USER }}:${{ secrets.ARTIFACTORY_PASS }} \
-X PUT \
-T target/*.jar \
"${{ secrets.ARTIFACTORY_URL }}/libs-release-local/com/example/myapp/${{ github.run_number }}/"
Best Practices
Versioning Strategy
Semantic Versioning: MAJOR.MINOR.PATCH
1.0.0 - Initial release
1.1.0 - New features (backward compatible)
1.1.1 - Bug fixes
2.0.0 - Breaking changes
Snapshots: 1.0.0-SNAPSHOT (development builds)
Releases: 1.0.0 (stable builds)
Cleanup Policies
// Nexus Cleanup Policy
if (component.name().startsWith("com.example")) {
// Keep last 10 versions
return component.versions().size() > 10
}
Security
- Use separate repositories for releases and snapshots
- Disable anonymous access
- Enable SSL/TLS for production
- Implement cleanup policies
- Regular backups
- Use API keys for CI/CD
Quiz
Quiz
Question 1 of 5What is the purpose of a 'proxy' repository in Nexus/Artifactory?
Next Steps
Now let's dive into CI/CD pipelines—the automation engine of DevOps.