Belajar GitHub Actions - Integrasi Docker & Container Registries
Episode 12 of 21

Belajar GitHub Actions - Integrasi Docker & Container Registries

Episode ini membahas integrasi Docker ke pipeline: menjalankan job di dalam container untuk isolasi lingkungan build, lalu mengotomasi build dan push image multi-platform ke GHCR dengan layer caching agar pipeline tetap cepat.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Pendahuluan

Di episode 11 kita belajar mengemas logika pipeline agar tidak diduplikasi antar repository. Sekarang tiba giliran masalah klasik yang menjengkelkan semua tim: "works on my machine". Kode yang lolos test di laptop developer sering berulah begitu sampai di server produksi — beda versi Node.js, beda sistem operasi, beda dependensi sistem.

Episode 12 menjawabnya dengan Docker: mengunci lingkungan build di dalam container sehingga apa yang diuji di pipeline sama persis dengan apa yang berjalan di produksi. Kita akan belajar menjalankan job di dalam container, lalu mengotomasi build dan push image ke registry (GHCR) dengan workflow production-grade.

Pembahasan Utama

Kenapa Menjalankan Job di Dalam Container

Secara default, job GitHub Actions berjalan di atas sistem operasi runner yang sudah diisi banyak perangkat lunak (yang juga terus berubah antar versi). Dengan key container, kalian bisa memerintahkan job berjalan di dalam container tertentu — lingkungan userland yang dijamin identik setiap kali:

Job berjalan di dalam container Node.js
jobs:
  test:
    runs-on: ubuntu-latest
    container:
      image: node:20-alpine
      env:
        NODE_ENV: test
      options: --memory 512m --cpus 1
    steps:
      - uses: actions/checkout@v4
      - run: node --version
      - run: npm test

Runner VM tetap menyediakan kernel dan Docker, tetapi seluruh langkah job berjalan di dalam image node:20-alpine — versi Node.js yang spesifik, tanpa toolchain yang tidak diinginkan. env di dalam container menyetel variabel lingkungan image, dan options meneruskan flag tambahan ke docker run (misalnya batas memori). Image alpine dipilih karena ringan, sehingga startup job cepat.

Note

Penting dibedakan: key container adalah untuk menjalankan job di dalam container, bukan untuk membangun image. Membangun dan mengirim image ke registry menggunakan rangkaian action Docker di bawah — keduanya sering tertukar oleh pemula.

Membangun dan Mengirim Image: Workflow Lengkap

Tujuan akhir bab ini: setiap push ke main menghasilkan image Docker baru, dikirim ke registry, siap dipakai deployment. Registry yang kita pakai adalah GHCR (ghcr.io), yang terintegrasi natural dengan GitHub — login-nya bahkan bisa memakai GITHUB_TOKEN, tanpa menyimpan password registry terpisah.

Tiga action kunci yang membentuk rantai build:

  • docker/login-action@v3 — autentikasi ke registry (GHCR atau Docker Hub).
  • docker/setup-buildx-action@v3 — mengaktifkan BuildKit dengan dukungan multi-platform.
  • docker/build-push-action@v6 — membangun dan (jika push: true) mengirim image.
Build dan push image multi-platform ke GHCR
name: Build and Push Image
on:
  push:
    branches: [main]
    tags: ["v*"]
permissions:
  contents: read
  packages: write
jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - id: meta
        uses: docker/metadata-action@v5
        with:
          images: ghcr.io/devvnull/app
          tags: |
            type=semver,pattern={{version}}
            type=sha
      - uses: docker/build-push-action@v6
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

Mari kita bedah dari atas: permission packages: write adalah syarat untuk push ke GHCR — ini penerapan least privilege dari episode 9. Login memakai GITHUB_TOKEN sebagai password, sehingga tidak ada secret tambahan yang perlu dijaga. metadata-action menghasilkan tag image secara dinamis: tag versi semver saat ada git tag v*, dan tag hash commit untuk setiap push. platforms: linux/amd64,linux/arm64 membuat image berjalan baik di server x86 maupun prosesor ARM (misalnya Apple Silicon atau instance ARM di cloud). Terakhir, cache-from dan cache-to dengan backend type=gha menyambungkan layer caching — kita bahas sebentar lagi.

Docker Layer Caching

Tanpa cache, setiap build mengulang seluruh proses dari awal: mengunduh base image, menyalin kode, menginstal dependensi — meskipun hanya satu baris kode yang berubah. Docker menyimpan hasil antar-langkah dalam layer, dan layer yang tidak berubah bisa dipakai ulang dari build sebelumnya. Ini seperti save game bertahap: hanya bagian yang berubah yang diulang.

Backend type=gha menyimpan cache build di GitHub Actions cache, sehingga bertahan lintas run:

Menghidupkan layer caching antar run
cache-from: type=gha
cache-to: type=gha,mode=max

mode=max memaksa cache menyimpan semua layer antar platform, bukan hanya layer terakhir. Tanpa itu, cache untuk linux/arm64 bisa hilang dan build multi-platform tidak mendapat manfaat penuh.

Warning

Cache type=gha memakai kuota penyimpanan cache yang sama dengan actions/cache (batas default 10 GB per repository). Image yang besar bisa cepat menghabiskan kuota ini — pantau halaman settings cache, dan pertimbangkan menulis cache hanya untuk branch default agar tidak mengonsumsi kuota untuk tiap branch fitur.

Alternatif: Docker Hub

Tidak semua proyek memakai GHCR. Untuk Docker Hub, alurnya sama persis, hanya registry dan kredensialnya yang berbeda — password berupa personal access token, bukan password akun biasa:

Login ke Docker Hub
- uses: docker/login-action@v3
  with:
    username: ${{ secrets.DOCKERHUB_USERNAME }}
    password: ${{ secrets.DOCKERHUB_TOKEN }}

Setelah login, image dikirim ke docker.io dengan tag seperti devvnull/app:latest dan devvnull/app:v1.2.3.

Kesalahan Umum

KesalahanGejalaSolusi
Lupa permission packages: writePush ke GHCR ditolak dengan 403Tambahkan permissions: packages: write
push: true tidak disetelImage hanya ada di runner, hilang setelah jobSetel push: true pada build-push-action
Cache tanpa mode=maxCache multi-platform tidak optimalGunakan cache-to: type=gha,mode=max
Base image tidak di-pinBuild rusak karena tag base berubahPin digest image base di Dockerfile
Mengira container job untuk membangun imageImage tidak pernah dibuatPakai buildx + build-push-action

Penutup

Docker menutup celah antara lingkungan build dan lingkungan produksi:

  • Job di dalam container (container: image: node:20-alpine) mengunci lingkungan eksekusi test dan build.
  • Rantai tiga action Dockerlogin-action@v3, setup-buildx-action@v3, build-push-action@v6 — mengotomasi build dan push ke GHCR.
  • Multi-platform build menghasilkan image yang berjalan di linux/amd64 dan linux/arm64 dari satu pipeline.
  • Layer caching dengan backend type=gha membuat build berikutnya jauh lebih cepat.

Di episode 13 berikutnya, kita masuk bab Continuous Deployment (CD): Deployment ke Server via SSH, Rsync, dan Ansible — mengirim aplikasi yang sudah dibangun dan dikemas ini ke server produksi secara otomatis, tanpa login manual ke VPS. Dari pipeline hingga produksi!

Belajar GitHub Actions - Integrasi Docker & Container Registries | Belajar GitHub Actions