spinny:~/writing $ less docker-containers-complete-guide.md
12Docker telah mengubah cara kita membina, menghantar dan menjalankan perisian. Berbanding "ia berfungsi pada mesin saya", Docker menjamin bahawa aplikasi anda berjalan dengan cara yang sama di mana-mana - pada laptop anda, pada mesin rakan sekerja, dalam CI/CD dan dalam produksi. Dalam panduan ini, kita akan bermula dari sifar hingga men-deploy aplikasi sebenar.34## Apa itu Docker?56Docker ialah platform yang membungkus aplikasi anda dan semua kebergantungannya ke dalam unit piawai yang dipanggil **kontena**. Kontena ialah proses terpencil dan ringan yang berkongsi kernel OS hos tetapi mempunyai sistem fail, rangkaian dan ruang proses sendiri.78```mermaid9graph TD10 subgraph "Traditional Deployment"11 A1[App 1] --> OS1[Guest OS]12 A2[App 2] --> OS2[Guest OS]13 OS1 --> HV[Hypervisor]14 OS2 --> HV15 HV --> HW1[Hardware]16 end1718 subgraph "Docker Deployment"19 B1[App 1] --> D1[Container]20 B2[App 2] --> D2[Container]21 D1 --> DE[Docker Engine]22 D2 --> DE23 DE --> HW2[Hardware]24 end25```2627### Kontena vs Mesin Maya2829| Aspek | Kontena | Mesin Maya |30|-------|---------|-----------|31| **Permulaan** | Saat | Minit |32| **Saiz** | MB | GB |33| **OS** | Berkongsi kernel hos | OS tetamu penuh |34| **Pengasingan** | Tahap proses | Tahap perkakasan |35| **Prestasi** | Hampir natif | Beban tambahan dari hypervisor |36| **Kepadatan** | Ratusan setiap hos | Puluhan setiap hos |3738## Memasang Docker3940```bash41# macOS42brew install --cask docker4344# Ubuntu/Debian45curl -fsSL https://get.docker.com | sh46sudo usermod -aG docker $USER4748# Verify installation49docker --version50docker run hello-world51```5253## Konsep Teras5455### Imej5657Imej ialah templat baca-sahaja dengan arahan untuk mencipta kontena. Anggap ia sebagai gambar kilat aplikasi anda dan persekitarannya.5859```bash60# Pull an image from Docker Hub61docker pull node:20-alpine6263# List local images64docker images6566# Remove an image67docker rmi node:20-alpine68```6970### Kontena7172Kontena ialah contoh yang sedang berjalan bagi sebuah imej. Anda boleh mencipta, memulakan, menghentikan dan memadamkan kontena.7374```bash75# Run a container76docker run -d --name my-app -p 3000:3000 node:20-alpine7778# List running containers79docker ps8081# List all containers (including stopped)82docker ps -a8384# Stop a container85docker stop my-app8687# Remove a container88docker rm my-app8990# View logs91docker logs my-app9293# Execute a command inside a running container94docker exec -it my-app sh95```9697## Menulis Dockerfile9899Dockerfile ialah fail teks dengan arahan untuk membina imej. Setiap arahan mencipta satu lapisan.100101### Dockerfile Asas untuk Aplikasi Node.js102103```dockerfile104# Use an official Node.js runtime as base image105FROM node:20-alpine106107# Set working directory108WORKDIR /app109110# Copy package files first (better caching)111COPY package.json package-lock.json ./112113# Install dependencies114RUN npm ci --only=production115116# Copy application code117COPY . .118119# Expose the port the app runs on120EXPOSE 3000121122# Command to run the application123CMD ["node", "server.js"]124```125126### Membina dan Menjalankan127128```bash129# Build the image130docker build -t my-node-app .131132# Run the container133docker run -d -p 3000:3000 my-node-app134135# Visit http://localhost:3000136```137138## Multi-Stage Build139140Multi-stage build mengekalkan imej produksi anda kecil dengan memisahkan persekitaran build daripada runtime.141142```dockerfile143# Stage 1: Build144FROM node:20-alpine AS builder145WORKDIR /app146COPY package.json package-lock.json ./147RUN npm ci148COPY . .149RUN npm run build150151# Stage 2: Production152FROM node:20-alpine AS runner153WORKDIR /app154COPY --from=builder /app/dist ./dist155COPY --from=builder /app/node_modules ./node_modules156COPY --from=builder /app/package.json ./157EXPOSE 3000158CMD ["node", "dist/server.js"]159```160161Ini menghasilkan imej yang hanya mengandungi output yang dikompilasi dan kebergantungan produksi - tiada kod sumber, tiada kebergantungan pembangunan, tiada alat build.162163### Contoh Multi-Stage Next.js164165```dockerfile166FROM node:20-alpine AS deps167WORKDIR /app168COPY package.json package-lock.json ./169RUN npm ci170171FROM node:20-alpine AS builder172WORKDIR /app173COPY --from=deps /app/node_modules ./node_modules174COPY . .175RUN npm run build176177FROM node:20-alpine AS runner178WORKDIR /app179ENV NODE_ENV=production180COPY --from=builder /app/public ./public181COPY --from=builder /app/.next/standalone ./182COPY --from=builder /app/.next/static ./.next/static183EXPOSE 3000184CMD ["node", "server.js"]185```186187## Volum: Data Kekal188189Secara lalai, data dalam kontena hilang apabila kontena dipadamkan. Volum menyelesaikan masalah ini.190191```bash192# Create a named volume193docker volume create my-data194195# Run with a volume196docker run -d -v my-data:/app/data my-app197198# Bind mount (map host directory to container)199docker run -d -v $(pwd)/data:/app/data my-app200201# List volumes202docker volume ls203```204205## Rangkaian206207Docker mencipta rangkaian terpencil untuk kontena berkomunikasi.208209```bash210# Create a custom network211docker network create my-network212213# Run containers on the same network214docker run -d --name api --network my-network my-api215docker run -d --name db --network my-network postgres:16216217# Containers can reach each other by name218# From "api" container: postgres://db:5432219```220221```mermaid222graph LR223 subgraph "my-network"224 API[api container\nport 3000] -- "db:5432" --> DB[db container\nport 5432]225 end226 User -- "localhost:3000" --> API227```228229## Docker Compose230231Docker Compose membolehkan anda mendefinisi dan menjalankan aplikasi berbilang kontena dengan satu fail YAML.232233### docker-compose.yml234235```yaml236services:237 api:238 build: ./api239 ports:240 - "3000:3000"241 environment:242 - DATABASE_URL=postgres://user:pass@db:5432/mydb243 depends_on:244 - db245246 db:247 image: postgres:16-alpine248 environment:249 - POSTGRES_USER=user250 - POSTGRES_PASSWORD=pass251 - POSTGRES_DB=mydb252 volumes:253 - pgdata:/var/lib/postgresql/data254 ports:255 - "5432:5432"256257 redis:258 image: redis:7-alpine259 ports:260 - "6379:6379"261262volumes:263 pgdata:264```265266### Arahan267268```bash269# Start all services270docker compose up -d271272# View logs273docker compose logs -f274275# Stop all services276docker compose down277278# Rebuild and restart279docker compose up -d --build280281# Scale a service282docker compose up -d --scale api=3283```284285## .dockerignore286287Seperti `.gitignore`, fail ini menghalang fail yang tidak diperlukan daripada disalin ke dalam imej.288289```plaintext290node_modules291.git292.env293*.md294.next295dist296coverage297```298299## Amalan Terbaik untuk Produksi300301### 1. Gunakan Imej Asas yang Kecil302303```dockerfile304# Bad: 1GB+305FROM node:20306307# Good: ~180MB308FROM node:20-alpine309```310311### 2. Jangan Jalankan sebagai Root312313```dockerfile314FROM node:20-alpine315RUN addgroup -S app && adduser -S app -G app316USER app317WORKDIR /home/app318COPY --chown=app:app . .319```320321### 3. Gunakan Tag Imej yang Khusus322323```dockerfile324# Bad: can change unexpectedly325FROM node:latest326327# Good: pinned version328FROM node:20.11-alpine3.19329```330331### 4. Manfaatkan Cache Build332333Susun arahan Dockerfile anda daripada yang paling jarang hingga paling kerap berubah:334335```dockerfile336FROM node:20-alpine337WORKDIR /app338339# These change rarely - cached340COPY package.json package-lock.json ./341RUN npm ci --only=production342343# This changes often - not cached344COPY . .345```346347### 5. Pemeriksaan Kesihatan348349```dockerfile350HEALTHCHECK --interval=30s --timeout=3s --retries=3 \351 CMD wget -qO- http://localhost:3000/health || exit 1352```353354### 6. Gunakan Pemboleh Ubah Persekitaran355356```dockerfile357ENV NODE_ENV=production358ENV PORT=3000359```360361## Helaian Rujukan Pantas Arahan Docker Biasa362363```bash364# Images365docker build -t name:tag . # Build image366docker images # List images367docker rmi image_name # Remove image368docker image prune # Remove unused images369370# Containers371docker run -d -p 3000:3000 image # Run detached372docker ps # List running373docker stop container_name # Stop374docker rm container_name # Remove375docker logs -f container_name # Follow logs376docker exec -it container sh # Shell into container377378# Compose379docker compose up -d # Start services380docker compose down # Stop services381docker compose logs -f # Follow all logs382docker compose ps # List services383384# Cleanup385docker system prune -a # Remove everything unused386```387388## Dari Docker ke Kubernetes389390Docker menguruskan kontena individu. Apabila anda perlu mengorkestra ratusan kontena merentasi beberapa pelayan, anda memerlukan Kubernetes. Docker dan Kubernetes saling melengkapi:3913921. **Docker**: membina dan menjalankan kontena3932. **Kubernetes**: mengorkestra kontena pada skala besar (penjadualan, penskalaan, penyembuhan sendiri)394395Jika anda berminat dengan langkah seterusnya, lihat artikel saya tentang Pengenalan kepada Kubernetes.396397## Kesimpulan398399Docker ialah kemahiran asas untuk pembangun moden. Ia menghapuskan ketidakseragaman persekitaran, memudahkan deployment, dan merupakan asas untuk orkestrasi kontena dengan Kubernetes. Mulakan dengan Dockerfile mudah, beralih ke Docker Compose untuk aplikasi berbilang perkhidmatan, dan amalkan multi-stage build serta amalan terbaik keselamatan apabila anda berkembang.400401Cara terbaik untuk belajar Docker ialah meng-containerize projek yang sudah anda kerjakan. Mulakan hari ini.402
:Docker untuk Pemula: Dari Image Pertama hingga Deploy Produksilines 1-402 (END) — press q to close