1. Docker là gì?

Docker là nền tảng giúp đóng gói và chạy ứng dụng trong các môi trường được gọi là container.

Một ứng dụng Backend thường phụ thuộc vào nhiều thành phần:

  • Ngôn ngữ lập trình và runtime như Go, PHP hoặc Node.js.
  • Thư viện và package.
  • Database như PostgreSQL hoặc MySQL.
  • Cache như Redis.
  • Biến môi trường và cấu hình.
  • Các công cụ hệ thống cần thiết để ứng dụng hoạt động.

Nếu mỗi developer tự cài đặt những thành phần này theo cách khác nhau, môi trường trên máy cá nhân có thể khác môi trường staging hoặc production. Điều đó dẫn đến những lỗi kiểu “máy tôi chạy được nhưng lên server lại lỗi”. Docker giúp chuẩn hóa môi trường chạy ứng dụng bằng cách đóng gói ứng dụng và các dependency cần thiết thành một image, sau đó tạo container từ image đó.

Docker giải quyết vấn đề gì?

Nhất quán môi trường: Các thành viên trong nhóm có thể chạy cùng image và cấu hình tương tự nhau.

Cô lập ứng dụng: Mỗi container có môi trường tiến trình và filesystem riêng theo cấu hình, giảm xung đột giữa các ứng dụng.

Triển khai thuận tiện: Image có thể được build một lần, lưu trong registry rồi triển khai trên các môi trường tương thích.

Khởi tạo nhanh: Container thường khởi động nhanh hơn máy ảo đầy đủ vì container chia sẻ kernel của hệ điều hành host.

Hỗ trợ CI/CD: Pipeline có thể build image, chạy test trong container và triển khai artifact nhất quán hơn.

2. Container là gì?

Container là một môi trường thực thi tiến trình được cô lập bằng các tính năng của hệ điều hành.

Một container thường có:

  • Một hoặc nhiều tiến trình.
  • Filesystem riêng theo image và các lớp ghi.
  • Cấu hình mạng.
  • Giới hạn tài nguyên nếu được thiết lập.
  • Các biến môi trường và cấu hình runtime.

Điểm quan trọng là container không phải một máy ảo đầy đủ. Container Linux thông thường sử dụng kernel Linux của host, trong khi máy ảo có hệ điều hành khách với kernel riêng.

3. Image là gì?

Docker Image là một template bất biến dùng để tạo container. Image được tổ chức thành các lớp filesystem và metadata.

Ví dụ:

docker pull nginx:alpine

Lệnh này tải image Nginx với tag alpine.

Sau đó có thể tạo container:

docker run -d --name web -p 8080:80 nginx:alpine

Ứng dụng Nginx chạy bên trong container và cổng 80 của container được ánh xạ ra cổng 8080 trên host.

Image và Container khác nhau thế nào?

Có thể hình dung:

  • Image: Bản mẫu để tạo ứng dụng.
  • Container: Một instance đang hoặc đã chạy từ image.

Một image có thể được dùng để tạo nhiều container.

Ví dụ, cùng image của một API có thể tạo ra nhiều instance chạy độc lập. Mỗi instance có trạng thái runtime riêng, mặc dù chúng có thể cùng sử dụng một volume hoặc một database bên ngoài.

4. Docker Engine và Docker Architecture

Docker thường được sử dụng theo mô hình client-server.

Các thành phần chính gồm:

Docker Client: Công cụ người dùng tương tác, thường là lệnh docker.

Docker Daemon (dockerd): Thành phần quản lý các đối tượng Docker như image, container, network và volume.

Docker API: Giao diện để client giao tiếp với daemon.

Registry: Nơi lưu trữ và phân phối image, chẳng hạn Docker Hub hoặc private registry.

Luồng thông thường:

  1. Developer chạy docker build.
  2. Docker xử lý Dockerfile và build context để tạo image.
  3. Image có thể được đẩy lên registry.
  4. Môi trường triển khai lấy image từ registry.
  5. Docker tạo và chạy container từ image.

Trên Linux, Docker Engine thường chạy trực tiếp trên kernel Linux. Trên macOS và Windows, các giải pháp Docker Desktop thường sử dụng một môi trường Linux VM hoặc cơ chế tương đương để chạy Linux container.

5. Dockerfile là gì?

Dockerfile là file mô tả cách build một Docker image.

Ví dụ Dockerfile cho ứng dụng Go:

FROM golang:1.25 AS builder

WORKDIR /src

COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux \
    go build -o /out/api ./cmd/api

FROM scratch

COPY --from=builder /out/api /api

ENTRYPOINT ["/api"]

Ví dụ này minh họa multi-stage build: dùng image Go để biên dịch, sau đó chỉ đưa binary vào image cuối.

6. Build context và .dockerignore

Khi chạy:

docker build -t my-api:dev .

Dấu . là build context. Docker sử dụng các file trong context theo cách phù hợp với builder và Dockerfile.

Nếu context chứa toàn bộ repository, thư mục build output, file log, .git, hoặc các file không cần thiết, quá trình build có thể chậm và vô tình đưa dữ liệu nhạy cảm vào context.

Tạo file .dockerignore:

.git
.env
.env.*
!.env.example
node_modules
vendor
tmp
coverage
*.log

Đây chỉ là ví dụ. Hãy điều chỉnh theo công nghệ và Dockerfile thực tế.

Nếu ứng dụng cần vendor hoặc node_modules được tạo sẵn trong quá trình build, không nên sao chép chúng từ host một cách thiếu kiểm soát. Thông thường nên cài dependency bên trong quá trình build để bảo đảm tính nhất quán.

7. Multi-stage Build

Multi-stage build cho phép sử dụng nhiều stage trong một Dockerfile để tách môi trường build và môi trường runtime.

Ví dụ:

FROM golang:1.25 AS builder

WORKDIR /src

COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux \
    go build -o /out/api ./cmd/api

FROM debian:bookworm-slim

RUN apt-get update \
    && apt-get install -y --no-install-recommends ca-certificates \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

COPY --from=builder /out/api ./api

CMD ["./api"]

Stage đầu chứa compiler và dependency phục vụ build. Stage cuối chỉ chứa runtime cần thiết cùng binary đã biên dịch.

Lợi ích:

  • Giảm kích thước image cuối trong nhiều trường hợp.
  • Hạn chế công cụ build không cần thiết trong production.
  • Tách dependency build khỏi dependency runtime.
  • Giảm bề mặt tấn công khi image runtime chứa ít thành phần hơn.

Tuy nhiên, image nhỏ không phải mục tiêu duy nhất. Cần chọn base image tương thích, cập nhật bảo mật và bảo đảm ứng dụng thực sự chạy được.

8. Docker Networking

Container thường cần giao tiếp với nhau và với các hệ thống bên ngoài. Docker networking cung cấp các cơ chế kết nối cho mục đích đó.

Port Mapping

Ví dụ:

docker run -d \
  --name web \
  -p 8080:80 \
  nginx:alpine

Cú pháp -p 8080:80 ánh xạ cổng 8080 của host đến cổng 80 của container.

Nếu không publish cổng, dịch vụ trong container vẫn có thể truy cập được từ các container khác trên network phù hợp, nhưng không mặc nhiên được publish ra host.

Bridge Network

Bridge network thường được dùng cho các container trên cùng một Docker host.

Docker Compose thường tự tạo network cho project để các service có thể giao tiếp bằng tên service.

Có thể tạo network riêng:

docker network create app-network

Sau đó gắn các container vào network phù hợp.

9. Docker Compose là gì?

Docker Compose là công cụ giúp định nghĩa và quản lý ứng dụng gồm nhiều service thông qua file YAML.

Một Backend điển hình có thể gồm:

  • API.
  • PostgreSQL.
  • Redis.
  • Worker.
  • Message broker.

Thay vì chạy từng lệnh docker run thủ công, ta mô tả các service trong một file Compose.

Healthcheck và Dependency Readiness

Container chạy không có nghĩa ứng dụng bên trong đã sẵn sàng.

Ví dụ, PostgreSQL container có thể đã được tạo nhưng database vẫn đang khởi tạo. Nếu API kết nối quá sớm, ứng dụng có thể nhận lỗi kết nối.

Healthcheck giúp Docker xác định trạng thái sức khỏe theo một lệnh kiểm tra. Với Compose, depends_on kết hợp condition: service_healthy có thể giúp trì hoãn khởi động service phụ thuộc cho đến khi dependency được đánh giá là healthy.

10. Kết luận

Docker giúp chuẩn hóa cách đóng gói, chạy và phân phối ứng dụng. Để sử dụng hiệu quả, cần hiểu rõ mối quan hệ giữa image, container, Dockerfile, networking, volumes và Docker Compose.

Với Backend Developer, những kỹ năng quan trọng nhất không chỉ là biết build image mà còn phải:

  • Tạo image có thể tái lập và dễ bảo trì.
  • Hiểu cách các container giao tiếp với nhau.
  • Bảo đảm dữ liệu được lưu trữ bền vững.
  • Quản lý cấu hình và secret an toàn.
  • Xử lý startup, shutdown và dependency readiness.
  • Tích hợp Docker với testing và CI/CD.
  • Phân biệt công cụ chạy container với nền tảng điều phối container.

Bài viết khác

Use ProxySQL as database gateway for mysql database

Use pgBouncer as database gateway for PostgreSQL database

Build for global scale: AFK scale cube and basic rule to build an application for global scale

REF https://akfpartners.com/growth-blog/scale-cube

Use AWS to deploy your applications and services

Amazon Web Services (AWS) is a cloud computing platform that provides a wide range of services to help businesses and individuals build and deploy applications in the cloud. AWS offers a variety of services such as compute, storage, databases, networking, security, and more. In this guide, we will walk through the steps to get started […]

Use docker to run go project

Docker is a powerful tool that enables developers to create, deploy and run applications in a containerized environment. Using Docker to run Go projects has many advantages, including the ability to isolate your application from the underlying operating system, simplifying the deployment process, and allowing for greater scalability and flexibility. In this guide, we will […]

Install WSL for windows 10

1/ Enable feature Windows Subsystem for Linux Head to Control Panel > Programs > Turn Windows Features On Or Off. Enable the “Windows Subsystem for Linux” option in the list, and then click the “OK” button. Restart computer Now you can type on console: wsl –help 2/ Download ubuntu 18 from Microsoft Store or open […]

Leave a Reply

Your email address will not be published. Required fields are marked *