Appearance
Buổi 2: Docker Images & Dockerfile
🎯 Mục tiêu
- Hiểu Docker Image là gì và cấu trúc layer
- Biết cách pull, list, remove images
- Viết Dockerfile cơ bản với các instructions chính
- Build image từ Dockerfile
- Push image lên Docker Hub
1. Docker Image là gì?
Định nghĩa
Docker Image là một template read-only chứa:
- Hệ điều hành cơ sở (Ubuntu, Alpine, Debian...)
- Runtime (Node.js, Python, Java...)
- Thư viện & dependencies
- Code ứng dụng
- Cấu hình chạy
Image → là bản thiết kế (blueprint) Container → là instance đang chạy từ image đó
┌─────────────────────────────────────┐
│ Docker Image │
│ (Read-only template) │
│ │
│ ┌───────────────────────────────┐ │
│ │ Layer 4: COPY app code │ │
│ ├───────────────────────────────┤ │
│ │ Layer 3: RUN npm install │ │
│ ├───────────────────────────────┤ │
│ │ Layer 2: RUN apt-get update │ │
│ ├───────────────────────────────┤ │
│ │ Layer 1: FROM node:20-alpine │ │
│ └───────────────────────────────┘ │
└─────────────────────────────────────┘
│ │ │
▼ ▼ ▼
Container A Container B Container C
(writable) (writable) (writable)Image layers – hệ thống lớp
Mỗi instruction trong Dockerfile tạo một layer. Docker cache các layer để tái sử dụng → build nhanh hơn.
2. Quản lý Images
Pull image từ Docker Hub
bash
# Pull image chính thức
$ docker pull nginx
$ docker pull node:20-alpine
$ docker pull python:3.12-slim
# Pull với tag cụ thể
$ docker pull ubuntu:22.04
# Pull từ registry khác
$ docker pull ghcr.io/owner/image:tagXem danh sách images
bash
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest a6bd71f48f68 2 days ago 187MB
node 20-alpine 1a2b3c4d5e6f 1 week ago 130MB
python 3.12-slim 7a8b9c0d1e2f 3 days ago 52MB
ubuntu 22.04 4a5b6c7d8e9f 2 weeks ago 77MBXóa images
bash
# Xóa một image
$ docker rmi nginx
# Xóa image bằng ID
$ docker rmi a6bd71f48f68
# Xóa tất cả image không dùng
$ docker image prune -aSo sánh base images phổ biến
| Base Image | Dung lượng | Use case |
|---|---|---|
ubuntu:22.04 | ~77MB | Full OS, apt-get |
debian:bookworm-slim | ~80MB | Stable, nhiều packages |
alpine:3.19 | ~7MB | Siêu nhẹ, dùng apk |
node:20 | ~1GB | Full Node.js + OS |
node:20-alpine | ~130MB | Node.js trên Alpine |
node:20-slim | ~200MB | Node.js minimal Debian |
python:3.12 | ~1GB | Full Python + OS |
python:3.12-slim | ~52MB | Python minimal |
💡 Khuyến nghị
Luôn dùng tag cụ thể (ví dụ node:20-alpine) thay vì latest để đảm bảo tính nhất quán.
3. Dockerfile – Tạo image riêng
Dockerfile là gì?
Dockerfile là file text chứa các instructions để Docker build ra một image.
Ví dụ: Node.js app đơn giản
Tạo cấu trúc project:
my-app/
├── Dockerfile
├── package.json
├── package-lock.json
└── server.jsserver.js:
javascript
const http = require('http');
const PORT = 3000;
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello from Docker! 🐳\n');
});
server.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});Dockerfile:
dockerfile
# Bước 1: Chọn base image
FROM node:20-alpine
# Bước 2: Đặt thư mục làm việc trong container
WORKDIR /app
# Bước 3: Copy file package trước (tận dụng cache)
COPY package*.json ./
# Bước 4: Cài đặt dependencies
RUN npm install --production
# Bước 5: Copy toàn bộ code
COPY . .
# Bước 6: Khai báo port
EXPOSE 3000
# Bước 7: Lệnh chạy khi start container
CMD ["node", "server.js"]4. Các Dockerfile Instructions quan trọng
| Instruction | Ý nghĩa | Ví dụ |
|---|---|---|
FROM | Base image | FROM node:20-alpine |
WORKDIR | Thư mục làm việc | WORKDIR /app |
COPY | Copy file từ host vào image | COPY . . |
ADD | Copy + giải nén + URL | ADD archive.tar.gz /app |
RUN | Chạy lệnh khi build | RUN npm install |
CMD | Lệnh mặc định khi run | CMD ["node", "app.js"] |
ENTRYPOINT | Lệnh cố định khi run | ENTRYPOINT ["python"] |
EXPOSE | Khai báo port | EXPOSE 3000 |
ENV | Biến môi trường | ENV NODE_ENV=production |
ARG | Biến lúc build | ARG VERSION=1.0 |
LABEL | Metadata cho image | LABEL maintainer="dev" |
USER | Chạy với user nào | USER node |
CMD vs ENTRYPOINT
dockerfile
# CMD – có thể bị override khi docker run
CMD ["node", "server.js"]
# docker run myapp → chạy node server.js
# docker run myapp bash → chạy bash (override CMD)
# ENTRYPOINT – không bị override
ENTRYPOINT ["node"]
CMD ["server.js"]
# docker run myapp → chạy node server.js
# docker run myapp app.js → chạy node app.js (CMD bị override)COPY vs ADD
dockerfile
# COPY – chỉ copy file/thư mục (KHUYẾN NGHỊ)
COPY ./src /app/src
COPY package.json /app/
# ADD – copy + giải nén tự động + hỗ trợ URL
ADD archive.tar.gz /app/ # tự giải nén
ADD https://example.com/file /app/ # tải từ URL⚠️ Lưu ý
Luôn dùng COPY trừ khi cần giải nén. ADD có hành vi phức tạp hơn và dễ gây nhầm lẫn.
5. Build Image
Lệnh docker build
bash
# Build image từ Dockerfile trong thư mục hiện tại
$ docker build -t my-node-app .
# Build với tag version
$ docker build -t my-node-app:1.0 .
# Build với build argument
$ docker build --build-arg VERSION=2.0 -t my-app:2.0 .
# Xem quá trình build chi tiết
$ docker build --progress=plain -t my-app .| Flag | Ý nghĩa |
|---|---|
-t | Tag – đặt tên:version cho image |
. | Build context – thư mục chứa Dockerfile |
-f | Chỉ định Dockerfile khác tên mặc định |
--no-cache | Build không dùng cache |
--build-arg | Truyền build argument |
Ví dụ build và chạy
bash
# Build
$ docker build -t my-node-app:1.0 .
# Kiểm tra image
$ docker images | grep my-node-app
my-node-app 1.0 abc123def456 10 seconds ago 135MB
# Chạy container từ image
$ docker run -d -p 3000:3000 --name my-app my-node-app:1.0
# Kiểm tra
$ curl http://localhost:3000
Hello from Docker! 🐳6. Ví dụ: Dockerfile cho Python
dockerfile
FROM python:3.12-slim
WORKDIR /app
# Copy requirements trước (tận dụng cache)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy code
COPY . .
EXPOSE 8000
CMD ["python", "app.py"]7. Ví dụ: Dockerfile cho Go
dockerfile
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o main .
FROM alpine:3.19
WORKDIR /app
COPY --from=builder /app/main .
EXPOSE 8080
CMD ["./main"]🏋️ Bài tập thực hành
Bài 1: Pull và khám phá images
- Pull 3 images:
nginx,node:20-alpine,python:3.12-slim - So sánh dung lượng bằng
docker images - Kiểm tra chi tiết image:
docker inspect node:20-alpine
Bài 2: Viết Dockerfile đầu tiên
- Tạo file
server.jsnhư ví dụ ở trên - Viết
Dockerfilecho Node.js app - Build:
docker build -t my-first-app . - Chạy:
docker run -d -p 3000:3000 my-first-app - Mở
http://localhost:3000kiểm tra
Bài 3: Dockerfile cho static website
- Tạo file
index.htmlđơn giản - Viết Dockerfile dùng base
nginx:alpine - Copy
index.htmlvào/usr/share/nginx/html/ - Build và chạy trên port 8080
Bài 4: Tag và quản lý images
- Build image với nhiều tags:
myapp:1.0,myapp:latest - Liệt kê tất cả images
- Xóa image cũ, giữ lại bản mới nhất
- Dọn dẹp:
docker image prune