Panduan Setup Pipeline CI/CD GitHub Actions ke Server Bare-Metal Tanpa Downtime

Dipublikasikan ⏱️ 7 menit bacaoleh Gugun Sayoti
Tutorial

Deploy manual lewat protokol SSH tengah malam picu downtime tak terduga. Margin error tinggi. Biaya managed cloud Kubernetes melambung tanpa utilisasi komputasi penuh. Tim rekayasa terjebak rilis rapuh dan tagihan infrastruktur bengkak.

Solusi tepat: pipeline GitHub Actions otomatis target server bare-metal via self-hosted runner. Gandeng arsitektur container Docker dan reverse proxy Nginx blue-green. Hasilnya nol downtime, pangkas biaya cloud 70%, rilis stabil hitungan detik.

Pelajari cetak biru teknis, konfigurasi pipeline, dan automasi rilis tingkat produksi berikut.


Daftar Isi

Kelemahan Deploy Manual dan Solusi Bare-Metal

Eksekusi git pull manual di server produksi timbulkan risiko fatal inkonsistensi environment. Human error picu konfigurasi environment rusak. Downtime aplikasi ganggu retensi pengguna.

Managed container service cloud publik kuras anggaran lewat biaya resource idle. Server bare-metal tawarkan performa I/O raw CPU dan memori penuh tanpa markup biaya virtualisasi.

Automasi via CI/CD hilangkan celah kelalaian operator. Setiap commit masuk pipeline teruji, terisolasi dalam container image deterministik, lalu rilis instan tanpa intervensi manual rentan error.

Komparasi Biaya dan Performa: Bare-Metal vs Managed Cloud

Pilihan arsitektur wajib hitung rasio cost-to-performance riil jangka panjang. Managed cloud tawarkan kemudahan operasional awal, tetapi biaya melonjak tajam saat throughput data dan kebutuhan memori naik.

Bare-metal hadirkan resource komputasi dedicated tanpa noise neighbor. Ketiadaan lapisan hypervisor ekstra pastikan utilisasi core CPU dan transfer disk NVMe sentuh kapasitas hardware maksimal.

Metrik EvaluasiServer Bare-Metal DedicatedManaged Cloud (AWS ECS/EKS)
Biaya Operasional BulananTetap dan Terprediksi (Flat Low Cost)Variabel Tinggi (Beban CPU, RAM, Network Egress)
Performa CPU dan Memori I/O100% Dedicated Hardware murniVirtualisasi Bersama (Shared Hypervisor)
Kontrol Pipeline RunnerSelf-Hosted Runner di Private NetworkCloud Hosted Runner (Limit Menit & Jaringan Publik)
Tingkat Kompleksitas SetupMenengah (Butuh Fondasi OS & Docker)Tinggi (Konfigurasi IAM, VPC, K8s Overlay)

Panduan ini komponen inti ekosistem Panduan Lengkap DevOps & Deployment Modern: Mengelola Server, Container, SSL, dan CI/CD dari Nol terpadu untuk efisiensi infrastruktur modern.

Persiapan Server dan Instalasi Self-Hosted Runner

Server bare-metal butuh Docker Engine mutakhir dan user isolasi non-root. Runner GitHub Actions self-hosted hindari kebutuhan buka port SSH server ke internet global. Komunikasi runner tarik job via HTTPS outbound port 443.

Masuk server bare-metal via SSH, jalankan setup user runner dan instal Docker runtime:

# Buat user runner dedicated dan berikan izin docker
sudo useradd -m -s /bin/bash runner
sudo usermod -aG docker runner
sudo su - runner

# Unduh paket runner resmi GitHub Actions
mkdir actions-runner && cd actions-runner
curl -o actions-runner-linux-x64-2.314.1.tar.gz -L https://github.com/actions/runner/releases/download/v2.314.1/actions-runner-linux-x64-2.314.1.tar.gz
tar xzf ./actions-runner-linux-x64-2.314.1.tar.gz

# Registrasi runner via token dari Repository Settings > Actions > Runners
./config.sh --url https://github.com/ORGANISASI/REPO --token TOKEN_DARI_GITHUB

# Pasang dan aktifkan systemd service background
sudo ./svc.sh install
sudo ./svc.sh start

Service runner systemd pastikan agen deploy otomatis aktif paska server reboot. Runner siap terima payload build langsung dari antrean repositori GitHub aman.

Strategi Zero-Downtime: Docker Compose Blue-Green

Zero-downtime mustahil diraih jika container lama dimatikan sebelum container baru siap layani trafik. Pola blue-green deploy selesaikan kendala ini lewat skema dua container identik aktif bergantian.

Satu container aktif terima request produksi (Blue). Container baru deploy di port terpisah (Green). Script health check verifikasi container Green siap, lalu Nginx reload config secara halus tanpa drop koneksi aktif.

Simpan konfigurasi docker-compose.yml berikut di direktori /opt/app/docker-compose.yml:

version: '3.8'
services:
  app_blue:
    image: ghcr.io/organisasi/web-app:${IMAGE_TAG}
    container_name: app_blue
    restart: always
    ports:
      - "127.0.0.1:8081:8080"
    environment:
      - ENV=production

  app_green:
    image: ghcr.io/organisasi/web-app:${IMAGE_TAG}
    container_name: app_green
    restart: always
    ports:
      - "127.0.0.1:8082:8080"
    environment:
      - ENV=production

Trafik masuk diatur Nginx upstream. Reload konfigurasi Nginx cuma butuh waktu milidetik via perintah nginx -s reload tanpa matikan socket HTTP.

Penyusunan Workflow Pipeline GitHub Actions

File workflow otomatisasi bangun image container, push ke registry aman, lalu trigger container reload langsung pada server bare-metal via self-hosted runner.

Buat file .github/workflows/deploy.yml pada repositori proyek:

name: CI/CD Bare-Metal Pipeline

on:
  push:
    branches: [ "main" ]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    outputs:
      image_tag: ${{ steps.meta.outputs.version }}
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

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

      - name: Extract Metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: type=sha,format=short

      - name: Build and Push Image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

  deploy:
    needs: build-and-push
    runs-on: self-hosted
    steps:
      - name: Log in to GitHub Container Registry
        run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin

      - name: Execute Blue-Green Deployment
        env:
          IMAGE_TAG: ${{ needs.build-and-push.outputs.image_tag }}
        run: |
          cd /opt/app
          export IMAGE_TAG=$IMAGE_TAG
          docker compose pull

          ACTIVE_APP=$(curl -s http://127.0.0.1:80/health-check-target || echo "blue")
          
          if [ "$ACTIVE_APP" = "blue" ]; then
            TARGET_SERVICE="app_green"
            TARGET_PORT="8082"
            OLD_SERVICE="app_blue"
          else
            TARGET_SERVICE="app_blue"
            TARGET_PORT="8081"
            OLD_SERVICE="app_green"
          fi

          docker compose up -d $TARGET_SERVICE
          
          # Verifikasi health check container baru
          sleep 5
          curl --fail http://127.0.0.1:$TARGET_PORT/health || exit 1
          
          # Switch upstream Nginx dan reload
          sed -i "s/127.0.0.1:[0-9]*/127.0.0.1:$TARGET_PORT/" /etc/nginx/conf.d/upstream.conf
          sudo nginx -s reload
          
          # Nonaktifkan instance lama
          docker compose stop $OLD_SERVICE

Pipeline di atas pastikan container lama tetap layani user sampai health check container baru lolos. Gagal health check gagalkan pipeline instan tanpa ganggu traffic aktif.

Protokol Rollback Otomatis dan Observabilitas Sistem

Deploy andal wajib punya mekanisme rollback otomatis jika runtime error lolos tahap testing awal. Skrip bash pipeline di atas membatalkan reload Nginx jika health check container target bernilai non-200.

Logging terpusat jadi fondasi observabilitas. Manfaatkan Docker logging driver bawaan (systemd journald atau local driver) batasi ukuran file log container cegah kapasitas storage bare-metal penuh.

Aktifkan pruning resource Docker berkala via cron job mingguan pada server runner. Bersihkan dangling image dan container layer kadaluarsa:

# Jalankan maintenance storage tiap Minggu jam 02:00 pagi
0 2 * * 0 /usr/bin/docker system prune -af --volumes

Checklist Implementasi Deployment Bare-Metal

  • Instalasi Docker Engine, Compose plugin, dan Nginx reverse proxy di host bare-metal.
  • Pembuatan user sistem runner non-root dengan hak akses socket Docker.
  • Registrasi GitHub Actions self-hosted runner via systemd service background.
  • Penyusunan file docker-compose.yml skema Blue-Green dual binding port.
  • Pemisahan file upstream Nginx untuk kemudahan automasi via sed.
  • Implementasi workflow deploy.yml terintegrasi GHCR dan health check testing.
  • Konfigurasi cron pruning image Docker kadaluarsa penghemat disk space.

Tanya Jawab Seputar CI/CD Bare-Metal (FAQ)

Apakah aman menjalankan self-hosted runner GitHub Actions di server produksi?

Sangat aman untuk repositori privat. Pastikan repositori bukan publik cegah eksekusi pull request tak dikenal. Jalankan runner via user sistem non-root terisolasi dan hindari inject credential root langsung di runner workspace.

Bagaimana cara Nginx me-reload konfigurasi tanpa memutus koneksi client?

Perintah nginx -s reload spawn proses worker baru baca konfigurasi anyar tanpa bunuh proses lama. Worker lama tuntaskan request koneksi aktif sebelum terminasi graceful.

Mengapa memilih GitHub Packages (GHCR) dibanding Docker Hub publik?

GHCR beri integrasi token native GitHub Actions via GITHUB_TOKEN tanpa secret eksternal. Batas rate limit transfer GHCR jauh lebih tinggi dibanding free tier Docker Hub.

Referensi & Tautan Berguna