tutorial, docker,

Dockerfile: Cara Membuat Docker Image Sendiri

Kiki/🎮🍉⌨️🍩💻 Kiki/🎮🍉⌨️🍩💻 Aug 30, 2026 · 6 mins read
Dockerfile: Cara Membuat Docker Image Sendiri
Share this

Kalau di artikel sebelumnya kita sudah paham konsep Docker dan container, sekarang saatnya masuk ke praktik. Dockerfile adalah file teks berisi serangkaian instruksi yang digunakan Docker untuk membangun sebuah Image. Memahami cara menulis Dockerfile yang baik adalah keterampilan inti yang harus dimiliki setiap developer yang bekerja dengan Docker.


Anatomi Dockerfile

Setiap Dockerfile terdiri dari instruksi-instruksi yang dieksekusi secara berurutan dari atas ke bawah. Setiap instruksi menghasilkan satu layer di dalam Image.

# Komentar diawali dengan tanda pagar

INSTRUKSI argumen

Instruksi-Instruksi Utama Dockerfile

FROM — Base Image

Instruksi pertama dan wajib. Mendefinisikan image dasar yang digunakan.

FROM node:20-alpine       # Node.js 20 di atas Alpine Linux (ringan)
FROM ubuntu:22.04         # Ubuntu 22.04
FROM python:3.12-slim     # Python 3.12 versi slim
FROM nginx:latest         # Nginx terbaru

Gunakan tag spesifik (node:20-alpine) daripada latest untuk build yang reproducible.

WORKDIR — Set Working Directory

Menetapkan direktori kerja di dalam container untuk instruksi selanjutnya.

WORKDIR /app

COPY — Copy File ke Image

Menyalin file dari host ke filesystem Image.

COPY package.json ./          # copy package.json ke /app/
COPY . .                      # copy semua file ke /app/
COPY src/ ./src/              # copy folder src/

ADD — Seperti COPY tapi Lebih Powerful

Mirip COPY tapi bisa otomatis mengekstrak file .tar dan mengambil file dari URL. Gunakan COPY untuk kasus biasa, ADD hanya jika benar-benar butuh fitur ekstranya.

RUN — Eksekusi Perintah Saat Build

Menjalankan perintah shell dan hasilnya menjadi layer baru di Image.

RUN npm install
RUN apt-get update && apt-get install -y curl
RUN npm run build

Gabungkan perintah dengan && untuk mengurangi jumlah layer:

# Kurang baik — 3 layer
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get clean

# Lebih baik — 1 layer
RUN apt-get update && apt-get install -y curl && apt-get clean

ENV — Environment Variable

Menetapkan environment variable yang tersedia saat build dan runtime.

ENV NODE_ENV=production
ENV PORT=3000
ENV APP_NAME="Blog API"

EXPOSE — Dokumentasi Port

Mendokumentasikan port yang digunakan container. Tidak otomatis membuka port — hanya metadata.

EXPOSE 3000
EXPOSE 80 443

CMD — Perintah Default Saat Container Dijalankan

Perintah yang dijalankan saat container start. Bisa di-override dengan docker run.

CMD ["node", "index.js"]
CMD ["npm", "start"]
CMD ["nginx", "-g", "daemon off;"]

ENTRYPOINT — Perintah Utama Container

Mirip CMD tapi lebih rigid — tidak mudah di-override. Cocok untuk container yang berperan sebagai executable.

ENTRYPOINT ["node"]
CMD ["index.js"]    # argumen default untuk ENTRYPOINT

Dockerfile untuk Aplikasi Node.js

# Gunakan Node.js 20 Alpine (lebih ringan dari full image)
FROM node:20-alpine

# Set working directory
WORKDIR /app

# Copy package files dulu (manfaatkan layer cache)
COPY package.json package-lock.json ./

# Install dependencies
RUN npm ci --omit=dev

# Copy source code
COPY . .

# Set environment variable
ENV NODE_ENV=production
ENV PORT=3000

# Dokumentasikan port
EXPOSE 3000

# Jalankan aplikasi
CMD ["node", "index.js"]

Build dan Jalankan Image

# Build image dari Dockerfile di direktori saat ini
# -t = tag (nama:versi)
docker build -t blog-api:1.0 .

# Lihat image yang sudah di-build
docker images

# Jalankan container dari image
docker run -p 3000:3000 blog-api:1.0

# Jalankan di background (detached mode)
docker run -d -p 3000:3000 --name api blog-api:1.0

# Lihat container yang berjalan
docker ps

# Lihat log container
docker logs api
docker logs -f api   # follow (live log)

# Stop dan hapus container
docker stop api
docker rm api

Flag -p 3000:3000 artinya: port 3000 di hostport 3000 di container.


.dockerignore — Jangan Copy File yang Tidak Perlu

Seperti .gitignore, file .dockerignore mencegah file tertentu ter-copy ke Image:

node_modules
.git
.env
*.log
dist
coverage
README.md
docker-compose.yml
.dockerignore

Tanpa .dockerignore, folder node_modules yang berisi ribuan file akan ter-copy ke Image dan memperlambat build secara signifikan.


Layer Caching — Optimalkan Kecepatan Build

Docker menyimpan cache setiap layer. Jika sebuah layer tidak berubah, Docker menggunakan cache dan tidak rebuild layer tersebut.

Trik penting: letakkan instruksi yang jarang berubah di atas, yang sering berubah di bawah.

FROM node:20-alpine
WORKDIR /app

# COPY package.json dulu — hanya berubah saat ada dependency baru
COPY package.json package-lock.json ./
RUN npm ci

# COPY source code SETELAH install — source code sering berubah
COPY . .

CMD ["node", "index.js"]

Dengan urutan ini, npm ci hanya dijalankan ulang saat package.json berubah, bukan setiap kali kode berubah. Build menjadi jauh lebih cepat.


Multi-Stage Build — Image yang Lebih Kecil

Multi-stage build memungkinkan kamu menggunakan beberapa FROM untuk memisahkan proses build dari runtime image:

# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: Production image (hanya copy hasil build)
FROM node:20-alpine AS production
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/index.js"]

Hasilnya: image production tidak mengandung devDependencies maupun source code mentah — ukurannya jauh lebih kecil.


Kesimpulan

Dockerfile adalah fondasi dari semua workflow Docker. Dengan memahami instruksi-instruksi utama, manfaat layer caching, dan multi-stage build, kamu bisa membuat Image yang efisien, kecil, dan reproducible.

Di artikel berikutnya, kita bahas Docker Compose — cara mengelola aplikasi yang terdiri dari beberapa container sekaligus.

Kiki/🎮🍉⌨️🍩💻
Written by Kiki/🎮🍉⌨️🍩💻
hello I'm friend K.