Hướng Dẫn Dockerfile Ubuntu: Tạo Môi Trường Phát Triển Hiện Đại với Docker cho Lập Trình Viên

目次

1. Giới thiệu

Docker và Dockerfile là gì?

Trong những năm gần đây, Docker đã trở nên phổ biến nhanh chóng như một giải pháp giúp đơn giản hóa việc thiết lập môi trường phát triển và triển khai ứng dụng. Docker cho phép đóng gói ứng dụng và các phụ thuộc vào một “container” duy nhất, giúp bạn chạy ở bất kỳ đâu với môi trường nhất quán.

Để xây dựng container Docker, bạn cần một bản thiết kế gọi là “Dockerfile“. Dockerfile là tệp văn bản mô tả image hệ điều hành cơ sở, phần mềm cần cài đặt, biến môi trường, v.v… Nhờ đó, lập trình viên có thể tự động xây dựng môi trường tùy chỉnh của mình.

Lý do chọn Ubuntu làm nền tảng

Khi tạo Dockerfile, bước đầu tiên là chọn image hệ điều hành cơ sở. Trong số đó, Ubuntu là lựa chọn rất phổ biến. Ubuntu là một bản phân phối Linux dựa trên Debian, nổi bật với sự thân thiện và kho gói phong phú, phù hợp cho việc xây dựng môi trường linh hoạt.

Dockerfile dựa trên Ubuntu có các lợi thế sau:

  • Tài liệu chính thức và cộng đồng phong phú, dễ học
  • Nhiều gói và công cụ có thể cài đặt dễ dàng qua APT
  • Các image tối giản (như ubuntu:20.04, ubuntu:24.04) được cung cấp chính thức

Mục tiêu bài viết & đối tượng độc giả

Bài viết này lấy chủ đề từ từ khóa “Dockerfile Ubuntu” và sẽ hướng dẫn cách tạo Dockerfile dựa trên Ubuntu một cách dễ hiểu cho người mới bắt đầu.

Cụ thể, bài viết sẽ giải thích từ cấu trúc cơ bản của Dockerfile, cách xây dựng môi trường Ubuntu thực tế, ví dụ triển khai môi trường ứng dụng như Python, cũng như tổng hợp các lỗi thường gặp và cách khắc phục.

Bài viết này phù hợp với:

  • Người lần đầu muốn tạo môi trường bằng Dockerfile
  • Người muốn tái tạo môi trường phát triển bằng Ubuntu một cách nhất quán
  • Người muốn hiểu sâu cả về cách xử lý khi gặp sự cố

2. Cấu trúc cơ bản của Dockerfile

Dockerfile là gì? Hiểu vai trò của nó

Dockerfile giống như một công thức để tạo ra Docker image. Nó là tệp văn bản mô tả sẽ sử dụng hệ điều hành cơ sở nào, cài đặt phần mềm gì, thiết lập như thế nào,…

Dựa vào tệp này, bạn chỉ cần chạy lệnh docker build là có thể dễ dàng xây dựng môi trường phát triển hoặc môi trường chạy ứng dụng với tính nhất quán cao.

Lợi ích khi sử dụng Dockerfile:

  • Tự động hóa xây dựng môi trường (không cần lặp lại thao tác thủ công)
  • Tránh sai khác môi trường khi phát triển nhiều người
  • Dễ tích hợp vào quy trình CI/CD pipeline

Các lệnh (directive) cơ bản thường dùng trong Dockerfile

Dockerfile có nhiều lệnh khác nhau, dưới đây là những lệnh tiêu biểu bạn sẽ dùng để tạo Dockerfile dựa trên Ubuntu.

LệnhMô tả
FROMChỉ định image Docker nền tảng. Ví dụ: FROM ubuntu:24.04
RUNChạy lệnh shell, thường dùng để cài đặt package
COPYSao chép file từ máy local vào image
ADDGiống COPY nhưng hỗ trợ tải từ URL hoặc giải nén file archive
WORKDIRChỉ định thư mục làm việc
ENVThiết lập biến môi trường
CMDĐịnh nghĩa lệnh chạy khi khởi động container (có thể override)
ENTRYPOINTĐịnh nghĩa lệnh bắt buộc phải chạy khi khởi động container

Ví dụ tối thiểu về Dockerfile dựa trên Ubuntu

Dưới đây là ví dụ Dockerfile cơ bản dùng Ubuntu làm nền tảng.

FROM ubuntu:24.04

RUN apt-get update && apt-get install -y 
    curl 
    vim

CMD ["/bin/bash"]

Dockerfile này sẽ sử dụng Ubuntu 24.04, cài đặt curlvim, sau đó khởi động shell bash.

Lưu ý khi chọn tag Ubuntu

Image Ubuntu được cung cấp trên Docker Hub (official repository). Khi chỉ định ubuntu:latest sẽ lấy bản mới nhất, nhưng nên cố định version cụ thể để tránh thay đổi ngoài ý muốn.

Ví dụ:

  • ubuntu:22.04 (LTS: bản ổn định, ưu tiên sự ổn định)
  • ubuntu:24.04 (LTS mới nhất, ưu tiên tính năng mới)

Tùy mục đích mà ưu tiên sự ổn định hay cập nhật tính năng.

3. Thực hành: Tạo Dockerfile dựa trên Ubuntu

Cài đặt các gói cần thiết cho môi trường Ubuntu

Khi xây dựng môi trường Ubuntu bằng Dockerfile, thường bạn sẽ cần cài thêm các gói phần mềm bổ sung. Ví dụ, để chuẩn bị môi trường phát triển, các tiện ích sau thường được sử dụng:

  • curl: Tải file và kiểm tra API
  • vim: Trình soạn thảo văn bản cơ bản
  • git: Công cụ quản lý phiên bản
  • build-essential: Bộ công cụ biên dịch C/C++

Để cài các gói này trong Dockerfile, hãy sử dụng lệnh RUN như sau:

FROM ubuntu:24.04

RUN apt-get update && apt-get install -y 
    curl 
    vim 
    git 
    build-essential

Thực hiện apt-get update trước khi cài để đảm bảo lấy được danh sách gói mới nhất.

Cài đặt không tương tác (non-interactive)

Với Ubuntu, đôi khi apt-get install yêu cầu nhập tương tác. Trong quá trình build Docker, thao tác này là không thể, nên hãy thiết lập biến môi trường sau để cài đặt ở chế độ không tương tác:

ENV DEBIAN_FRONTEND=noninteractive

Điều này giúp bỏ qua các câu hỏi như chọn khu vực, giúp quá trình cài đặt mượt mà hơn.

Giảm dung lượng bằng cách xóa cache không cần thiết

Khi dùng APT, các file tạm sẽ được lưu lại và làm tăng dung lượng image. Hãy xóa cache sau khi cài đặt như sau:

RUN apt-get update && apt-get install -y 
    curl 
    vim 
    && rm -rf /var/lib/apt/lists/*

Bằng cách kết hợp nhiều lệnh trong một dòng RUN, bạn cũng tránh tạo nhiều layer không cần thiết.

Best Practice: Viết Dockerfile hiệu quả

Trong thực tế phát triển, các best practice sau được khuyến nghị khi viết Dockerfile:

  • Kết hợp các lệnh RUN để giảm số layer
  • Sử dụng ENV để định nghĩa rõ version và thiết lập
  • Ghi chú bằng comment để dễ hiểu mục đích từng lệnh
  • Dọn dẹp file không cần thiết với rm hoặc dùng --no-install-recommends

Ví dụ:

RUN apt-get update && apt-get install -y --no-install-recommends 
    curl 
    git 
    && rm -rf /var/lib/apt/lists/*

Làm như vậy, bạn sẽ xây dựng được Dockerfile nhẹ, dễ bảo trì.

4. Build và kiểm tra Docker Image

Build Docker Image từ Dockerfile

Sau khi hoàn thiện Dockerfile, bước tiếp theo là build Docker image bằng lệnh sau, chạy trong thư mục chứa Dockerfile:

docker build -t my-ubuntu-image .
  • Tùy chọn -t dùng để đặt tên cho image, ví dụ my-ubuntu-image
  • . nghĩa là build tại thư mục hiện tại

Docker sẽ đọc từng dòng Dockerfile và tạo image mới tương ứng.

Kiểm tra Docker Image vừa build

Sau khi tạo xong image, dùng lệnh sau để kiểm tra:

docker images

Bạn sẽ thấy danh sách các Docker image trên máy, bao gồm các thông tin:

  • REPOSITORY (Tên image)
  • TAG (Tag của image)
  • IMAGE ID (Mã nhận diện duy nhất)
  • CREATED (Thời gian tạo)
  • SIZE (Dung lượng)

Ví dụ:

REPOSITORY        TAG       IMAGE ID       CREATED          SIZE
my-ubuntu-image   latest    abcd1234abcd   5 minutes ago    189MB

Bạn sẽ xác nhận được image đã được tạo thành công.

Khởi động container để kiểm tra hoạt động

Để kiểm tra image có hoạt động đúng không, hãy khởi động container bằng lệnh:

docker run -it my-ubuntu-image
  • Tùy chọn -it giúp mở terminal ở chế độ tương tác
  • Nếu thành công, bạn sẽ truy cập được shell bash trong môi trường Ubuntu

Bạn có thể chạy các lệnh sau trong container để kiểm tra công cụ đã cài:

curl --version
vim --version

Nếu mọi thứ ổn, Dockerfile của bạn đã hoàn thành tốt.

Dọn dẹp image và container không cần thiết

Sau khi build/test nhiều lần, các image/container không dùng tới sẽ chiếm chỗ trên máy. Hãy dọn dẹp định kỳ với các lệnh sau:

  • Xóa container đã dừng:
docker container prune
  • Xóa image không dùng:
docker image prune
  • Xóa tất cả dữ liệu không dùng (Cẩn thận!):
docker system prune

Các thao tác này giúp giải phóng dung lượng và tránh lỗi.

5. Ứng dụng: Xây dựng môi trường Python

Cài đặt Python trong Dockerfile dựa trên Ubuntu

Khi xây dựng môi trường Ubuntu bằng Dockerfile, bạn có thể thêm môi trường Python để phục vụ phát triển, kiểm thử, học máy, v.v… Ubuntu thường đã có sẵn Python, nhưng để quản lý phiên bản và các gói một cách chủ động, bạn nên tự cài đặt rõ ràng trong Dockerfile.

Cách cài đặt Python bằng apt

Cách đơn giản nhất là sử dụng apt để cài Python. Ví dụ:

FROM ubuntu:24.04

RUN apt-get update && apt-get install -y 
    python3 
    python3-pip 
    && rm -rf /var/lib/apt/lists/*

Cách này sẽ cài Python (thường là bản 3.10 hoặc 3.12 tuỳ Ubuntu) cùng pip để quản lý các package Python.

Quản lý nhiều phiên bản Python với pyenv

Nếu bạn cần một phiên bản Python cụ thể, hoặc muốn chuyển đổi nhiều version, hãy dùng pyenv. Dưới đây là ví dụ cài Python 3.11.6 với pyenv trong Dockerfile:

FROM ubuntu:24.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y 
    git 
    curl 
    make 
    build-essential 
    libssl-dev 
    zlib1g-dev 
    libbz2-dev 
    libreadline-dev 
    libsqlite3-dev 
    wget 
    llvm 
    libncurses5-dev 
    libncursesw5-dev 
    xz-utils 
    tk-dev 
    libffi-dev 
    liblzma-dev 
    && rm -rf /var/lib/apt/lists/*

# Cài đặt pyenv
RUN git clone https://github.com/pyenv/pyenv.git ~/.pyenv

ENV PYENV_ROOT="$HOME/.pyenv"
ENV PATH="$PYENV_ROOT/bin:$PATH"

RUN echo 'eval "$(pyenv init --path)"' >> ~/.bashrc

# Cài đặt phiên bản Python mong muốn
RUN pyenv install 3.11.6 && pyenv global 3.11.6

Cách này giúp bạn xây dựng môi trường Python linh hoạt và hiện đại hơn.

Quản lý thư viện với requirements.txt

Trong dự án thực tế, bạn sẽ cần cài nhiều thư viện Python. Thường dùng file requirements.txt để quản lý chúng.

Đầu tiên, tạo file requirements.txt ở thư mục gốc dự án:

flask==2.3.2
requests>=2.25.1
pandas

Sau đó, bổ sung vào Dockerfile:

COPY requirements.txt /app/requirements.txt
WORKDIR /app

RUN pip install --no-cache-dir -r requirements.txt

Như vậy, các thư viện cần thiết sẽ được cài tự động và môi trường sẽ nhất quán.

Best Practice

  • Khi dùng Python, hãy dùng virtualenv hoặc venv để tạo môi trường ảo, tránh xung đột phụ thuộc.
  • Dùng tuỳ chọn --no-cache-dir để làm nhẹ Docker image.
  • Nên chạy pip install --upgrade pip trước khi cài thư viện để tránh lỗi.

6. Các lỗi thường gặp và cách xử lý

Lỗi quyền truy cập (Permission Error)

Ví dụ:

Permission denied

Lỗi này xuất hiện khi file sao chép vào container không có quyền thực thi, hoặc user/owner không đúng.

Cách xử lý:

  • Đặt quyền thực thi cho file:
  RUN chmod +x script.sh
  • Đổi user sở hữu nếu cần:
  RUN chown root:root /path/to/file

Lỗi không tìm thấy package hoặc không cài được

Ví dụ:

E: Unable to locate package xxx

Lỗi này thường do không chạy apt-get update trước khi cài, hoặc sai tên package.

Cách xử lý:

  • Luôn chạy apt-get update trước khi install:
  RUN apt-get update && apt-get install -y curl
  • Kiểm tra kỹ tên package có đúng không

Lỗi mạng khi build

Ví dụ:

Temporary failure resolving 'deb.debian.org'

Lỗi này xảy ra khi DNS không hoạt động trong quá trình build.

Cách xử lý:

  • Khởi động lại Docker daemon:
  sudo systemctl restart docker
  • Xem lại cấu hình DNS cho Docker (/etc/docker/daemon.json):
  {
    "dns": ["8.8.8.8", "8.8.4.4"]
  }

Lỗi build do cache cũ

Docker dùng cache để tăng tốc build, nhưng đôi khi thay đổi Dockerfile mà build không như mong muốn.

Cách xử lý:

  • Build lại không dùng cache:
  docker build --no-cache -t my-image .

Lệnh khởi động không chạy hoặc container tự tắt

Nguyên nhân:

  • Lệnh CMD hoặc ENTRYPOINT lỗi
  • Chạy CMD với ["/bin/bash"] mà không tương tác sẽ tự tắt ngay

Cách xử lý:

  • Khởi động container ở chế độ debug để kiểm tra:
  docker run -it my-image /bin/bash
  • Hiểu sự khác biệt giữa CMDENTRYPOINT để dùng đúng mục đích

Khi gặp lỗi, hãy đọc kỹ thông báo và xác định bước/command gây ra lỗi để xử lý chính xác.

7. Tổng kết

Tóm tắt các điểm quan trọng khi tạo Dockerfile dựa trên Ubuntu

Bài viết này đã giải thích từng bước cách xây dựng môi trường Ubuntu bằng Dockerfile từ cơ bản đến nâng cao. Dưới đây là các điểm mấu chốt:

  • Hiểu cấu trúc cơ bản của Dockerfile
    FROM, RUN, CMD, ENV giúp tự động hóa cấu hình môi trường.
  • Ubuntu là image nền tảng ổn định, linh hoạt
    Kho gói phong phú, cộng đồng lớn, có các bản LTS phù hợp làm nền cho phát triển.
  • Quản lý package hiệu quả giúp cài đặt công cụ và thư viện đúng chuẩn
    apt-get, xóa cache, cài đặt không tương tác là những điểm mấu chốt.
  • Dễ dàng cài đặt các môi trường như Python
    Dùng pyenv, pip, requirements.txt để tạo môi trường phát triển có thể tái sử dụng.
  • Khả năng xử lý sự cố giúp vận hành ổn định
    Biết cách xử lý lỗi quyền, lỗi mạng, cache, v.v… sẽ nâng cao hiệu quả làm việc với Docker.

Bước tiếp theo để học về Dockerfile

Thành thạo Dockerfile không chỉ hữu ích cho phát triển mà còn cho kiểm thử và triển khai môi trường thực tế (production). Bạn có thể tiếp tục học các chủ đề sau:

  • Quản lý nhiều container với Docker Compose
  • Tích hợp với các công cụ CI/CD (GitHub Actions, GitLab CI, v.v.)
  • Kết hợp với Kubernetes hoặc các công cụ orchestration khác

Tài liệu tham khảo chính thức

8. FAQ (Các câu hỏi thường gặp)

Q1. Nên chọn phiên bản Ubuntu nào cho Dockerfile?

A1. Thông thường nên chọn phiên bản LTS (Long Term Support) để được hỗ trợ lâu dài và ổn định. Ví dụ ubuntu:22.04 hoặc ubuntu:20.04 rất phổ biến vì có thời gian hỗ trợ 5 năm.

Nếu bạn muốn dùng các gói/phần mềm mới nhất thì có thể chọn ubuntu:24.04 (phiên bản mới), nhưng nên kiểm tra kỹ trước khi dùng trong môi trường production.

Q2. Tại sao gặp lỗi “Không tìm thấy package” khi dùng apt-get install?

A2. Lý do phổ biến nhất là bạn chưa chạy apt-get update trước khi cài, khiến danh sách package chưa được cập nhật. Hãy luôn chạy update trước:

RUN apt-get update && apt-get install -y curl

Cũng hãy kiểm tra tên package có chính xác (ví dụ nên dùng python3 thay vì python cho các bản mới).

Q3. Làm thế nào để thiết lập biến môi trường trong Dockerfile?

A3. Dùng lệnh ENV trong Dockerfile. Biến này sẽ có hiệu lực trong quá trình build và khi chạy container.

Ví dụ:

ENV DEBIAN_FRONTEND=noninteractive

Thường dùng để tắt prompt khi cài APT, hoặc truyền key cấu hình/phím API cho app.

Q4. Sự khác nhau giữa CMDENTRYPOINT trong Dockerfile là gì?

A4. Cả hai đều dùng để chỉ định lệnh chạy khi container khởi động, nhưng có điểm khác biệt:

Thuộc tínhCMDENTRYPOINT
Có thể override không?Có, có thể thay thế bằng lệnh khi chạy docker runKhông, lệnh luôn được thực thi (tham số truyền thêm là argument)
Mục đíchChỉ định lệnh mặc địnhChỉ định lệnh chính luôn chạy

Ví dụ:

CMD ["python3", "app.py"]
# hoặc
ENTRYPOINT ["python3"]
CMD ["app.py"]

Trường hợp thứ hai, bạn có thể chạy docker run my-image another_script.py để chạy script khác.

Q5. Sửa Dockerfile rồi mà build không ra kết quả mới, tại sao?

A5. Docker dùng cache khi build, nên đôi khi sửa Dockerfile nhưng vẫn lấy lại layer cũ.

Cách khắc phục:

docker build --no-cache -t my-image .

Lệnh này sẽ build lại toàn bộ mà không dùng cache, đảm bảo mọi thay đổi đều có hiệu lực.