Tìm hiểu về Dockerfile để build Docker Image

Tìm hiểu về Dockerfile dùng để build Docker ImageCuongquach.com | Bạn đang tìm hiểu cách thức để build các Docker Image dành riêng cho các mục đích ứng dụng hoá đem lên Container chạy. Vậy thì ngoài việc tìm hiểu cách thức build docker image, thì bạn cũng phải tham khảo và tìm hiểu về Dockerfile, một trong những thành phần quan trọng của quá trình build docker Image. Cùng tìm hiểu về Dockerfile nhé !

tìm hiểu về dockerfile

Có thể bạn quan tâm chủ đề khác
Container Registry là gì ?
Sự khác nhau giữa Docker Registry và Docker Repository
Docker Hub là gì ?
Cài đặt Docker trên CentOS 7

Dockerfile là gì ?

Docker sẽ xây dựng (build) docker image một cách tự động bằng cách đọc các chỉ thị (instruction) đã được khai báo trong một file có tên là Dockerfile. Dockerfile là một file văn bản chứa toàn bộ các chỉ thị lệnh mà người dùng muốn thực thi để tạo ra một Docker Image.

Ở bài viết này không hướng dẫn bạn cách thức build một Docker Image, mà chỉ nói về danh sách chỉ thị (instruction) do Docker quy định được sử dụng trong một Dockerfile. Thực tế thì khi build Docker Image thường sẽ dùng lệnh :

# docker build . 
Sending build context to Docker daemon 6.51 MB
...

Trình build docker image sẽ đọc nội dung file văn bản Dockerfile và gửi nội dung đó đến dịch vụ Docker đang chạy. Kế đến Docker sẽ chạy các chỉ thị trong Dockerfile từng dòng một, commit các kết quả của từng chỉ thị thành các lớp layer của image.

Như vậy, Dockerfile giúp ta đơn giản hoá và tự động hoá việc xây dựng một Docker Image.

Cú pháp Dockerfile

# Comment
INSTRUCTION arguments
  • Các INSTRUCTION là các chỉ thị, được docker quy định. Khi khai báo, các bạn phải viết chữ in hoa.
  • Các arguments là đoạn nội dung mà chỉ thị sẽ làm gì.
  • Một Dockerfile phải bắt đầu bằng chỉ thị ‘FROM‘ để khai báo base image nào sẽ được sử dụng để làm nền tảng xây dựng image của riêng bạn.

Ví dụ:
– Một file Dockerfile dùng để build Docker Image ứng dụng Apache PHP.

FROM cuongqc/apache2

MAINTAINER Cuongquach version: 0.1

RUN apt-get update && \
apt-get install -y php5 libapache2-mod-php5 php5-mysql php5-cli && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]

Các chỉ thị (instruction) trong Dockerfile

Giờ bạn sẽ đến với danh sách các chỉ thị (instruction) được Docker quy định cho phép sử dụng trong file Dockerfile dùng để build Docker Image.

FROM

Cú pháp:

FROM <image> [AS <name>]
FROM <image>[:<tag>] [AS <name>]
FROM <image>[@<digest>] [AS <name>]

Chỉ thị FROM dùng cho quá trình khởi tạo xây dựng một Docker Image mới và dùng để chỉ ra image gốc nào sẽ là cơ sở để build image thực hiện các chỉ thị kế tiếp. Như vậy, một Dockerfile hợp lệ thường phải bắt đầu bằng chỉ thị FROM . Các base image sẽ có thể được tải về từ Public Repository hoặc Private Repository riêng của người dùng setup.

Các giá trị thẻ (tag) hoặc digest là tùy chọn. Nếu bạn bỏ qua một trong số chúng, thì thẻ được sử dụng mặc định sẽ là ‘latest‘.

Ví dụ :

FROM ubuntu

hoặc

FROM ubuntu14.04:lastest

RUN

Cú pháp:

RUN <command>  (shell form)
RUN ["executable", "param1", "param2"]  (exec form)

Chỉ thị RUN dùng để chạy một lệnh bất kì trên lớp layer mới của Docker Image và commit kết quả của lệnh đó khi build image. Ví dụ như bạn chạy lệnh để cài đặt các gói chương trình, package,.. thì kết quả việc cài đặt sẽ gồm các chương trình được cài vào lớp layer mới trong  docker image. Bạn có thể thực hiện nhiều lệnh cùng lúc ở cách thức ‘shell form‘ khi sử dụng chỉ thị RUN với dấu ‘\‘.

Ví dụ:

FROM ubuntu
RUN apt-get update
RUN apt-get install curl -y

hoặc

FROM ubuntu
RUN apt-get update; \
    apt-get install curl -y

CMD

Cú pháp:

CMD ["executable","param1","param2"] (exec form)
CMD ["param1","param2"] (tham số cho chỉ thị ENTRYPOINT)
CMD command param1 param2 (shell form)

Chỉ thị CMD được sử dụng để cung cấp câu lệnh mặc định sẽ được chạy khi Docker Container khởi động từ Image đã build, chỉ có thể có duy nhất 1 chỉ thị CMD trong một. Có 3 cách thức sử dụng lệnh CMD:

  • Sử dụng ở hình thức ‘exec form‘ với các tham số truyền vào.
  • Sử dụng ở hình thức ‘shell form‘ như bình thường.
  • Sử dụng ở hình thức truyền tham số cho chỉ thị ENTRYPOINT.

Khi sử dụng CMD ở ‘shell‘ hoặc ‘exec‘ form thì lệnh chỉ thị CMD sẽ được thực thi khi khởi chạy Container Docker. Vậy có khác gì so với chỉ thị lệnh RUN ? RUN chạy lệnh và commit kết quả của lệnh trong quá trình build image. CMD không thực thi câu lệnh ở quá trình build image, mà sẽ thực thi trong quá trình chạy Docker Container từ Image đó.

Để chi tiết hơn về CMDENTRYPOINT, chúng ta sẽ có bài viết khác.

Ví dụ :
– Cách 1 không sử dụng shell .

FROM ubuntu
RUN apt-get update
RUN apt-get install curl -y
CMD ["curl", "ipinfo.io"]

– Cách 2 với shell.

FROM ubuntu
RUN apt-get update
RUN apt-get install wget -y
CMD curl ifconfig.io

ENTRYPOINT

Cú pháp:

ENTRYPOINT ["executable", "param1", "param2"] (exec form)
ENTRYPOINT command param1 param2 (shell form)

Hai cái CMDENTRYPOINT có tác dụng tương tự nhau. Nếu một Dockerfile có cả CMDENTRYPOINT thì CMD sẽ thành param cho script ENTRYPOINT. Lý do người ta dùng ENTRYPOINT nhằm chuẩn bị các điều kiện setup như tạo user, mkdir, change owner… cần thiết để chạy service trong container.

SHELL

Cú pháp:

SHELL ["executable", "parameters"]
  • Chỉ thị Shell cho phép các shell form khác, có thể ghi đè shell mặc định.
  • Mặc định trên Linux là [“/bin/sh”, “-c”] và Windows là [“cmd”, “/S”, “/C”].

ENV

Cú pháp:

ENV <key> <value>
ENV <key>=<value> ...

Chỉ thị ENV dùng để khai báo biến môi trường tên <key> với giá trị <value>. Giá trị biến môi trường này sẽ hiện hữu cho các chỉ thị kế tiếp trong quá trình build Docker Image từ Dockerfile. Ngay cả khi chạy container từ Docker Image đã build có khai báo ENV thì container đó cũng sẽ hiện hữu biến môi trường ENV đã set.

Ví dụ:

ENV myName="CuongQuach" myDog=Rex\ The\ Dog \
       myCat=fluffy
ENV myName Cuong Quach

Bạn cũng có thể thay đổi giá trị biến môi trường từ câu lệnh khởi động container.

# docker run --env <key>=<value>

LABEL

Cú pháp:

LABEL <key>=<value> <key>=<value> <key>=<value> ...

Chỉ thị LABEL dùng để thêm các thông tin metadata vào Docker Image khi được build. Một Image có thể có nhiều nhãn (label) thông tin metadata. Bạn có thể khai báo các metadata theo từng dòng chỉ thị LABEL hoặc nhiều metadata cho Image trên cùng một dòng chỉ thị LABEL.

Ví dụ :

LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."
LABEL multi.label1="value1" multi.label2="value2" other="value3"
LABEL multi.label1="value1" \
      multi.label2="value2" \
      other="value3"

Để xem thông tin label của Docker Image, bạn có thể dùng lệnh : # docker inspect

"Labels": {
"com.example.vendor": "ACME Incorporated"
"com.example.label-with-value": "foo",
"version": "1.0",
"description": "This text illustrates that label-values can span multiple lines.",
"multi.label1": "value1",
"multi.label2": "value2",
"other": "value3"
},

USER

Cú pháp:

USER <user>[:<group>] or
USER <UID>[:<GID>]

Chỉ thị USER dùng để khai báo thông tin username hoặc UUID/GUID sử dụng khi chạy image và cũng là user dùng để chạy các lệnh chỉ thị khác như :RUN, CMD ENTRYPOINT .

WORKDIR

Cú pháp:

WORKDIR /path/to/workdir

Chỉ thị WORKDIR dùng để khai báo thư mục làm việc cho các lệnh chỉ thị: RUN, CMD, ENTRYPOINT, COPY ADD . Nếu thư mục WORKDIR không tồn tại thì sẽ được tự động tạo.

Ví dụ:

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

Output của lệnh ‘pwd’ trong Dockerfile sẽ là ‘/a/b/c‘.

EXPOSE

Cú pháp:

EXPOSE <port> [<port>/<protocol>...]

Ví dụ:

EXPOSE 80/tcp
EXPOSE 80/udp

Chỉ thị EXPOSE sẽ khai báo với Docker rằng container sử dụng Docker Image có khai báo EXPOSE sẽ lắng nghe kết nối trên các cổng được chỉ định khi khởi chạy. Bạn có thể chỉ định cổng lắng nghe theo giao thức TCP hoặc UDP, mặc định nếu không chỉ định cụ thể thì sẽ là TCP.

Chỉ thị EXPOSE không có chức năng nat port từ máy chủ host vào container, mà chỉ dùng để giúp người build Docker Image và người sử dụng Docker Image để chạy Container có thông tin về dịch vụ sẽ lắng nghe trên cổng nào. Như một dạng tài liệu giúp lưu ý với nhau ấy mà.

Còn nếu muốn thực sự nat port thì lưu ý đến phần Docker Network, có thể dùng các option như ‘-p‘ để chỉ định nat port cụ thể cho quá trình khởi chạy container.

# docker run -p 80:80/tcp

VOLUME

Cú pháp:

VOLUME ["/data"]
  • Mount thư mục từ máy host và container. Tương tự option -v khi tạo container.
  • Thư mục chưa volumes là /var/lib/docker/volumes/. Ứng với mỗi container sẽ có các thư mục con nằm trong thư mục này.

Tìm thư mục chứa Volumes của container example_cuongqc:

# docker inspect example_cuongqc | grep /var/lib/docker/volumes
"Source": "/var/lib/docker/volumes/491a2a775a4cf02bbaca105ec25995008cc7adbc5511e054bb9c6a691a2681ee/_data",

Phần này có thể tìm hiểu kĩ hơn ở phần Docker Storage/Volume.

ADD

Cú pháp:

ADD <src>... <dest>
ADD ["<src>",... "<dest>"]

Chỉ thị ADD sẽ copy file, thư mục từ vị trí thư mục đang build trên local client hoặc remote files URL (src) và thêm chúng vào filesystem của image (dest). Trong đó cần lưu ý :

  • src‘ có thể khai báo nhiều file, thư mục, có thể sử dụng các ký hiệu wildcard như *,?,…
  • dest‘ phải là đường dẫn tuyệt đối hoặc có quan hệ với chỉ thị WORKDIR.

Ví dụ:

ADD hom* /mydir/ 
ADD hom?.txt /mydir/ 
ADD test relativeDir/ 
ADD test /absoluteDir/

Bạn cũng có thể phân quyền user cho các file, thư mục mới được copy vào container filesystem.

ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/
ADD --chown=1 files* /somedir/
ADD --chown=10:11 files* /somedir/

Tất cả file mới, thư mục mới tạo sẽ có UID và GID là 0. Nếu container tập tin hệ thống root không có file /etc/passwd /etc/group thì ngay cả khi bạn có truyền thông tin user/group owner cũng sẽ khiến quá trình build image thất bại.

Ví dụ:

ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/
ADD --chown=1 files* /somedir/
ADD --chown=10:11 files* /somedir/

COPY

Cú pháp:

COPY <src>... <dest>
COPY ["<src>",... "<dest>"]

Chỉ thị COPY sẽ copy file, thư mục (src) và thêm chúng vào filesystem của container (dest). Khác với chỉ thị ADD thì COPY không hỗ trợ download các remote file URL từ nguồn web. Các lưu ý còn lại thì tương tự chỉ thị ADD.

ARG

Cú pháp:

ARG <name>[=<default value>]

Chỉ thị ARG dùng để khai báo biến mà user có thể truyền vào cho trình build image ở khi thực hiện quá trình build Docker Image. Thường khi truyền vào sẽ sử dụng option ‘–build-arg <varname>=<value>‘ kèm lệnh docker build. Nếu mà người dùng truyền vào biến nhưng không được khai báo trong Dockerfile sẽ gặp phải thông báo lỗi.

[Warning] One or more build-args [foo] were not consumed.

Một Dockerfile có thể bao gồm một hoặc nhiều chỉ thị ARG.

FROM busybox
ARG user1
ARG user2
ARG version

Bạn có thể khai báo giá trị mặc định cho biến trong trường hợp nếu chúng ta không truyền tham số biến từ ngoài vào thì ARG trong Dockerfile sẽ giúp trình build image hiểu giá trị mặc định nên sử dụng của biến đó.

FROM busybox
ARG user1=cuongqc2
ARG user2=cuongquach3

Nếu bạn sử dụng chỉ thị ARG ENV để khai báo cùng giá trị cho 1 tên biến thì giá trị của chỉ thị ENV sẽ chép đè thông tin lên biến do chỉ thị ARG khai báo. Biến ARG cũng sẽ không bền vững như sử dụng biến chỉ thị ENV.

STOPSIGNAL

Cú pháp:

STOPSIGNAL signal

Khi mà bạn dừng một Docker Container bằng lệnh “docker stop” thì Docker sẽ gửi tín hiệu SIGTERM SIGKILL để tắt các tiến trình trong Docker Container. Thì với chỉ thị STOPSIGNAL bạn được phép cấu hình lại tín hiệu sẽ được gửi tới Docker Container khi nó được yêu cầu dừng hoạt động.

ONBUILD

Cú pháp:

ONBUILD [INSTRUCTION]

Chỉ thị ONBUILD được khai báo trong base image. Và khi child image build image từ base image thì lệnh ONBUILD mới được thực thi.

Nguồn: https://cuongquach.com/

Previous articleEbook Trí tuệ nhân tạo – Lập trình tiến hóa (PDF)
Next articleGiáo trình Bài tập Kĩ thuật Lập trình C (PDF)
Bạn đang theo dõi website "https://cuongquach.com/" nơi lưu trữ những kiến thức tổng hợp và chia sẻ cá nhân về Quản Trị Hệ Thống Dịch Vụ & Mạng, được xây dựng lại dưới nền tảng kinh nghiệm của bản thân mình, Quách Chí Cường. Hy vọng bạn sẽ thích nơi này !