$ aoox

DocsAplikasi

Cara build

Tiga cara mengubah repo menjadi image: Dockerfile milikmu sendiri, deteksi otomatis oleh Nixpacks, atau situs statis dengan nginx.

Pilihan
Dockerfile · Nixpacks · Railpack · Situs statis, per aplikasi
Berjalan di
Daemon Docker (builder klasik); Railpack lewat BuildKit sendiri
Hasil
Image <registry>/<project>/<app>:<id>
Halaman ini tentang aplikasi yang dibangun dari repo Git. Aplikasi yang sumbernya image siap pakai tidak melewati tahap build sama sekali — lihat Dua sumber aplikasi.

Mana yang dipilih?

Hasilnya hanya file HTML/CSS/JS (Vite, CRA, Astro, Hugo, dokumentasi)?ya → Situs statistidak → lanjut
Repo sudah punya Dockerfile?ya → Dockerfiletidak → lanjut
Butuh build ulang cepat / cache layer?ya → Dockerfile atau Railpacktidak → lanjut
Ingin nol konfigurasi dan cache antar deploy (di host, bukan server remote)?ya → Railpacktidak → lanjut
Ingin nol konfigurasi, terima build lambat tiap kali?ya → Nixpackstidak → Dockerfile
DockerfileNixpacksRailpackSitus statis
SetupTulis Dockerfile sendiriNol konfigurasiNol konfigurasiPerintah build + folder output
Build ulangCache layer DockerHanya cache layer (tanpa cache mount, --no-cache)Cache BuildKit antar deployHanya cache layer
Build pertamaTergantung base imageLambat: base ± 350 MB + nix-env284 detik (helper + BuildKit sekali)Cepat: node alpine + nginx alpine
Build berikutnyaCepat bila layer tak berubahCepat bila layer tak berubah; lambat bila file dependensi berubah±8 detik — dependensi dari cacheCepat bila layer tak berubah
Kontrol imagePenuhTerbatas ke opsi nixpacksTerbatas ke opsi railpackTidak ada — nginx :80
Server remoteYaYaTidak — host sajaYa
Cocok untukProduksi, image rampingPrototipe, repo tanpa DockerfileDeploy berulang tanpa DockerfileSPA, landing page, dokumentasi

Dockerfile

Pilih Cara build → Dockerfile dan isi Dockerfile di repo (default Dockerfile di root). Build dijalankan daemon Docker langsung dari URL Git (POST /build?remote=…) — daemon yang meng-clone, API tidak butuh git. Untuk monorepo, isi Root directory; path Dockerfile lalu dihitung dari folder itu.

Contoh minimal (Node.js)
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["node", "server.js"]
  • Builder klasik, bukan BuildKit: sintaks RUN --mount, COPY --link, dan heredoc tidak didukung.
  • Layer cache berlaku antar build selama base image dan langkah awal tidak berubah — letakkan COPY package*.json + npm ci sebelum COPY . ..
  • Sertakan wget atau curl di image bila memakai health check (alpine punya wget bawaan busybox).

Nixpacks

Pilih Cara build → Nixpacks untuk repo tanpa Dockerfile. Tidak ada binary nixpacks di host maupun di image API — semuanya berjalan di container:

  1. 01helperimage aoox-nixpacks dibangun sekali (debian + git + nixpacks CLI)
  2. 02clonecontainer sekali-jalan git clone --depth 1 (kredensial tidak keluar dari helper)
  3. 03plannixpacks build → menulis .nixpacks/Dockerfile
  4. 04buildsource di-tar → POST /build dengan Dockerfile hasil generate
Konsekuensi yang perlu diketahui
  • Build pertama lambat: base image nixpacks (± 350 MB) di-pull dan helper image dibangun sekali; versi nixpacks dipin oleh aoox.
  • Tidak ada cache mount dependensi — --no-cache wajib karena cache mount nixpacks butuh BuildKit. Cache layer Docker tetap berlaku: deploy ulang dengan source yang sama memakai ulang semua layer (hitungan detik), sedangkan perubahan file dependensi membangun ulang dari layer itu dan mengunduh dependensi lagi.
  • Source tree ditahan di memori API selama build (tanpa .git) — repo yang sangat besar sebaiknya memakai Dockerfile.

Mengarahkan Nixpacks

Nixpacks membaca variabel NIXPACKS_*. Isi lewat Build args:

Build args
NIXPACKS_NODE_VERSION=22
NIXPACKS_BUILD_CMD=npm run build
NIXPACKS_START_CMD=node server.js

Alternatif: taruh nixpacks.toml di repo — dibaca otomatis saat plan.

Railpack

Pilih Cara build → Railpack untuk repo tanpa Dockerfile yang di-deploy berulang kali dan ingin cache dependensi tetap ada. Berbeda dari Nixpacks, Railpack mengeksekusi build plan-nya lewat container moby/buildkit yang hidup terus dengan volume sendiri — layer dependensi bertahan antar deploy.

  1. 01helperimage aoox-railpack dibangun sekali (docker CLI + git + binary railpack)
  2. 02buildkitcontainer aoox-buildkit (moby/buildkit) dinyalakan sekali, volume cache sendiri
  3. 03clonehelper git clone --depth 1, lalu railpack build --cache-key <project>/<app>
  4. 04cachelayer dependensi tersimpan di volume BuildKit — deploy berikutnya memakainya lagi
Hanya di host
Railpack menjalankan BuildKit di sebelah registry di host aoox sendiri — belum ada BuildKit per server remote. Aplikasi dengan server remote harus memakai Dockerfile atau Nixpacks.
Memori di server kecil
Railpack menjalankan BuildKit, dan build pertama (cold) adalah yang paling banyak memakai memori. Di server 2 GB build bisa dimatikan karena kehabisan memori (exit code 137). Pakai server 4 GB, atau pastikan swap aktif lalu coba lagi: build berikutnya memakai ulang cache BuildKit dan butuh jauh lebih sedikit. Anda juga bisa build dengan Dockerfile.
  • Image hasil Railpack mendengarkan di $PORT (konvensi Railway). aoox otomatis mengisi PORT dengan container port yang dikonfigurasi, kecuali aplikasi sudah men-set PORT sendiri di env.
  • Build args diteruskan sebagai --env ke railpack — sama seperti Nixpacks, ikut memengaruhi hasil deteksi provider-nya.
  • Cache di-scope per project/aplikasi, jadi aplikasi lain tidak berbagi layer secara tidak sengaja. Volume BuildKit dipangkas otomatis oleh maintenance malam — prune bawaan Docker tidak menjangkaunya.

Situs statis (nginx)

Pilih Cara build → Situs statis (nginx) untuk repo yang hasil akhirnya hanya file statis. aoox membuat Dockerfile dua tahap: (opsional) tahap build di node:22-alpine, lalu nginx:1.27-alpine yang melayani folder output di port 80 — form membuat aplikasi mengisi Port container 80 otomatis saat memilih Situs statis (bisa diubah, tetapi nginx tetap mendengarkan port 80).

FieldKeterangan
Perintah buildMis. npm ci && npm run build. Kosongkan bila file sudah ada di repo (tanpa tahap Node).
Folder outputRelatif dari Root directory (root repo bila kosong): dist (default), build, out, atau . untuk seluruh folder.
Mode SPAAktif (default): path tak dikenal dilayani index.html (client-side routing). Nonaktif: 404 biasa untuk situs multi-halaman.
Dockerfile yang dihasilkan (ilustrasi)
FROM node:22-alpine AS build
WORKDIR /src
COPY . .
RUN npm ci && npm run build

FROM nginx:1.27-alpine
COPY --from=build /src/dist/ /usr/share/nginx/html/
COPY .aoox/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
  • Port container harus 80. Health check path / cukup (nginx alpine punya wget).
  • Build berjalan lewat helper yang sama dengan Nixpacks (clone di container, konteks tar) — repo privat aman, tapi tanpa cache mount dependensi (layer yang tidak berubah tetap dipakai ulang).
  • Env runtime tidak berguna untuk file statis, dan Build args belum diteruskan ke tahap build statis. Nilai saat build (mis. VITE_API_URL) untuk sementara ditaruh di repo (.env.production) atau di perintah build: VITE_API_URL=https://api.example.com npm run build.
  • Versi Node dipin ke 22 oleh aoox; belum bisa diubah dari UI.

Root directory (monorepo)

Repo monorepo menyimpan beberapa aplikasi dalam satu repository (mis. apps/web dan services/api). Isi Root directory di bagian Git pada form aplikasi dengan folder yang ingin di-build; kosong berarti root repo. Berlaku untuk semua cara build, termasuk preview pull request.

Cara buildYang dihitung dari Root directory
DockerfileKonteks build = folder itu (POST /build?remote=URL#branch:folder), dan Dockerfile dihitung dari folder yang sama.
NixpacksDeteksi stack dan build dijalankan di folder itu; .nixpacks/Dockerfile ditulis di sana.
Railpackrailpack build dijalankan di folder itu.
Situs statisPerintah build berjalan di folder itu dan Folder output dihitung dari folder itu juga.
Contoh: satu repo, tiga aplikasi
apps/web        Root directory: apps/web       (Nixpacks)
services/api    Root directory: services/api   (Dockerfile di services/api/Dockerfile)
apps/site       Root directory: apps/site      (Situs statis, output: .)
Batasannya
  • File di luar folder tidak tersedia saat build. Dockerfile di apps/web tidak bisa COPY ../../packages/shared. Paket bersama harus di-bundle lebih dulu, atau pakai Dockerfile di root repo dengan Root directory kosong.
  • Format: folder relatif, hanya huruf, angka, ., _, - dipisah /; tanpa .. dan tanpa / di awal atau akhir.
  • Folder yang tidak ada di branch itu menggagalkan deployment dengan pesan Root directory … was not found; container lama tetap berjalan.
  • Link simbolis di repo yang menunjuk ke luar clone ditolak.

Mau deploy hanya bila folder itu berubah? Lihat Webhook untuk monorepo.

Build args

Field Build args (tab Pengaturan) berformat KEY=VALUE per baris dan diteruskan sebagai --build-arg. Untuk Nixpacks dan Railpack nilainya juga menjadi env saat plan/build. Belum berlaku untuk situs statis.

Dockerfile yang memakainya
ARG NEXT_PUBLIC_API_URL
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
RUN npm run build
Build args tidak mendukung referensi ${{…}} dan ikut tersimpan di image yang di-push. Jangan taruh rahasia di sini — pakai environment variables yang diterapkan saat runtime.

Image yang dihasilkan

<registry.url>/<project-slug>/<app-slug>:<12 karakter id deployment>
# contoh: localhost:5000/toko/shop:a1b2c3d4e5f6
  • Tag lama tetap ada di registry sampai dihapus di halaman Registry — itulah yang memungkinkan rollback. Hapus + garbage collect untuk mengembalikan disk.
  • Di server remote image tidak di-push; tersimpan di daemon server itu dengan ref aoox/<project>/<app>:<tag>.

Jebakan umum

GejalaPenyebab & solusi
Build gagal: unknown flag / --mountSintaks BuildKit di Dockerfile. Ganti dengan langkah biasa.
Nixpacks: build menggantungTidak seharusnya terjadi — aoox memaksa --no-cache. Cek log helper di tab Deploy.
Nixpacks memilih versi Node/Python yang salahSet NIXPACKS_NODE_VERSION / NIXPACKS_PYTHON_VERSION di Build args, atau engines di package.json.
Env kosong saat buildEnv memang tidak tersedia di tahap build. Pakai Build args (non-rahasia) atau baca env saat runtime.
Railpack: "run on the aoox host only"Aplikasi ini punya server remote. Pindahkan ke Dockerfile/Nixpacks, atau hapus penempatan server-nya.
Railpack: aplikasi tidak menerima koneksiCek aplikasi membaca process.env.PORT, bukan port tertulis. aoox mengisinya otomatis dari container port.

Langkah berikutnya

Ada yang keliru? Edit halaman ini di GitHub ↗