Docker: Chưa biết gì đến biết dùng (Phần 2 - Dockerfile)
1. Mở đầu
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 ! 👋👋👋
2. Source code
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ặcPython
... -
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ớihot reload
để hiển thị kết quả tức thì. Ví dụ sửa textHello World
thànhHello 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ạocontainer
- đây chính là môi trường ảo hoá để chạy ứng dụng ở bên trong.
- Như đã tìm hiểu, file này định nghĩa cách tạo
-
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, ...
3. Dockerfile là gì ?
-
- 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ênDockerfile
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:
4. Cách viết Dockerfile
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 CMDcuối cùng
được sử dụng.Một
câu hỏi
đặt ra là nếu tôi muốn khởi độngnhiều ứng dụng
khi start container thì sao, lúc đó hay nghĩ tớiENTRYPOINT
-
ENTRYPOINT: Để thực thi
một số câu lệnh
trong quá trìnhstart container
, những câu lệnh này sẽ được viết trongfile .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-server
Trong 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 80
Tổng hợp lại, ta có một ví dụ cho Dockerfile như sau :
FROM ubuntu:16.04
MAINTAINER HoanKi<hoanki2212@gmail.com>
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:
<h1>Hello word</h1>
-
Mình có push code mẫu lên GitHub: HoanKy/docker_tutorial
-
Còn đây là full document về Dockerfile
5. Cách sử dụng 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:
sudo docker run -p 9000:80 -it ubuntu-nginx /bin/bash
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:
sudo docker run -v /media/hoanki/PROJECT4/GitRepo/docker_tutorial/webroot:/var/www/html -p 9000:80 -it ubuntu-nginx /bin/bash
Thay thế /media/hoanki/PROJECT4/GitRepo/docker_tutorial/webroot
cho đúng với trên máy bạn nhé !
Kết quả:
6. Cách chia sẻ Dockerfile
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.
All rights reserved
Bình luận