Docker: Chưa Biết Gì đến Biết Dùng (Phần 2 - Dockerfile) - Viblo
Có thể bạn quan tâm
Xin chào các bạn, ở bài trước Docker: Chưa biết gì đến biết dùng (Phần 1):
-
Chúng ta đã cùng nhau tìm hiểu công nghệ ảo hóa containerlization với công cụ docker của công ty cùng tên. Tuy nhiên nội dung chủ yếu tập trung vào lý thuyết vào lịch sử và cơ chế hoạt động.
-
Hôm nay, chúng ta sẽ đi sâu hơn để khám phá cách sử dụng Docker trong thực tế.

-
Như bác Hoàng Nam Tiến từng nói:
Hãy nhớ rằng Tiếng Anh là ngôn ngữ để làm việc , để sống, không còn là ngoại ngữ nữa. -
Thì Docker hiện tại gần như đã trở thành tiêu chuẩn trong phát triển phần mềm, không chỉ xuất phát từ sự tiện lợi, mà còn bởi cách nó thay đổi tư duy, quy trình và phương pháp làm việc.
-
Nên nếu như bạn chưa dùng Docker thì câu hỏi không phải là Tại sao nữa mà là Làm thế nào để bắt đầu. Chuỗi bài viết này sẽ hỗ trợ bạn giải quyết phần nào câu hỏi đó.
-
Trước khi đọc phần 2, đừng quên đọc lại phần 1 - để mình hiểu rõ lý thuyết và bản chất của Docker đã nhé.
Let's go ! 👋👋👋

Bớt lý thuyết lại, coding luôn:
Dưới đây là cấu trúc demo source code của chúng ta:

-
Thư mục web_app:
-
Đây là nơi chứa mã nguồn chương trình của bạn.
-
Nó có thể là một ứng dụng viết bằng PHP, Node.js hoặc Python ...
-
Trong ví dụ này, để cho đơn giản, ta chỉ tạo file index.html với nội dung:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Docker tutorial</title> </head> <body> <div>Hello World</div> </body> </html>Sẽ hiển thị dòng Hello World khi chạy trên trình duyệt.
-
Trong quá trình phát triển, bạn có thể chỉnh sửa mã nguồn trong thư mục này trực tiếp trên máy thật (host OS) bằng các trình soạn thảo như VS Code.
-
Nhờ docker volume, những thay đổi sẽ ngay lập tức được cập nhật vào bên trong container, kết hợp với hot reload để hiển thị kết quả tức thì. Ví dụ sửa text Hello World thành Hello World From Asia.
-
-
Dockerfile:
- Như đã tìm hiểu, file này định nghĩa cách tạo docker image.
- Sau khi build được image, bạn có thể khởi tạo container - đây chính là môi trường ảo hoá để chạy ứng dụng ở bên trong.
-
File start.sh:
- Đây là script chứa những câu lệnh được thực thi mỗi khi container khởi động.
- Có thể dùng script này để khởi chạy các dịch vụ như MySQL, Nginx, Redis, ...
-
Dockerfile:
- Một file dạng text thuần tuý.
- Không có đuôi mở rộng (như .txt, .sh ...) mà docker nhận diện nó thông qua tên Dockerfile cố định.
- Gồm các lệnh được viết tuần tự, hướng dẫn Docker xây dựng docker image mà bạn muốn.
-
Có thể liên tưởng tới việc cài lại hệ điều hành:
- Khi cài lại Windows:
- Bạn dùng usb boot để cài os lên laptop.
- Sau đó cài các phần mềm lên như Chrome, VS code, ...
- Thì khi build docker images từ Dockerfile cũng tương tự:
-
Bạn cũng bắt đầu từ một base image ví dụ: ubuntu, centos ...
-
Sau đó thêm các lệnh cài đặt, sao chép hoặc cấu hình.
# Use the official Ubuntu image as the base FROM ubuntu:latest # Configure the main working directory WORKDIR /app # Update package lists and install necessary packages RUN apt-get update; \ apt-get install -y --no-install-recommends \ nginx \ nano \ vim \ postgresql; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* # Copy the startup script and set permissions COPY start.sh . RUN chmod +x ./start.sh # Set the entrypoint ENTRYPOINT ["./start.sh"] # Expose the required port EXPOSE 80
-
- Như việc xây một bức tường:
- Từng hàng gạch lần lượt được xây.
- Hàng dưới xây xong rồi mới tới hàng trên, hàng trên được kế thừa từ hàng dưới.
- Mỗi một hàng gạch được xem tương tự như một layer (Lát sẽ tìm hiểu kĩ hơn)
- Khi cài lại Windows:

Các câu lệnh trong Dockerfile được liệt kê và giải thích trên trang chủ cũng khá đầy đủ
Sau đây chúng ta sẽ điểm qua những câu lệnh nào hay sử dụng nhất.
4.1 Thiết lập thông tin cơ bản
-
FROM
-
Ví dụ:
FROM centos:7 FROM ubuntu:16.04 FROM ubuntu:22.04 ... FROM ubuntu:latest -
Câu lệnh này luôn nằm đầu tiên, nó giúp chúng ta chỉ định image ta đang muốn tạo khởi nguồn từ đâu.
-
Hiểu nôm na là bắt nguồn từ ubuntu, hay centos ... cùng phiên bản của nó (latest có nghĩa là phiên bản mới nhất) sau đó cài thêm những gì lên.
-
Có thể bạn đã biết, Docker hub - nơi lưu trữ và chia sẻ các image sẽ chứa những image gốc này.
-
Khi Docker đọc tới câu lệnh này, nó sẽ tự động tìm xem image ubuntu:16.04 này đã tồn tại trong host OS chưa, nếu chưa thì Docker sẽ tự động pull image này về. Trong đó ubuntu là tên của image, 16:04 là tag, latest nghĩa là tag mới nhất.
![]()
-
-
WORKDIR
-
Ví dụ:
WORKDIR /app WORKDIR /path/to/workdir -
Thay đổi thư mục làm việc
-
4.2 Cài thêm ứng dụng
Bây giờ, chúng ta sẽ cài thêm các ứng dụng, thiết lập môi trường cần thiết trên ubuntu:16.04 này
Bạn có thể cài nginx, php, python, ruby, java ... phụ thuộc vào nhu cầu của bạn, sử dụng:
-
RUN : Để thực thi một câu lệnh nào đó trong quá trình build images.
-
CMD : Để thực thi một câu lệnh trong quá trình bật container.
Mỗi Dockerfile chỉ có một câu lệnh CMD, nếu như có nhiều hơn một câu lệnh CMD thì chỉ có câu lệnh CMD cuối cùng được sử dụng.
Một câu hỏi đặt ra là nếu tôi muốn khởi động nhiều ứng dụng khi start container thì sao, lúc đó hay nghĩ tới ENTRYPOINT
-
ENTRYPOINT: Để thực thi một số câu lệnh trong quá trình start container, những câu lệnh này sẽ được viết trong file .sh.
Ví dụ:
# Update ubuntu RUN apt-get update # Install nginx RUN apt-get install -y nginx # Install mysql server RUN echo "mysql-server mysql-server/root_password password root" | debconf-set-selections \ && echo "mysql-server mysql-server/root_password_again password root" | debconf-set-selections \ && apt-get install -y mysql-serverTrong khi cài nginx, sẽ có câu hỏi xuất hiện và bạn cần trả lời yes/no, khi đó tùy chọn -y trong RUN apt-get install -y nginx sẽ thể hiện cho sự lựa chọn yes của bạn.
4.3 Cấu hình
-
EXPOSE: Container sẽ lắng nghe trên các cổng mạng được chỉ định khi chạy
-
ADD : Copy file, thư mục, remote file thêm chúng vào filesystem của image.
-
COPY : Copy file, thư mục từ host machine vào image. Có thể sử dụng url cho tập tin cần copy.
-
WORKDIR : Định nghĩa directory cho CMD
-
VOLUME : Mount thư mục từ máy host vào container.
Tạo file .sh
Như ở phần entrypoint đã nói, cho dù chỉ cần một câu lệnh mình vẫn dùng ENTRYPOINT, để sau này dễ dàng tùy biến, phát triển.
Tạo file start.sh như sau
#!/bin/bash service nginx start exec $@Ta có ví dụ ở phần này như sau:
ADD start.sh /venv WORKDIR /venv RUN chmod a+x /venv/* ENTRYPOINT ["/venv/start.sh"] EXPOSE 80Tổng hợp lại, ta có một ví dụ cho Dockerfile như sau :
FROM ubuntu:16.04 MAINTAINER HoanKi<[email protected]> RUN DEBIAN_FRONTEND=noninteractive RUN apt-get update RUN apt-get install -y nginx RUN echo "mysql-server mysql-server/root_password password root" | debconf-set-selections \ && echo "mysql-server mysql-server/root_password_again password root" | debconf-set-selections \ && apt-get install -y mysql-server WORKDIR /venv COPY start.sh /venv RUN chmod a+x /venv/* ENTRYPOINT ["/venv/start.sh"] EXPOSE 80- Tạo file hello.html trong thư mục webroot:
-
Mình có push code mẫu lên GitHub: HoanKy/docker_tutorial
-
Còn đây là full document về Dockerfile
5.1 Build docker image từ Dockerfile
Ta sử dụng câu lệnh sau:
sudo docker build -t <image_name> .
Ví dụ:
sudo docker build -t ubuntu-nginx .Bạn có thể dùng lệnh
docker imagesđể xem thành quả nhé !

5.2 Tạo container từ image.
- Gõ lệnh theo syntax:
sudo docker run -v <forder_in_computer>:<forder_in_container> -p <port_in_computer>:<port_in_container> -it <image_name> /bin/bash
Trong đó:
-
-v : Thể hiện việc mount volume, dữ liệu từ thư mục từ máy thật có thể được truy cập từ thư mục của máy ảo.
-
-p: Cổng mạng từ máy thật để dẫn tới cổng mạng của máy ảo đang chạy.
-
-t: Chạy container và mở terminal bằng /bin/bash
-
Ví dụ vào localhost mặc định của nginx:
Kiểm tra log trên Terminal:

Trên trình duyệt:

- Ví dụ vào thư mục dự án ở máy thật:
Thay thế /media/hoanki/PROJECT4/GitRepo/docker_tutorial/webroot cho đúng với trên máy bạn nhé !
Kết quả:

Docker-hub: Nơi lưu trữ và chia sẻ các image của Docker, nhưng không chỉ có vậy.
Nãy giờ bạn và tôi đang build image hoàn toàn dưới local, nhưng Docker Hub còn hỗ trợ chúng ta làm việc này trên server nữa.
- Mình tạo mới repo docker-basic trên Github, như này:

- Sau đó mình tạo mới một repo trên Dockerhub.
Vào Create chọn Create Automated Build, chọn Github rồi trỏ tới docker-basic bạn vừa tạo ở GitHub.

Và ta có docker_basic, trông như sau:

-
Dockerhub sẽ hỗ trợ bạn build docker image online, sau đó bạn có thể pull nó về để sử dụng.
-
Vào tab Build Settings,
![]()
-
Từ giờ trở đi, mỗi khi bạn push code lên branch nào trên github branch đó bạn đã setting trên DockerHub thì images sẽ tự động được build.
Việc build này sẽ tự động thực hiên trên server Docker Hub nhé, ví dụ mình push code lên branch init_dockerfile thì Dockerhub tự động build image, kết quả có ở trong tab Build Detail.
Mình tạo pull request, sau khi mình merge nó thì DockerHub cũng sẽ build image tiếp trên branch master.
- Thử đi nhé, đôi khi buid ở local thì pass mà build trên server thì lỗi, cảm giác fix mãi nó mới hiện dòng chữ "Success" nó mới awesome làm sao.
![]()
###############################################
Thank for your attention

Mình đã viết xong Docker: Chưa biết gì đến biết dùng (Phần 3), mời các bạn đọc tiếp.


Từ khóa » Docker Chưa Biết Gì đến Biết Dùng
-
Docker: Chưa Biết Gì đến Biết Dùng (Phần 1- Lịch Sử) - Viblo
-
Docker: Chưa Biết Gì đến Biết Dùng (Phần 1) - Bizfly Cloud
-
Docker: Chưa Biết Gì đến Biết Dùng - DVMS
-
Docker: Chưa Biết Gì đến Biết Dùng (Phần 2 – Dockerfile) - Code 24h
-
Docker Cho Người Mới Bắt đầu - 2KVN
-
Chưa Biết Gì đến Biết Dùng (Phần 3: Docker-compose) - 2KVN
-
Container Là Gì Docker - Docker: Chưa Biết Gì Đến Biết Dùng (Phần 1
-
Docker Là Gì? Tìm Hiểu Docker Từ Chưa Biết Gì Tới Biết Dùng
-
Docker Là Gì? Tại Sao Phải Dùng Docker Trong Dự án Phần Mèm?
-
Top 15 Chạy Docker Compose
-
Hướng Dẫn Sử Dụng Docker Cơ Bản - Hybrid Technologies
-
Docker Là Gì? Hướng Dẫn Sử Dụng Docker Cơ Bản - Vietnix
-
Docker: Chưa Biết Gì đến Biết Dùng (Phần 1- Lịch Sử) - Pinterest
-
Docker Là Gì? Kiến Thức Cơ Bản Về Docker - TopDev


