+1

Tại sao Docker chạy trên Windows thì "ngon", nhưng lên Linux lại lỗi? Cơn ác mộng Naming Case-Sensitive

Chào anh em,

Đã bao giờ bạn gặp tình huống: Code chạy mượt mà trên máy local (Windows/macOS), nhưng vừa đóng gói vào Docker hoặc deploy lên server Linux là hệ thống báo lỗi Module not found chưa?

Thủ phạm thường không nằm ở Logic code, mà nằm ở một "lời nói dối" ngọt ngào của hệ điều hành bạn đang dùng.

1. Sự khác biệt về Triết lý Hệ điều hành (Kernel Level)

Mọi rắc rối bắt đầu từ cách các hệ điều hành quản lý File System (Hệ thống tệp tin):

  • Windows (NTFS): Triết lý của Microsoft là ưu tiên sự tiện dụng. Với Windows, User.service.tsuser.service.ts về mặt ngữ nghĩa là một. Do đó, NTFS được thiết kế là Case-Insensitive (Không phân biệt hoa thường).
  • Linux (Ext4/XFS): Triết lý của Linux là sự chính xác tuyệt đối. Trong bảng mã ASCII, chữ 'U' (mã 65) và chữ 'u' (mã 117) là hai thực thể khác nhau. Linux coi User.tsuser.ts là hai tệp tin riêng biệt.

2. "Cú lừa" từ Docker trên máy Local

Có một sự thật là Docker trên Windows/macOS không chạy trực tiếp trên nhân OS đó. Nó chạy thông qua một máy ảo Linux siêu nhẹ (Linux VM).

Khi bạn mount code từ máy Windows (không phân biệt hoa thường) vào máy ảo Linux này:

  1. Bạn đặt tên file là UserMapper.ts.
  2. Bạn viết code: import { UserMapper } from './usermapper'.
  3. Windows bảo: "Ok, tôi hiểu bạn muốn tìm UserMapper".
  4. Nhưng khi Docker/Linux quét tệp tin, nó bảo: "Tôi không thấy file nào tên là usermapper (viết thường) cả!".

Kết quả: Hệ thống sập ngay tại bước khởi tạo (Runtime Error hoặc Build Error).

3. Vaccine cho lỗi Naming trong phát triển Node.js

Thay vì chỉ dựa vào sự cẩn thận của con người, chúng ta nên dùng công cụ để "ép" mọi thứ vào khuôn khổ. Trong dự án Open Source của mình là nodejs-quickstart-structure, mình đã xử lý vấn đề này bằng 3 lớp bảo vệ:

Lớp 1: ESLint Rule (Chặn từ trong trứng nước)

Sử dụng plugin eslint-plugin-import để báo lỗi ngay trên VS Code nếu path bạn import không khớp 100% với tên file thực tế.

"import/no-unresolved": "error"

Lớp 2: CI/CD Pipeline (Chốt chặn cuối cùng)

Tận dụng GitHub Actions chạy trên môi trường Ubuntu. Nếu bạn lỡ tay đặt tên sai, Pipeline sẽ "fail" ngay lập tức khi chạy bộ test, không cho phép code lỗi lọt xuống Production.

Lớp 3: Standard Naming Convention

Luôn tuân thủ quy tắc đặt tên thống nhất (ví dụ: luôn dùng kebab-case hoặc PascalCase cho toàn bộ dự án).

Lời kết

Môi trường Linux không tạo ra lỗi, nó chỉ giúp bạn nhìn thấy những lỗi mà Windows đã che giấu. Việc đồng bộ môi trường từ Local đến Production là yếu tố then chốt của một Senior Developer.

Nếu bạn muốn một bộ khung Node.js đã được cấu hình sẵn để "miễn nhiễm" với các lỗi môi trường như thế này (kèm theo Kafka, Redis, Clean Architecture), hãy tham khảo dự án của mình nhé:

👉 GitHub: nodejs-quickstart-structure

👉 NPM: npx nodejs-quickstart-structure init

Hy vọng bài viết này giúp bạn tiết kiệm vài giờ debug vô nghĩa! Đừng quên tặng 1 Star nếu bạn thấy dự án hữu ích nhé!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí