Sonatype Nexus Repository Manager
Kirish
Tasavvur qiling: sizning jamoangiz har kuni loyihani build qilganda Maven Central, NuGet Gallery yoki Docker Hubdan yuzlab paketlarni qayta-qayta yuklab oladi. Har bir build internertga so'rov yuboradi, vaqt ketadi, tarmoq yuklanadi. Agar internet sekin bo'lsa yoki tashqi repository vaqtincha ishlamay qolsa — butun CI/CD pipeline to'xtab qoladi.
Aynan shu muammoni hal qilish uchun Sonatype Nexus Repository Manager ishlatiladi.
Nexus — bu markazlashtirilgan artifakt menejeri bo'lib, u quyidagi vazifalarni bajaradi:
- Tashqi paketlarni keshlash (Proxy) — Maven Central, NuGet, PyPI, Docker Hub kabi tashqi repositorylardan yuklab olingan paketlarni local serverda saqlaydi. Keyingi safar xuddi shu paket kerak bo'lganda, internet o'rniga Nexusdan olinadi.
- Ichki paketlarni saqlash (Hosted) — kompaniyaning o'ziga xos kutubxonalari va artifaktlarini xavfsiz saqlaydi.
- Bir nechta repositoryni birlashtirish (Group) — Proxy va Hosted repositorylarni bitta URL ostida birlashtiradi, loyihalaringiz faqat bitta manzilni bilsa kifoya.
Nexus Java (Maven, Gradle), .NET (NuGet), Python (PyPI), Docker, Node.js (NPM), Go, Helm, Cargo va boshqa ko'plab texnologiyalarni qo'llab-quvvatlaydi.
Nexus ikki versiyada mavjud: Nexus OSS (opensource, bepul) va Nexus Pro (pullik, qo'shimcha funksiyalar bilan). Ushbu qo'llanma Nexus OSS bilan ishlashga mo'ljallangan — u ko'pchilik hollarda yetarli.
Qisqacha tarix: Nexus 2007-yilda Sonatype Inc. tomonidan yaratilgan. Dastlab faqat Maven uchun mo'ljallangan bo'lsa, bugungi kunda u deyarli barcha paket menejerlarni qo'llab-quvvatlaydigan universal yechimga aylangan.
Bu qo'llanmada biz Nexusni Docker yordamida o'rnatamiz, domen ulaymiz, repository turlarini tushunib olamiz va oxirida Maven hamda NuGet loyihalarini CI/CD pipeline ichida Nexus bilan integratsiya qilamiz.
Nexus o'rnatish
Nexusni Docker yordamida ishga tushiramiz. O'rnatishning ikkita usulini ko'rib chiqamiz: manual va Ansible orqali avtomatlashtirilgan.
Minimum server talablari
| OS | RAM | CPU | Xotira | Static IP |
|---|---|---|---|---|
| Ubuntu 20.04+ yoki Rocky Linux 8+ | 8GB | 4 core | 80GB | Ha kerak |
Nexus juda ko'p metadatalar bilan ishlaydi, shuning uchun RAM va disk hajmi muhim. 4GB RAM bilan ishga tushsa ham, real ishlatishda sekinlashadi.
Docker o'rnatilmagan bo'lsa, avval uni o'rnatib oling — Docker o'rnatish qo'llanmasi (opens in a new tab)
- Manual
- Ansible
Manual o'rnatish
1-> Nexus o'z ma'lumotlarini (repositorylar, konfiguratsiyalar, keshlangan paketlar) /nexus-data papkasida saqlaydi. Docker container o'chirilsa yoki restart bo'lsa, ichidagi ma'lumotlar yo'qoladi. Shuning uchun biz bu papkani host serverga mount qilamiz:
sudo mkdir -p /mnt/nexus/nexus-data
sudo chown -R 200 /mnt/nexus/nexus-dataNima uchun chown 200? Nexus container ichida nexus foydalanuvchisi UID 200 bilan ishlaydi. Agar papka egaligi to'g'ri bo'lmasa, Nexus yozish huquqi yo'qligi sababli ishga tushmaydi.
2-> Nexusni Docker bilan ishga tushiramiz:
docker run -d \
-p 8081:8081 \
--name nexus \
--restart=always \
-v /mnt/nexus/nexus-data:/nexus-data \
sonatype/nexus3Bu yerda:
-p 8081:8081— Nexus web interfeysi uchun port--restart=always— server yoki Docker restart bo'lganda Nexus avtomatik qayta ishga tushadi-v /mnt/nexus/nexus-data:/nexus-data— ma'lumotlar host serverda saqlanadi
3-> Nexus birinchi marta ishga tushganda avtomatik admin parol generatsiya qiladi. Uni olish uchun:
docker exec -it nexus cat /nexus-data/admin.passwordBu parol faqat birinchi kirish uchun! Nexus sizdan uni o'zgartirishni talab qiladi. Parolni xavfsiz joyda saqlang.
Birinchi kirish
Nexus o'rnatilgandan so'ng, brauzerda http://server_ip:8081 manzilini oching.
Yuqori o'ng burchakdagi Sign in tugmasini bosing:
admin login va oldingi bosqichda olgan parol bilan kiring:
Nexus sizdan default parolni o'zgartirishni talab qiladi — yangi kuchli parol kiriting:
Keyingi qadamda anonymous access sozlamasini tanlaymiz. Agar faqat autentifikatsiya qilingan foydalanuvchilar kirishi kerak bo'lsa, "Disable anonymous access"ni tanlang:
Tabriklaymiz! Nexus tayyor:
Nexusga domen ulash
Production muhitda Nexusni IP:port orqali emas, balki domen va HTTPS orqali ishlatish kerak. Bu xavfsizlik va qulaylik uchun muhim — ayniqsa CI/CD pipeline'larda credential'lar shifrlanmagan holda yuborilmasligi uchun.
Biz NGINX reverse proxy va Let's Encrypt orqali bepul SSL sertifikat olamiz.
- Debian Based
- Red Hat Based
1-> NGINX va Certbot o'rnatamiz:
sudo apt update
sudo apt install nginx certbot python3-certbot-nginx -y2-> DNS provayderingizda A record yarating — domenni serveringiz IP manziliga yo'naltiring. Masalan, nexus.helm.uz subdomenini serverga ulash:
3-> NGINX konfiguratsiya faylini yaratamiz:
sudo nano /etc/nginx/sites-available/nexus.helm.uzQuyidagi konfiguratsiyani yozing:
server {
listen 80;
client_max_body_size 100M;
server_name nexus.helm.uz;
location / {
proxy_pass http://localhost:8081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}client_max_body_size 100M — bu NGINX orqali yuklanadigan fayllarning maksimal hajmini belgilaydi. Nexusga katta artifaktlar yuklash uchun bu qiymatni oshirish kerak bo'lishi mumkin. Agar 413 Request Entity Too Large xatosi chiqsa, bu qiymatni ko'paytiring.
4-> Konfiguratsiyani faollashtirish uchun sites-enabledga symbolic link yaratamiz:
sudo ln -s /etc/nginx/sites-available/nexus.helm.uz /etc/nginx/sites-enabled/5-> NGINXni restart qilamiz:
sudo systemctl restart nginx6-> Let's Encrypt SSL sertifikatini olamiz:
sudo certbotCertbot sizdan email so'raydi va Terms of Serviceni qabul qilishingizni kutadi — y bosing:
Keyin domenlar ro'yxatidan keraklisini tanlang:
Sertifikat olingandan keyin NGINXni qayta ishga tushiring:
sudo systemctl restart nginxEndi brauzerda https://nexus.helm.uz (opens in a new tab) ochsangiz, Nexus HTTPS bilan ishlayotganini ko'rasiz:
Nexus bilan tanishuv
Keling, Nexusning asosiy tushunchalari va interfeysini ko'rib chiqamiz.
Qo'llab-quvvatlanadigan texnologiyalar
Nexus deyarli barcha mashhur paket menejerlarni qo'llab-quvvatlaydi:
APT, Cargo, Bower, CocoaPods, Composer, Conan, Conda, Docker, Git LFS, Go, Helm, Hugging Face, Maven, npm, NuGet, p2, PyPI, R, Raw, RubyGems, Yum (RPM)
Sonatype kompaniyasining Nexusdan tashqari Repository Firewall (zararli paketlarni bloklash), Lifecycle (open-source xavfsizlik nazorati) va SBOM (dasturiy ta'minot tarkibini kuzatish) kabi mahsulotlari ham mavjud.
Interfeys bilan tanishish
Nexusga kirganda asosiy sahifa ochiladi:
Server Administration and Configuration — bu yerda Nexusning barcha sozlamalari joylashgan:
Blob Stores — Nexus fayllarni fizik ravishda saqlaydigan joy. Default holatda default nomli bitta blob store mavjud. Katta tashkilotlarda har bir repository turi uchun alohida blob store yaratish tavsiya etiladi:
Repositories — bu yerda barcha repositorylarni ko'rishimiz mumkin. Nexus default holda Maven va NuGet uchun tayyor repositorylar bilan keladi:
Proxy sozlamalari
Agar kompaniyangizda internet proxy orqali chiqilsa, Nexusga ham proxy sozlamalarini kiritish kerak. Settings → System → HTTP bo'limiga o'ting:
HTTP Proxy uchun Enable HTTP Proxyni belgilab, proxy server manzili va portini kiriting:
HTTPS Proxy uchun ham xuddi shunday. Agar proxy autentifikatsiya talab qilsa, Enable HTTPS Proxy Authenticationni belgilab, login va parolni kiriting:
No Proxy Hosts — bu yerda proxy orqali chiqish shart bo'lmagan local manzillarni yozish mumkin (masalan, ichki servislar):
Repositorylar bilan ishlash
Nexusdagi eng muhim tushuncha — repository turlari. Ularni to'g'ri tushunish Nexusdan samarali foydalanish uchun juda muhim.
Proxy Repository — "Aqlli kesh"
Proxy repository tashqi (remote) repositorylarni local serverda keshlaydi.
Hayotiy misol: Tasavvur qiling, siz har kuni do'konga non olishga borasiz. Bir kuni eshik oldiga mini-do'kon ochildi — siz endi uzoqqa bormasdan, o'sha yerdan olasiz. Proxy repository ham xuddi shunday ishlaydi:
- Loyihangiz
spring-boot-starterpaketini so'raydi - Nexus avval o'zining keshida qidiradi
- Agar topilmasa — Maven Centraldan yuklab olib, keshda saqlaydi
- Keyingi safar xuddi shu paket so'ralganda — internetga chiqmasdan keshdan beradi
Natija: Build tezligi oshadi, internet trafigi kamayadi, tashqi repository ishlamay qolsa ham loyihangiz build bo'laveradi.
Nexusda default maven-central proxy repository mavjud — u https://repo1.maven.org/maven2/ (opens in a new tab) manzilidan paketlarni oladi:
Hosted Repository — "Ichki ombor"
Hosted repository — kompaniyaning o'z paketlarini saqlash uchun. Bu tashqi dunyoga aloqasi yo'q, faqat sizning tashkilotingiz ichida ishlaydi.
Qachon kerak bo'ladi?
- Kompaniyada umumiy kutubxona (shared library) yozilgan va uni barcha jamoalar ishlatishi kerak
- Loyihaning
SNAPSHOTyokiRELEASEversiyalarini markazlashtirilgan joyda saqlash kerak mvn deployyokidotnet nuget pushbuyruqlari bilan artifaktlarni yuklash uchun
Nexusda default maven-releases va maven-snapshots hosted repositorylar mavjud.
Group Repository — "Yagona kirish nuqtasi"
Group repository — bir nechta repositoryni bitta URL ostida birlashtiradi.
Hayotiy misol: Savdo markazida 50 ta do'kon bor, lekin siz bitta eshikdan kirasiz. Group repository ham shunday — loyihangiz bitta URL biladi, lekin uning orqasida bir nechta repository ishlaydi.
Masalan, maven-public group repository o'z ichiga oladi:
- maven-central (proxy) — tashqi paketlar
- maven-releases (hosted) — kompaniyaning release paketlari
- maven-snapshots (hosted) — kompaniyaning snapshot paketlari
Loyihangiz faqat maven-public URLni ko'rsatadi — qolganini Nexus o'zi hal qiladi.
maven-public ichidagi repositorylar:
Xuddi shunday nuget-group ham nuget-hosted va nuget.org-proxy repositorylarni birlashtiradi:
nuget.org-proxy tashqi https://api.nuget.org/v3/index.json (opens in a new tab) manzilidan NuGet paketlarni keshlaydi:
Xulosa: Nexusda default holda faqat Maven va NuGet uchun repositorylar mavjud. Docker, PyPI, Go, Cargo, Helm va boshqalar uchun repositorylarni o'zingiz yaratishingiz kerak — bu Settings → Repositories → Create Repository orqali amalga oshiriladi.
Nexus Integratsiyasi
Endi eng qiziqarli qismga o'tamiz — Nexusni real loyihalarga va CI/CD pipeline'larga ulash. Biz Java (Maven) va .NET (NuGet) integratsiyalarini ko'rib chiqamiz.
Integratsiya nima beradi?
- Build tezligi oshadi — paketlar local Nexusdan olinadi, internet kutilmaydi
- Barqarorlik — tashqi repository ishlamay qolsa ham build ishlaydi
- Xavfsizlik — barcha paketlar Nexus orqali o'tadi, nazorat qilish oson
- Trafik tejash — bir xil paket faqat bir marta internetdan yuklanadi
Java Maven
Platformamizda Java Spring Boot Deployment: Gitlab CI va Github Actions (opens in a new tab) amaliyotida biz Spring Boot Maven loyihani CI/CD bilan ishga tushirishni ko'rib chiqgandik. Endi o'sha loyihaga Nexus integratsiyasini qo'shamiz.
Ushbu bo'limda ishlatiladigan loyihalar:
1-qadam: pom.xmlga repository qo'shish
Loyihangizning pom.xml fayliga quyidagi konfiguratsiyani qo'shing:
<repositories>
<repository>
<id>nexus</id>
<url>https://nexus.helm.uz/repository/maven-public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>nexus</id>
<url>https://nexus.helm.uz/repository/maven-public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>Bu yerda ikki bo'lim bor:
<repositories>— Mavenga dependencylarni qayerdan yuklab olishni aytadi.maven-publicgroup repository orqali ham tashqi (Maven Central), ham ichki paketlarni olish mumkin.<pluginRepositories>— Maven build jarayonida ishlatiladigan plaginlarni ham Nexus orqali yuklashni ta'minlaydi. Bu muhim, chunki Maven plaginlari (compiler, surefire, jar) ham tashqi repositorydan olinadi.
<id> qiymati (nexus) keyingi bosqichdagi settings.xml dagi server ID bilan bir xil bo'lishi shart — Maven autentifikatsiyani ID orqali moslashtiradi.
2-qadam: settings.xml yaratish
settings.xml — Maven'ning global konfiguratsiya fayli. Bu yerda autentifikatsiya, mirror va profil sozlamalari bo'ladi:
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">
<servers>
<server>
<id>nexus</id>
<username>${env.NEXUS_USER}</username>
<password>${env.NEXUS_PASSWORD}</password>
</server>
</servers>
<mirrors>
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>https://nexus.helm.uz/repository/maven-public/</url>
<layout>default</layout>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<repositories>
<repository>
<id>nexus</id>
<url>https://nexus.helm.uz/repository/maven-public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>nexus</activeProfile>
</activeProfiles>
</settings>Har bir bo'limni tushuntirib o'tamiz:
<servers> — Nexusga kirish uchun login va parol. ${env.NEXUS_USER} va ${env.NEXUS_PASSWORD} environment variable'lardan olinadi — bu CI/CD uchun xavfsiz usul, parollarni kodda saqlash shart emas.
<mirrors> — <mirrorOf>*</mirrorOf> degani "barcha repositorylar uchun Nexusni mirror sifatida ishlatilsin". Ya'ni Maven Central yoki boshqa tashqi repositoriyaga to'g'ridan-to'g'ri so'rov yuborish o'rniga, hamma narsa Nexus orqali o'tadi.
<profiles> va <activeProfiles> — nexus nomli profil yaratiladi va faollashtiriladi. Bu Maven har qanday mvn buyrug'ida Nexus repositorydan foydalanishini ta'minlaydi.
3-qadam: CI/CD environment variable'larni sozlash
NEXUS_USER va NEXUS_PASSWORD ni CI/CD platformangizga qo'shing:
Gitlab — Settings → CI/CD → Variables:
NEXUS_USER — Nexus foydalanuvchi nomi:
NEXUS_PASSWORD — Nexus paroli:
Github — Settings → Secrets → New repository secret:
NEXUS_USER:
NEXUS_PASSWORD:
Xavfsizlik masalasi: Nexus uchun alohida "read-only" foydalanuvchi yaratish tavsiya etiladi. admin parolni CI/CD'da ishlatmang — agar credential sizib chiqsa, buzg'unchi butun Nexusni boshqarishi mumkin.
4-qadam: Dockerfile'ni yangilash
settings.xmlni Docker build jarayonida Maven'ga tanishtrish uchun Dockerfile'ga quyidagi qatorni qo'shamiz:
COPY settings.xml /root/.m2/settings.xmlTo'liq Dockerfile:
FROM maven:3.9.5-eclipse-temurin-17-alpine AS builder
WORKDIR /app
COPY settings.xml /root/.m2/settings.xml
COPY pom.xml .
RUN mvn dependency:go-offline -B
COPY src ./src
RUN mvn package -DskipTests -B
FROM eclipse-temurin:17-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
RUN chown -R appuser:appgroup /app
USER appuser
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD wget --spider --quiet http://localhost:8080/actuator/health || exit 1
ENTRYPOINT ["java", "-jar", "app.jar"]mvn dependency:go-offline -B — bu buyruq barcha dependencylarni oldindan yuklab oladi. Docker layer caching tufayli, agar pom.xml o'zgarmasa, keyingi buildlarda bu qadam skiplab o'tiladi va build ancha tezlashadi.
5-qadam: CI/CD pipeline'ni yangilash
CI/CD pipeline'da settings.xml ichidagi placeholder'larni haqiqiy qiymatlar bilan almashtirishimiz kerak. Buning uchun sed buyrug'idan foydalanamiz.
Gitlab CI — before_script bo'limiga qo'shing:
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
- sed -i "s|\${env.NEXUS_USER}|${NEXUS_USER}|g" settings.xml
- sed -i "s|\${env.NEXUS_PASSWORD}|${NEXUS_PASSWORD}|g" settings.xmlTo'liq .gitlab-ci.yml:
stages:
- build_and_push
- deploy
variables:
IMAGE_NAME: waifulist
CONTAINER_NAME: waifulist
PORT: "8080:8080"
REPO_NAME: $CI_PROJECT_PATH
REGISTRY: "registry.gitlab.com"
SSH_HOST: $SERVER_IP
SSH_USER: $SERVER_USERNAME
SSH_KEY: $SSH_PRIVATE_KEY
SPRING_PROFILES_ACTIVE: dev
DEV_DATABASE_URL: $DEV_DATABASE_URL
DEV_DATABASE_USERNAME: $DEV_DATABASE_USERNAME
DEV_DATABASE_PASSWORD: $DEV_DATABASE_PASSWORD
build_and_push:
stage: build_and_push
image: docker:stable
services:
- docker:dind
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
- sed -i "s|\${env.NEXUS_USER}|${NEXUS_USER}|g" settings.xml
- sed -i "s|\${env.NEXUS_PASSWORD}|${NEXUS_PASSWORD}|g" settings.xml
script:
- docker build -t "$REGISTRY/$REPO_NAME/$IMAGE_NAME:$CI_COMMIT_SHA" .
- docker push "$REGISTRY/$REPO_NAME/$IMAGE_NAME:$CI_COMMIT_SHA"
deploy:
stage: deploy
image: alpine:latest
before_script:
- apk add --update --no-cache openssh-client
script:
- mkdir -p ~/.ssh
- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- ssh-keyscan -H $SSH_HOST >> ~/.ssh/known_hosts
- ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "echo "$CI_JOB_TOKEN" | docker login -u gitlab-ci-token --password-stdin $CI_REGISTRY"
- ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker pull $REGISTRY/$REPO_NAME/$IMAGE_NAME:$CI_COMMIT_SHA"
- ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker stop $CONTAINER_NAME || true"
- ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker rm $CONTAINER_NAME || true"
- ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no "$SSH_USER@$SSH_HOST" "docker run -d --name $CONTAINER_NAME --restart=always -p $PORT -e SPRING_PROFILES_ACTIVE=$SPRING_PROFILES_ACTIVE -e DEV_DATABASE_URL=$DEV_DATABASE_URL -e DEV_DATABASE_USERNAME=$DEV_DATABASE_USERNAME -e DEV_DATABASE_PASSWORD=$DEV_DATABASE_PASSWORD $REGISTRY/$REPO_NAME/$IMAGE_NAME:$CI_COMMIT_SHA"Github Actions — yangi step qo'shing:
- name: Replace Nexus Credentials in settings.xml
run: |
sed -i "s|\${env.NEXUS_USER}|${{ secrets.NEXUS_USER }}|g" settings.xml
sed -i "s|\${env.NEXUS_PASSWORD}|${{ secrets.NEXUS_PASSWORD }}|g" settings.xmlTo'liq .github/workflows/main.yml:
name: Github Actions CI/CD
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
env:
REPO_NAME: ${{ github.repository }}
CONTAINER_NAME: waifulist
REGISTRY: ghcr.io
SSH_HOST: ${{ secrets.SERVER_IP }}
SSH_USER: ${{ secrets.SERVER_USERNAME }}
SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
PORT: 8080:8080
SPRING_PROFILES_ACTIVE: dev
jobs:
build_and_push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Replace Nexus Credentials in settings.xml
run: |
sed -i "s|\${env.NEXUS_USER}|${{ secrets.NEXUS_USER }}|g" settings.xml
sed -i "s|\${env.NEXUS_PASSWORD}|${{ secrets.NEXUS_PASSWORD }}|g" settings.xml
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: "${{ env.REGISTRY }}/${{ env.REPO_NAME }}:${{ github.sha }}"
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.REPO_NAME }}:buildcache
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.REPO_NAME }}:buildcache,mode=max
deploy:
needs: build_and_push
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Executing remote SSH commands to deploy
uses: appleboy/ssh-action@master
with:
host: "${{ env.SSH_HOST }}"
username: "${{ env.SSH_USER }}"
key: "${{ env.SSH_KEY }}"
script: |
echo ${{ secrets.GITHUB_TOKEN }} | docker login -u ${{ github.actor }} --password-stdin ${{ env.REGISTRY }}
docker pull "${{ env.REGISTRY }}/${{ env.REPO_NAME }}:${{ github.sha }}"
docker stop "${{ env.CONTAINER_NAME }}" || true
docker rm "${{ env.CONTAINER_NAME }}" || true
docker run -d --name ${{ env.CONTAINER_NAME }} --restart=always -p ${{ env.PORT }} \
-e SPRING_PROFILES_ACTIVE=${{ env.SPRING_PROFILES_ACTIVE }} \
-e DEV_DATABASE_URL=${{ secrets.DEV_DATABASE_URL }} \
-e DEV_DATABASE_USERNAME=${{ secrets.DEV_DATABASE_USERNAME }} \
-e DEV_DATABASE_PASSWORD=${{ secrets.DEV_DATABASE_PASSWORD }} \
${{ env.REGISTRY }}/${{ env.REPO_NAME }}:${{ github.sha }}6-qadam: Natijani tekshirish
CI/CD pipeline ishga tushgandan keyin loglardan barcha paketlarning nexus.helm.uz orqali yuklanayotganini ko'rishingiz mumkin:
Gitlab CI natijasi:
Github Actions natijasi:
Nexus web interfeysida ham keshlangan paketlarni ko'rish mumkin:
maven-central repository'da saqlangan local paketlar:
Diqqat: Birinchi build odatdagidan sekinroq bo'lishi mumkin — chunki Nexus barcha paketlarni birinchi marta internetdan yuklab oladi va keshga saqlaydi. Keyingi buildlar esa ancha tez bo'ladi, chunki hamma narsa local keshdan olinadi.
.NET NuGet
.NET loyihalarida NuGet paket menejeri ishlatiladi. Nexus bilan integratsiya mantiqan Maven bilan bir xil — farqi faqat konfiguratsiya fayllarida.
Ushbu bo'limda Github Actions CI/CD (opens in a new tab) amaliyotida ishlatilgan .NET Core applicationni olamiz va unga Nexus integratsiyasini qo'shamiz.
Ushbu bo'limda ishlatiladigan loyihalar:
1-qadam: NuGet.Config yaratish
Loyiha root papkasida NuGet.Config faylini yaratamiz:
<configuration>
<packageSources>
<clear />
<add key="Nexus" value="https://nexus.helm.uz/repository/nuget-group/index.json" />
</packageSources>
<packageSourceCredentials>
<Nexus>
<add key="Username" value="__NEXUS_USER__" />
<add key="ClearTextPassword" value="__NEXUS_PASSWORD__" />
</Nexus>
</packageSourceCredentials>
</configuration>Bu yerda nima bo'lyapti:
<clear />— NuGet'ning default manbalarini (nuget.org) o'chiradi. Endi faqat Nexus orqali paketlar olinadi.nuget-group— Maven'dagimaven-publickabi, bu ham group repository bo'lib, o'z ichiganuget-hostedvanuget.org-proxyrepositorylarni oladi.__NEXUS_USER__va__NEXUS_PASSWORD__— bu placeholder'lar. CI/CD pipeline'da ular haqiqiy qiymatlar bilan almashtiriladi.
2-qadam: CI/CD environment variable'larni sozlash
Maven bo'limidagi 3-qadam bilan bir xil — NEXUS_USER va NEXUS_PASSWORDni CI/CD platformangizga qo'shing:
Gitlab — Settings → CI/CD → Variables:
NEXUS_USER:
NEXUS_PASSWORD:
Github — Settings → Secrets → New repository secret:
NEXUS_USER:
NEXUS_PASSWORD:
3-qadam: Dockerfile'ni yangilash
NuGet.Config faylini Docker build jarayonida .NET SDK'ga tanishtiramiz:
COPY NuGet.Config /root/.nuget/NuGet/NuGet.ConfigTo'liq Dockerfile:
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env
WORKDIR /app
COPY NuGet.Config /root/.nuget/NuGet/NuGet.Config
COPY . .
WORKDIR "/app/GitHub.Actions.API"
RUN dotnet publish "GitHub.Actions.API.csproj" -o /app/build -c Release
FROM mcr.microsoft.com/dotnet/aspnet:7.0
WORKDIR /app
ENV ASPNETCORE_ENVIRONMENT=Development
ENV TZ="Asia/Tashkent"
COPY --from=build-env /app/build .
ENTRYPOINT ["dotnet", "GitHub.Actions.API.dll", "--urls=http://0.0.0.0:4001"]4-qadam: CI/CD pipeline'ni yangilash
Gitlab CI — before_script bo'limiga placeholder almashtirishni qo'shamiz:
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- sed -i 's|__NEXUS_USER__|'"$NEXUS_USER"'|g' NuGet.Config
- sed -i 's|__NEXUS_PASSWORD__|'"$NEXUS_PASSWORD"'|g' NuGet.ConfigTo'liq .gitlab-ci.yml:
stages:
- build_and_push
- deploy
variables:
API_IMAGE_NAME: github-api
API_CONTAINER_NAME: github-api
UI_IMAGE_NAME: github-ui
UI_CONTAINER_NAME: github-ui
UI_PORT: "4000:4000"
API_PORT: "4001:4001"
REPO_NAME: $CI_PROJECT_PATH
REGISTRY: "registry.gitlab.com"
SSH_HOST: $SERVER_IP
SSH_USER: $SERVER_USERNAME
SSH_KEY: $SSH_PRIVATE_KEY
build_and_push:
stage: build_and_push
image: docker:stable
services:
- docker:dind
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- sed -i 's|__NEXUS_USER__|'"$NEXUS_USER"'|g' NuGet.Config
- sed -i 's|__NEXUS_PASSWORD__|'"$NEXUS_PASSWORD"'|g' NuGet.Config
script:
- docker build -t $REGISTRY/$REPO_NAME/$API_IMAGE_NAME:$CI_COMMIT_SHA -f ./API.Dockerfile .
- docker push $REGISTRY/$REPO_NAME/$API_IMAGE_NAME:$CI_COMMIT_SHA
- docker build -t $REGISTRY/$REPO_NAME/$UI_IMAGE_NAME:$CI_COMMIT_SHA -f ./UI.Dockerfile .
- docker push $REGISTRY/$REPO_NAME/$UI_IMAGE_NAME:$CI_COMMIT_SHA
deploy:
stage: deploy
image: alpine:latest
before_script:
- apk add --update --no-cache openssh-client
script:
- mkdir -p ~/.ssh
- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- ssh-keyscan -H $SSH_HOST >> ~/.ssh/known_hosts
- ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "echo "$CI_JOB_TOKEN" | docker login -u gitlab-ci-token --password-stdin $CI_REGISTRY"
- ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker pull $REGISTRY/$REPO_NAME/$API_IMAGE_NAME:$CI_COMMIT_SHA"
- ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker pull $REGISTRY/$REPO_NAME/$UI_IMAGE_NAME:$CI_COMMIT_SHA"
- ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker stop $UI_CONTAINER_NAME || true"
- ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker stop $API_CONTAINER_NAME || true"
- ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker rm $UI_CONTAINER_NAME || true"
- ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker rm $API_CONTAINER_NAME || true"
- ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker run -d --name $API_CONTAINER_NAME --restart=always -p $API_PORT $REGISTRY/$REPO_NAME/$API_IMAGE_NAME:$CI_COMMIT_SHA"
- ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker run -d --name $UI_CONTAINER_NAME --restart=always -p $UI_PORT $REGISTRY/$REPO_NAME/$UI_IMAGE_NAME:$CI_COMMIT_SHA"Github Actions — yangi step qo'shing:
- name: Replace Nexus Credentials in NuGet.Config
run: |
sed -i "s|__NEXUS_USER__|${{ secrets.NEXUS_USER }}|g" NuGet.Config
sed -i "s|__NEXUS_PASSWORD__|${{ secrets.NEXUS_PASSWORD }}|g" NuGet.ConfigTo'liq .github/workflows/ci-cd.yml:
name: Docker CI/CD
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
env:
API_IMAGE_NAME: github-api
API_CONTAINER_NAME: github-api
UI_IMAGE_NAME: github-ui
UI_CONTAINER_NAME: github-ui
UI_PORT: 4000:4000
API_PORT: 4001:4001
REPO_NAME: ${{ github.repository }}
REGISTRY: ghcr.io
SSH_HOST: ${{ secrets.SERVER_IP }}
SSH_USER: ${{ secrets.SERVER_USERNAME }}
SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
jobs:
build_and_push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Replace Nexus Credentials in NuGet.Config
run: |
sed -i "s|__NEXUS_USER__|${{ secrets.NEXUS_USER }}|g" NuGet.Config
sed -i "s|__NEXUS_PASSWORD__|${{ secrets.NEXUS_PASSWORD }}|g" NuGet.Config
- name: Build and push API Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./API.Dockerfile
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO_NAME}}/${{ env.API_IMAGE_NAME }}:${{ github.sha }}
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.REPO_NAME}}/${{ env.API_IMAGE_NAME }}:buildcache
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.REPO_NAME}}/${{ env.API_IMAGE_NAME }}:buildcache,mode=max
- name: Build and push UI Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./UI.Dockerfile
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO_NAME}}/${{ env.UI_IMAGE_NAME }}:${{ github.sha }}
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.REPO_NAME}}/${{ env.UI_IMAGE_NAME }}:buildcache
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.REPO_NAME}}/${{ env.UI_IMAGE_NAME }}:buildcache,mode=max
deploy:
needs: build_and_push
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Executing remote SSH commands to deploy
uses: appleboy/ssh-action@master
with:
host: "${{ env.SSH_HOST }}"
username: "${{ env.SSH_USER }}"
key: "${{ env.SSH_KEY }}"
script: |
echo ${{ secrets.GITHUB_TOKEN }} | docker login -u ${{ github.actor }} --password-stdin ${{ env.REGISTRY }}
docker pull "${{ env.REGISTRY }}/${{ env.REPO_NAME}}/${{ env.API_IMAGE_NAME }}:${{ github.sha }}"
docker pull "${{ env.REGISTRY }}/${{ env.REPO_NAME}}/${{ env.UI_IMAGE_NAME }}:${{ github.sha }}"
docker stop "${{ env.UI_CONTAINER_NAME }}" || true
docker stop "${{ env.API_CONTAINER_NAME }}" || true
docker rm "${{ env.UI_CONTAINER_NAME }}" || true
docker rm "${{ env.API_CONTAINER_NAME }}" || true
docker run -d --name "${{ env.API_CONTAINER_NAME }}" --restart=always -p "${{ env.API_PORT }}" "${{ env.REGISTRY }}/${{ env.REPO_NAME}}/${{ env.API_IMAGE_NAME }}:${{ github.sha }}"
docker run -d --name "${{ env.UI_CONTAINER_NAME }}" --restart=always -p "${{ env.UI_PORT }}" "${{ env.REGISTRY }}/${{ env.REPO_NAME}}/${{ env.UI_IMAGE_NAME }}:${{ github.sha }}"5-qadam: Natijani tekshirish
Github Actions muvaffaqiyatli tugagandan keyin:
Nexus interfeysida keshlangan NuGet paketlarni ko'rish mumkin:
nuget-group repository ichidagi paketlar:
Xulosa
Ushbu qo'llanmada biz:
- Nexusni Docker yordamida o'rnatdik (manual va Ansible orqali)
- Domen va HTTPS uladik (NGINX + Let's Encrypt)
- Repository turlarini (Proxy, Hosted, Group) tushunib oldik
- Maven va NuGet loyihalarini Nexus bilan integratsiya qildik
- Gitlab CI va Github Actions pipeline'larida Nexusdan foydalanishni sozladik
Keyingi qadam sifatida Docker, PyPI, Go, Cargo, Helm va boshqa texnologiyalar uchun ham Nexusda repositorylar yaratib, loyihalaringizni ulashingiz mumkin — mantiq bir xil, farqi faqat konfiguratsiya formatida.
Qo'shimcha
Qo'shimcha Resurslar
- Java Spring Boot Deployment: Gitlab CI va Github Actions (opens in a new tab)
- Gitlab Server o'rnatish va sozlash (opens in a new tab)
- Gitlab CI | Releaselar va Integrationlar (opens in a new tab)
- Github Actions bilan Flutter CI/CD (opens in a new tab)
- Github Actions CI/CD (opens in a new tab)
- Linux Serverlarga Jenkins o'rnatish (opens in a new tab)
- Koddan Servergacha: Jenkins bilan Docker CI/CD va Discord bilan integratsiya (opens in a new tab)
- Kubernetes CI/CD | GitHub Actions + Argo CD | GitOps (opens in a new tab)
Sana: 2025.02.08(2025-yil 8-fevral)
Oxirgi yangilanish: 2026.02.12(2026-yil 12-fevral)
Muallif: Otabek Ismoilov
| Telegram (opens in a new tab) | GitHub (opens in a new tab) | LinkedIn (opens in a new tab) |
|---|