Belum tahu Docker? Mulai dari sini — ada gambar di tiap langkah
Deploy blog pakai Docker, dari nol
Pernah dengar kata "Docker" tapi bingung itu apa? Tenang. Panduan ini menganggap kamu belum pernah memakainya sama sekali. Kita mulai dari analogi paling sederhana, lalu pelan-pelan sampai blog kamu benar-benar tayang di dalam Docker. Tinggal ikuti dan cocokkan dengan gambar di tiap langkah.
Sekali bungkus
Blog + Node + semua dependensi jadi satu "kotak" yang rapi.
Jalan di mana saja
Kotak yang sama jalan di laptop maupun di VPS — tanpa drama.
Update gampang
Ganti kode → build ulang kotak → jalankan. Selesai.
Apa itu Docker, sebenarnya?
Bayangkan kamu mau mengirim makanan ke teman. Daripada membawa kompor, panci, bumbu, dan bahan satu per satu (dan berharap dapur temanmu punya alat yang sama), kamu cukup memasukkan seluruhnya ke dalam satu kotak bekal yang sudah lengkap. Di mana pun kotak itu dibuka, isinya sama persis.
Docker itu kotak bekal untuk aplikasi. Ia membungkus blog kamu bersama Node.js dan semua yang dibutuhkannya ke dalam satu paket yang disebut image. Saat image dijalankan, ia menjadi container— aplikasi yang hidup dan berjalan. Karena semuanya sudah ada di dalam kotak, blog akan jalan sama persis di laptop kamu maupun di VPS, tanpa kalimat klasik "kok di komputerku jalan, di server tidak?".
Dockerfile
Resep: cara membungkus blog jadi kotak.
Image
Kotak yang sudah jadi & siap dikirim.
Container
Kotak yang sedang dibuka & berjalan.
Install Docker di VPS
Masuk ke VPS lewat SSH seperti di panduan utama. Cara termudah memasang Docker adalah dengan skrip resmi mereka. Cukup jalankan baris-baris ini satu per satu:
deploy@vps:~$ curl -fsSL https://get.docker.com -o get-docker.shdeploy@vps:~$ sudo sh get-docker.shClient: Docker Engine - CommunityServer: Docker Engine - Community# biar bisa pakai docker tanpa sudo terus-terusan:deploy@vps:~$ sudo usermod -aG docker $USERdeploy@vps:~$ newgrp dockerdeploy@vps:~$ docker --versionDocker version 27.3.1, build ce1223035ausermod -aG docker, sebaiknya logout lalu login lagi ke VPS agar hak akses grup benar-benar aktif. Kalau masih muncul permission denied saat memanggil Docker, itulah penyebabnya.Siapkan Next.js untuk Docker (mode standalone)
Agar kotak Docker kita kecil dan cepat, minta Next.js menghasilkan versi standalone — sebuah folder mungil yang sudah memuat semua yang diperlukan untuk jalan. Cukup tambahkan satu baris di next.config.mjs di komputer kamu:
// next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
// ⬇️ baris penting untuk Docker: bikin folder kecil siap-jalan
output: 'standalone',
images: { unoptimized: true },
}
export default nextConfigoutput: 'standalone' inilah kuncinya. Tanpa ini, hasil build tersebar ke mana-mana dan kotak Docker jadi besar serta ribet. Simpan, lalu commit perubahan ini ke GitHub.Buat file Dockerfile (resepnya)
Di folder utama project (sejajar dengan package.json), buat file bernama Dockerfile— tanpa ekstensi. Ini adalah "resep" yang memberi tahu Docker cara membungkus blog. Tampilan isinya kira-kira seperti ini di editor:
1# Tahap 1 — build2FROM node:20-alpine AS builder3WORKDIR /app4RUN corepack enable5COPY package.json pnpm-lock.yaml ./6RUN pnpm install --frozen-lockfile7COPY . .8RUN pnpm build9 10# Tahap 2 — jalan11FROM node:20-alpine AS runner12WORKDIR /app13ENV NODE_ENV=production14COPY --from=builder /app/public ./public15COPY --from=builder /app/.next/standalone ./16COPY --from=builder /app/.next/static ./.next/static17EXPOSE 300018CMD ["node", "server.js"]Salin teks lengkapnya dari sini:
# Dockerfile — resep membungkus blog jadi satu "kotak"
# 1) Tahap build: pasang dependency & build Next.js
FROM node:20-alpine AS builder
WORKDIR /app
RUN corepack enable
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
# 2) Tahap jalan: kotak akhir yang ramping & cepat
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
# salin hanya hasil yang perlu dari tahap build
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
EXPOSE 3000
CMD ["node", "server.js"]Buat .dockerignore
Sama seperti .gitignore, file .dockerignore memberi tahu Docker file apa saja yang tidak perlu ikut masuk ke dalam kotak. Ini membuat build lebih cepat dan kotak lebih ramping:
# .dockerignore — biar build cepat & kotak tetap ramping
node_modules
.next
.git
.env
npm-debug.log
README.mdnode_modules dan .next di sini itu penting — keduanya akan dibuat ulang di dalam kotak, jadi tidak perlu ikut disalin dari komputer kamu.Build image (membuat kotaknya)
Di VPS, masuk ke folder blog, lalu suruh Docker membaca resep tadi dan membuat image. Tanda -t blog artinya kita memberi nama blog pada kotaknya.
deploy@vps:~$ cd ~/blogdeploy@vps:~$ docker build -t blog .[+] Building 48.2s (16/16) FINISHED => [builder 4/6] RUN pnpm install --frozen-lockfile => [builder 6/6] RUN pnpm build => exporting to image => => naming to docker.io/library/blog:latestBuild pertama agak lama karena Docker mengunduh Node.js dan semua dependensi. Build berikutnya jauh lebih cepat karena hasilnya di-cache. Cek kotakmu sudah jadi:
deploy@vps:~$ docker imagesREPOSITORY TAG SIZEblog latest 182MBJalankan container (membuka kotaknya)
Sekarang jalankan image tadi menjadi container. -d artinya jalan di latar belakang, -p 3000:3000 menyambungkan port dalam kotak ke port VPS, dan --restart unless-stopped bikin blog otomatis hidup lagi kalau server di-reboot.
deploy@vps:~$ docker run -d --name blog --restart unless-stopped -p 3000:3000 bloga1b2c3d4e5f6...deploy@vps:~$ docker psCONTAINER ID IMAGE STATUS PORTSa1b2c3d4e5f6 blog Up 6 seconds 0.0.0.0:3000->3000/tcpBlog kamu kini berjalan di dalam Docker! Coba buka http://IP-VPS-KAMU:3000 di browser:
Blog berbasis markdown
Tulis di Markdown. Push ke GitHub. Deploy di VPS milikmu sendiri.
Menyiapkan VPS pertama kamu
Sebuah catatan singkat tentang menjalankan blog kamu sendiri…
Menulis dengan Markdown
Sebuah catatan singkat tentang menjalankan blog kamu sendiri…
docker logs -f blog. Mau berhenti? docker stop blog. Mau hapus? docker rm blog.Lebih rapi: pakai Docker Compose
Mengetik perintah docker run yang panjang tiap kali itu melelahkan. Docker Compose menyimpan semua pengaturan itu ke dalam satu file docker-compose.yml, jadi kamu cukup mengetik satu perintah pendek. Buat file ini di folder blog:
# docker-compose.yml — jalankan blog dengan satu perintah
services:
blog:
build: .
container_name: blog
restart: unless-stopped
ports:
- "3000:3000"
# kalau blog kamu butuh env, aktifkan baris ini:
# env_file: .envSekarang hentikan container lama (kalau masih jalan dari langkah 7), lalu jalankan semuanya hanya dengan satu baris:
deploy@vps:~$ docker rm -f blogdeploy@vps:~$ docker compose up -d --build[+] Building 12.4s ... FINISHED[+] Running 1/1 ✔ Container blog Starteddocker compose up -d --build untuk menyalakan/memperbarui, dan docker compose down untuk mematikan. Jauh lebih mudah diingat.Pasang Nginx + HTTPS di depan container
Saat ini blog hanya bisa diakses lewat :3000 dan masih http. Untuk memakai domain sendiri dengan https, kita taruh Nginx di depan container — persis seperti di panduan VPS utama. Container Docker tetap mendengarkan di localhost:3000, jadi konfigurasi Nginx-nya sama saja:
1server {2 listen 80;3 server_name domainkamu.com www.domainkamu.com;4 5 location / {6 proxy_pass http://localhost:3000;7 proxy_http_version 1.1;8 proxy_set_header Host $host;9 proxy_set_header X-Real-IP $remote_addr;10 }11}Cara update blog nanti
Mau menerbitkan tulisan baru atau mengubah kode? Alurnya selalu sama: push perubahan dari laptop ke GitHub, lalu di VPS tarik kode terbaru dan build ulang kotaknya.
deploy@vps:~$ cd ~/blogdeploy@vps:~$ git pulldeploy@vps:~$ docker compose up -d --build ✔ Container blog Started# bersihkan kotak lama yang sudah tak terpakaideploy@vps:~$ docker image prune -fTotal reclaimed space: 180.2MBBiar tidak perlu mengetik berulang, simpan langkah-langkah itu dalam file deploy.sh di repo kamu:
#!/usr/bin/env bash
set -e
cd ~/blog
echo "==> Ambil kode terbaru"
git pull
echo "==> Build ulang image & jalankan container baru"
docker compose up -d --build
echo "==> Bersihkan image lama yang tak terpakai"
docker image prune -f
echo "Deploy berhasil — blog jalan di dalam Docker!"Jadikan bisa dieksekusi sekali saja dengan chmod +x deploy.sh. Setelah itu, tiap update cukup jalankan ./deploy.sh.
Kalau ada masalah
| Gejala | Solusi |
|---|---|
| permission denied saat panggil docker | Lupa logout/login setelah usermod -aG docker $USER (lihat langkah 2) |
| Cannot find module server.js | Lupa output: 'standalone' di next.config.mjs (langkah 3) lalu build ulang |
| Port 3000 already in use | Container lama masih jalan — hentikan dengan docker rm -f blog |
| Build kehabisan memori di VPS 1 GB | Tambahkan swap (lihat panduan utama langkah 8), lalu build ulang |
| Container langsung mati (Exited) | Lihat sebabnya dengan docker logs blog |
Perintah penyelamat: docker ps -a (lihat semua container), docker logs blog (lihat error), dan docker compose up -d --build (bangun ulang).
Selamat!
Kamu baru saja men-deploy blog di dalam Docker — dari yang tadinya belum tahu Docker sama sekali. Kembali ke artikel.