Tuần 1 - Ngày 2: Cài Đặt Docker và Các Lệnh Cơ Bản
Mục tiêu học tập
- Cài đặt Docker Desktop trên Mac/Windows hoặc Docker Engine trên Linux
- Nắm vững vòng đời của container: run, stop, rm
- Phân biệt image và container
- Biết cách xem logs, exec vào container đang chạy
- Hiểu cơ chế pull từ public registry (Docker Hub)
1. Cài đặt Docker
macOS
# Cách 1: tải Docker Desktop từ trang chủ
# https://docs.docker.com/desktop/install/mac-install/
# Có bản Intel và Apple Silicon (M1/M2/M3/M4) — chọn đúng chip
# Cách 2: dùng Homebrew (khuyến nghị)
brew install --cask docker
# Sau khi cài, mở Docker Desktop app, đợi daemon khởi động
docker --version
# Docker version 27.x.x
Windows
# Yêu cầu: WSL2 đã bật (Windows 10/11)
# Tải Docker Desktop: https://docs.docker.com/desktop/install/windows-install/
# Hoặc dùng winget
winget install Docker.DockerDesktop
# Verify
docker --version
Linux (Ubuntu/Debian)
# Thêm Docker apt repo chính thức (không dùng apt install docker.io — phiên bản cũ)
curl -fsSL https://get.docker.com | sh
# Thêm user hiện tại vào group docker (tránh phải gõ sudo mỗi lần)
sudo usermod -aG docker $USER
newgrp docker # hoặc đăng xuất và đăng nhập lại
# Bật Docker service
sudo systemctl enable --now docker
# Verify
docker --version
docker run hello-world
Verify cài đặt
docker --version # Docker version 27.x.x
docker info # thông tin daemon, storage driver, runtime
docker run hello-world # test kéo image và chạy container đơn giản
2. Image vs Container
Phân biệt cốt lõi
- Một image có thể tạo ra nhiều container cùng lúc
- Mỗi container có writable layer riêng — dữ liệu write trong container mặc định mất khi container bị xoá
- Dùng volume để persist data (sẽ học ở Day 4)
3. Các lệnh cơ bản — vòng đời container
Pull image từ registry
# Pull image từ Docker Hub (mặc định)
docker pull nginx:1.27
docker pull ubuntu:22.04
docker pull node:20-alpine
# Pull từ Amazon ECR Public
docker pull public.ecr.aws/nginx/nginx:1.27
# Xem danh sách images đã pull về
docker images
# REPOSITORY TAG IMAGE ID CREATED SIZE
# nginx 1.27 abc123def456 2 days ago 188MB
# ubuntu 22.04 def456ghi789 3 weeks ago 77.9MB
# node 20-alpine ghi789jkl012 1 week ago 135MB
Chạy container
# Chạy và thoát ngay (foreground)
docker run nginx:1.27
# Chạy background (detached)
docker run -d nginx:1.27
# Đặt tên container
docker run -d --name my-nginx nginx:1.27
# Map port host:container
docker run -d -p 8080:80 --name my-nginx nginx:1.27
# Truy cập: http://localhost:8080
# Chạy tương tác (interactive + tty)
docker run -it ubuntu:22.04 bash
# Tự động xoá container sau khi exit
docker run --rm ubuntu:22.04 echo "hello"
# Set environment variables
docker run -d \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=mydb \
--name my-mysql \
mysql:8.0
# Mount volume (host path:container path)
docker run -d \
-p 8080:80 \
-v /home/user/html:/usr/share/nginx/html:ro \
--name my-nginx \
nginx:1.27
Xem container đang chạy
# Chỉ container đang running
docker ps
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# a1b2c3d4e5f6 nginx:1.27 "/docker-…" 2 mins ago Up 2 minutes 0.0.0.0:8080->80/tcp my-nginx
# Tất cả container (kể cả đã stop)
docker ps -a
# Chỉ lấy container IDs
docker ps -q
Stop, Start, Restart
# Stop graceful (SIGTERM → đợi 10s → SIGKILL)
docker stop my-nginx
# Stop ngay lập tức (SIGKILL)
docker kill my-nginx
# Start lại container đã stop
docker start my-nginx
# Restart
docker restart my-nginx
Xem logs
# Xem toàn bộ logs
docker logs my-nginx
# Follow logs (như tail -f)
docker logs -f my-nginx
# 50 dòng cuối
docker logs --tail 50 my-nginx
# Logs kèm timestamp
docker logs -t my-nginx
# Lọc theo thời gian
docker logs --since 5m my-nginx # 5 phút gần nhất
docker logs --since 2024-01-01 my-nginx
Exec vào container đang chạy
# Mở bash shell trong container đang running
docker exec -it my-nginx bash
# Chạy một lệnh đơn
docker exec my-nginx nginx -t # test nginx config
docker exec my-nginx cat /etc/nginx/nginx.conf
# Chạy với user khác
docker exec -it -u root my-nginx bash
Xoá container và image
# Xoá container đã stop
docker rm my-nginx
# Xoá container đang running (force)
docker rm -f my-nginx
# Xoá tất cả container đã stop
docker container prune
# Xoá image
docker rmi nginx:1.27
# Xoá tất cả unused images, containers, networks, build cache
docker system prune -a
# Cẩn thận: lệnh này xoá khá nhiều thứ
4. Inspect và Stats
# Xem chi tiết cấu hình container (JSON output)
docker inspect my-nginx
# Chỉ lấy IP address của container
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-nginx
# Xem CPU/RAM usage real-time
docker stats
docker stats my-nginx # chỉ một container
# Xem port mappings
docker port my-nginx
# Copy file giữa host và container
docker cp my-nginx:/etc/nginx/nginx.conf ./nginx.conf # container → host
docker cp ./index.html my-nginx:/usr/share/nginx/html/ # host → container
5. Hiểu registry và image tag
Best practice: Luôn pin tag cụ thể (:1.27) thay vì :latest trong production — :latest thay đổi khi image được update và có thể gây break.
6. Docker Hub quick tour
# Tìm image trên Docker Hub
docker search nginx
docker search --filter is-official=true ubuntu
# Login vào Docker Hub (cần khi push private image)
docker login
# Username: your-dockerhub-username
# Password: your-password
# Logout
docker logout
Câu hỏi ôn tập
-
Lệnh nào để xem tất cả container (kể cả đã stop)?
Xem đáp án
docker ps -a(hoặcdocker container ls -a). Flag-a/--allhiển thị tất cả container bao gồm trạng tháiexited,created,paused. Không có-achỉ hiện container đangrunning. -
Sự khác biệt giữa
docker stopvàdocker killlà gì?Xem đáp án
docker stopgửi signal SIGTERM cho PID 1 trong container, đợi tối đa 10 giây (configurable với--time) để process tự dọn dẹp, sau đó mới gửi SIGKILL nếu vẫn chưa thoát.docker killgửi SIGKILL ngay lập tức (hoặc signal tùy chỉnh), không chờ.Dùng
docker stopcho graceful shutdown;docker killkhi container bị treo và không phản hồi SIGTERM. -
Flag nào trong
docker runđể container tự xoá sau khi exit?Xem đáp án
Flag
--rm. Ví dụ:docker run --rm ubuntu:22.04 echo "hello"— container bị xoá ngay khi process kết thúc. Hữu ích cho one-shot commands, testing, hay CI jobs để tránh tích lũy container rác. -
Tại sao không nên dùng tag
:latesttrong production?Xem đáp án
Tag
:latestlà mutable — khi image được push mới lên registry,:latesttrỏ sang image mới. Deploy lại cùng tag:latestcó thể kéo về image khác so với lần deploy trước, gây inconsistency giữa các servers hoặc rollback không thể thực hiện đúng. Dùng tag cụ thể như:1.2.3hoặc:sha256-abc123để đảm bảo reproducible deployment. -
Dữ liệu ghi vào container mà không dùng volume sẽ như thế nào khi container bị xoá?
Xem đáp án
Dữ liệu bị mất vĩnh viễn. Container có một writable layer nằm trên các image layers (read-only). Khi container bị xoá (
docker rm), writable layer bị xoá theo. Để persist data, dùng named volume (-v mydata:/path) hoặc bind mount (-v /host/path:/container/path).
Bài tập thực hành
# 1. Chạy nginx, map port 8080, đặt tên "web"
docker run -d -p 8080:80 --name web nginx:1.27
curl http://localhost:8080 # hoặc mở browser
# 2. Xem logs của nginx
docker logs web
docker logs -f web # Ctrl+C để thoát
# 3. Exec vào container, kiểm tra process
docker exec -it web bash
ps aux
ls /usr/share/nginx/html
exit
# 4. Dừng và xoá
docker stop web
docker rm web
# 5. Chạy MySQL với env vars
docker run -d \
--name mydb \
-e MYSQL_ROOT_PASSWORD=secret123 \
-e MYSQL_DATABASE=testdb \
-p 3306:3306 \
mysql:8.0
# Kiểm tra đang chạy
docker ps
docker logs mydb
# Connect vào mysql (nếu đã cài mysql client)
mysql -h 127.0.0.1 -P 3306 -u root -psecret123 testdb
# Dọn dẹp
docker rm -f mydb
Tài liệu tham khảo chính thức
- Install Docker Desktop on Mac
- Install Docker Engine on Ubuntu
- docker run reference
- docker logs reference
- docker exec reference
Tiếp theo: Ngày 3 — Viết Dockerfile