Docker 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.
Apa itu Docker?
Docker 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.
Kontena vs Mesin Maya
| Aspek | Kontena | Mesin Maya |
|---|---|---|
| Permulaan | Saat | Minit |
| Saiz | MB | GB |
| OS | Berkongsi kernel hos | OS tetamu penuh |
| Pengasingan | Tahap proses | Tahap perkakasan |
| Prestasi | Hampir natif | Beban tambahan dari hypervisor |
| Kepadatan | Ratusan setiap hos | Puluhan setiap hos |
Memasang Docker
# macOS brew install --cask docker # Ubuntu/Debian curl -fsSL https://get.docker.com | sh sudo usermod -aG docker $USER # Verify installation docker --version docker run hello-world
Konsep Teras
Imej
Imej ialah templat baca-sahaja dengan arahan untuk mencipta kontena. Anggap ia sebagai gambar kilat aplikasi anda dan persekitarannya.
# Pull an image from Docker Hub docker pull node:20-alpine # List local images docker images # Remove an image docker rmi node:20-alpine
Kontena
Kontena ialah contoh yang sedang berjalan bagi sebuah imej. Anda boleh mencipta, memulakan, menghentikan dan memadamkan kontena.
# Run a container docker run -d --name my-app -p 3000:3000 node:20-alpine # List running containers docker ps # List all containers (including stopped) docker ps -a # Stop a container docker stop my-app # Remove a container docker rm my-app # View logs docker logs my-app # Execute a command inside a running container docker exec -it my-app sh
Menulis Dockerfile
Dockerfile ialah fail teks dengan arahan untuk membina imej. Setiap arahan mencipta satu lapisan.
Dockerfile Asas untuk Aplikasi Node.js
# Use an official Node.js runtime as base image FROM node:20-alpine # Set working directory WORKDIR /app # Copy package files first (better caching) COPY package.json package-lock.json ./ # Install dependencies RUN npm ci --only=production # Copy application code COPY . . # Expose the port the app runs on EXPOSE 3000 # Command to run the application CMD ["node", "server.js"]
Membina dan Menjalankan
# Build the image docker build -t my-node-app . # Run the container docker run -d -p 3000:3000 my-node-app # Visit http://localhost:3000
Multi-Stage Build
Multi-stage build mengekalkan imej produksi anda kecil dengan memisahkan persekitaran build daripada runtime.
# Stage 1: Build FROM node:20-alpine AS builder WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY . . RUN npm run build # Stage 2: Production FROM node:20-alpine AS runner WORKDIR /app COPY /app/dist ./dist COPY /app/node_modules ./node_modules COPY /app/package.json ./ EXPOSE 3000 CMD ["node", "dist/server.js"]
Ini menghasilkan imej yang hanya mengandungi output yang dikompilasi dan kebergantungan produksi - tiada kod sumber, tiada kebergantungan pembangunan, tiada alat build.
Contoh Multi-Stage Next.js
FROM node:20-alpine AS deps WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci FROM node:20-alpine AS builder WORKDIR /app COPY /app/node_modules ./node_modules COPY . . RUN npm run build FROM node:20-alpine AS runner WORKDIR /app ENV NODE_ENV=production COPY /app/public ./public COPY /app/.next/standalone ./ COPY /app/.next/static ./.next/static EXPOSE 3000 CMD ["node", "server.js"]
Volum: Data Kekal
Secara lalai, data dalam kontena hilang apabila kontena dipadamkan. Volum menyelesaikan masalah ini.
# Create a named volume docker volume create my-data # Run with a volume docker run -d -v my-data:/app/data my-app # Bind mount (map host directory to container) docker run -d -v $(pwd)/data:/app/data my-app # List volumes docker volume ls
Rangkaian
Docker mencipta rangkaian terpencil untuk kontena berkomunikasi.
# Create a custom network docker network create my-network # Run containers on the same network docker run -d --name api --network my-network my-api docker run -d --name db --network my-network postgres:16 # Containers can reach each other by name # From "api" container: postgres://db:5432
Docker Compose
Docker Compose membolehkan anda mendefinisi dan menjalankan aplikasi berbilang kontena dengan satu fail YAML.
docker-compose.yml
services: api: build: ./api ports: - "3000:3000" environment: - DATABASE_URL=postgres://user:pass@db:5432/mydb depends_on: - db db: image: postgres:16-alpine environment: - POSTGRES_USER=user - POSTGRES_PASSWORD=pass - POSTGRES_DB=mydb volumes: - pgdata:/var/lib/postgresql/data ports: - "5432:5432" redis: image: redis:7-alpine ports: - "6379:6379" volumes: pgdata:
Arahan
# Start all services docker compose up -d # View logs docker compose logs -f # Stop all services docker compose down # Rebuild and restart docker compose up -d --build # Scale a service docker compose up -d --scale api=3
.dockerignore
Seperti .gitignore, fail ini menghalang fail yang tidak diperlukan daripada disalin ke dalam imej.
node_modules .git .env *.md .next dist coverage
Amalan Terbaik untuk Produksi
1. Gunakan Imej Asas yang Kecil
# Bad: 1GB+ FROM node:20 # Good: ~180MB FROM node:20-alpine
2. Jangan Jalankan sebagai Root
FROM node:20-alpine RUN addgroup -S app && adduser -S app -G app USER app WORKDIR /home/app COPY . .
3. Gunakan Tag Imej yang Khusus
# Bad: can change unexpectedly FROM node:latest # Good: pinned version FROM node:20.11-alpine3.19
4. Manfaatkan Cache Build
Susun arahan Dockerfile anda daripada yang paling jarang hingga paling kerap berubah:
FROM node:20-alpine WORKDIR /app # These change rarely - cached COPY package.json package-lock.json ./ RUN npm ci --only=production # This changes often - not cached COPY . .
5. Pemeriksaan Kesihatan
HEALTHCHECK \ CMD wget -qO- http://localhost:3000/health || exit 1
6. Gunakan Pemboleh Ubah Persekitaran
ENV NODE_ENV=production ENV PORT=3000
Helaian Rujukan Pantas Arahan Docker Biasa
# Images docker build -t name:tag . # Build image docker images # List images docker rmi image_name # Remove image docker image prune # Remove unused images # Containers docker run -d -p 3000:3000 image # Run detached docker ps # List running docker stop container_name # Stop docker rm container_name # Remove docker logs -f container_name # Follow logs docker exec -it container sh # Shell into container # Compose docker compose up -d # Start services docker compose down # Stop services docker compose logs -f # Follow all logs docker compose ps # List services # Cleanup docker system prune -a # Remove everything unused
Dari Docker ke Kubernetes
Docker menguruskan kontena individu. Apabila anda perlu mengorkestra ratusan kontena merentasi beberapa pelayan, anda memerlukan Kubernetes. Docker dan Kubernetes saling melengkapi:
- Docker: membina dan menjalankan kontena
- Kubernetes: mengorkestra kontena pada skala besar (penjadualan, penskalaan, penyembuhan sendiri)
Jika anda berminat dengan langkah seterusnya, lihat artikel saya tentang Pengenalan kepada Kubernetes.
Kesimpulan
Docker 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.
Cara terbaik untuk belajar Docker ialah meng-containerize projek yang sudah anda kerjakan. Mulakan hari ini.