</>Học Dev
Bài học

Tuần 1 - Ngày 2: Cài Đặt Docker và Các Lệnh Cơ Bản

Tuần 1 – Ngày 2

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

Image(read-onlytemplate)Layer3:Appcode(COPY)Layer2:Node.js20(RUNaptinstallnodejs)Layer1:Ubuntu22.04(FROMubuntu:22.04)dockerrunContainer(image+writablelayer)Writablelayer:logs,tempfiles,state(mtkhicontainerbxoá)[Imagelayersbêndưiread-only]
  • 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

dockerpullnginx:1.27Tag(version;"latest"nếukhôngghi)RepositorynameRegistry(docker.iomcđnh)dockerpullpublic.ecr.aws/nginx/nginx:1.27TagRepositoryNamespaceRegistry(ECRPublic)

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

  1. Lệnh nào để xem tất cả container (kể cả đã stop)?

    Xem đáp án

    docker ps -a (hoặc docker container ls -a). Flag -a / --all hiển thị tất cả container bao gồm trạng thái exited, created, paused. Không có -a chỉ hiện container đang running.

  2. Sự khác biệt giữa docker stopdocker kill là gì?

    Xem đáp án

    docker stop gử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 kill gửi SIGKILL ngay lập tức (hoặc signal tùy chỉnh), không chờ.

    Dùng docker stop cho graceful shutdown; docker kill khi container bị treo và không phản hồi SIGTERM.

  3. 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.

  4. Tại sao không nên dùng tag :latest trong production?

    Xem đáp án

    Tag :latest là mutable — khi image được push mới lên registry, :latest trỏ sang image mới. Deploy lại cùng tag :latest có 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.3 hoặc :sha256-abc123 để đảm bảo reproducible deployment.

  5. 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


Tiếp theo: Ngày 3 — Viết Dockerfile