Giới thiệu về Dockerfile
Dockerfile là gì
Dockerfile có thể hình dung như một script dùng để build các image trong container. Dockerfile bao gồm các câu lệnh liên tiếp nhau được thực hiện tự động trên một image gốc để tạo ra một image mới. Dockerfile giúp đơn giản hóa tiến trình từ lúc bắt đầu đến khi kết thúc.
Dockerfile syntax
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: nội dung của chỉ thị.
Dockerfile instruction
FROM
Chỉ định rằng image nào sẽ được dùng làm image cơ sở để quá trình build image thực thiện các câu lệnh tiếp theo. Các image base này sẽ được tải về từ Public Repository hoặc Private Repository riêng của mỗi người tùy theo setup. Chỉ thị FROM là bắt buộc và phải được để lên phía trên cùng của Dockerfile.
Cú pháp:
FROM <image> [AS <name>]
FROM <image>[:<tag>] [AS <name>]
FROM <image>[@<digest>] [AS <name>]
Ví dụ:
FROM ubuntu
hoặc
FROM ubuntu:latest
LABEL
Chỉ thị LABEL được dùng để thêm các thông tin meta vào Docker Image khi chúng được build. Chúng tồn tại dưới dạng các cặp key – value, được lưu trữ dưới dạng chuỗi. Có thể chỉ định nhiều label cho một Docker Image, và tất nhiên mỗi cặp key – value phải là duy nhất. Nếu cùng một key mà được khai báo nhiều giá trị (value) thì giá trị được khai báo gần đây nhất sẽ ghi đè lên giá trị trước đó. Bạn có thể khai báo metadata cho Image theo từng dòng chỉ thị hoặc có thể tách ra khai báo thành từng dòng riêng biệt.
Cú pháp:
LABEL <key>=<value> <key>=<value> <key>=<value> ... <key>=<value>
Ví dụ:
LABEL com.example.some-label="lorem"
LABEL version="2.0" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
Để xem thông tin meta của một Docker Image, ta sử dụng dòng lệnh:
docker inspect <image id>
MAINTAINER
Chỉ thị MAINTAINER dùng để khai báo thông tin tác giả người viết ra file Dockerfile.
Cú pháp:
MAINTAINER <name> [<email>]
Ví dụ:
MAINTAINER NamDH <namduong3699@gmail.com>
Hiện nay, theo tài liệu chính thức từ bên phía Docker thì việc khai báo MAINTAINER đang dần được thay thế bằng LABEL maintainer bới tính linh hoạt của nó khi ngoài thông tin về tên, email của tác giả thì ta có thể thêm nhiều thông tin tùy chọn khác qua các thẻ metadata và có thể lấy thông tin dễ dàng với câu lệnh docker inspect ...
.
LABEL maintainer="namduong3699@gmail.com"
RUN
Chỉ thị RUN dùng để chạy một lệnh nào đó trong quá trình build image và thường là các câu lệnh Linux. Tùy vào image gốc được khai báo trong phần FROM thì sẽ có các câu lệnh tương ứng. Ví dụ, để chạy câu lệnh update đối với Ubuntu sẽ là RUN apt-get update -y
còn đối với CentOS thì sẽ là RUN yum update -y
. Kết quả của câu lệnh sẽ được commit lại, kết quả commit đó sẽ được sử dụng trong bước tiếp theo của Dockerfile.
Cú pháp:
RUN <command>
RUN ["executable", "param1", "param2"]
Ví dụ:
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'
hoặc
RUN ["/bin/bash", "-c", "echo hello"]
Ở cách thức shell form
bạn có thể thực hiện nhiều câu lệnh cùng một lúc với dấu \
:
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
ADD
Chỉ thị ADD sẽ thực hiện sao chép các tập, thư mục từ máy đang build hoặc remote file URLs từ src và thêm chúng vào filesystem của image dest.
Cú pháp:
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
Trong đó:
- src có thể khai báo nhiều file, thư mục, …
- dest phải là đường dẫn tuyệt đối hoặc có quan hệ chỉ thị đối với WORKDIR.
Ví dụ:
ADD hom* /mydir/
ADD hom?.txt /mydir/
ADD test.txt relativeDir/
Bạn cũng có thể phân quyền vào các file/thư mục mới được copy:
ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/
ADD --chown=1 files* /somedir/
ADD --chown=10:11 files* /somedir/
COPY
Chỉ thị COPY cũng giống với ADD là copy file, thư mục từ <src> và thêm chúng vào <dest> của container. Khác với ADD, nó không hỗ trợ thêm các file remote file URLs từ các nguồn trên mạng.
Cú pháp:
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
ENV
Chỉ thị ENV dùng để khai báo các biến môi trường. Các biến này được khai báo dưới dạng key – value bằng các chuỗi. Giá trị của các biến này sẽ có hiện hữu cho các chỉ thị tiếp theo của Dockerfile. ENV chỉ được sử dụng 1 trong các command sau: ADD, COPY, ENV, EXPOSE, FROM, LABEL, STOPSIGNAL, USER, VOLUME, WORKDIR
Cú pháp:
ENV <key>=<value> ...
Ví dụ:
ENV DOMAIN="viblo.asia"
ENV PORT=80
ENV USERNAME="namdh" PASSWORD="secret"
Ngoài ra cũng có thể thay đổi giá trị của biến môi trường bằng câu lệnh khởi động container:
docker run --env <key>=<value>
CMD
Chỉ thị CMD định nghĩa các câu lệnh sẽ được chạy sau khi container được khởi động từ image đã build. Có thể khai báo được nhiều nhưng chỉ có duy nhất CMD cuối cùng được chạy.
Cú pháp:
CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1 param2
Ví dụ:
FROM ubuntu
CMD echo Viblo
ENTRYPOINT
Hai chỉ thị CMD và ENTRYPOINT có tác dụng tương tự nhau. Nếu một Dockerfile có cả CMD và ENTRYPOINT 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.
Cú pháp:
ENTRYPOINT ["executable", "param1", "param2"] (exec form, preferred)
ENTRYPOINT command param1 param2 (shell form)
USER
Có tác dụng set username hoặc UID để sử dụng khi chạy image và khi chạy các lệnh có trong RUN, CMD, ENTRYPOINT sau nó.
Cú pháp:
USER <user>[:<group>]
hoặc
USER <UID>[:<GID>]
Ví dụ:
FROM alpine:3.4
RUN useradd -ms /bin/bash namdh
USER namdh
EXPOSE
Chỉ thị EXPOSE thông báo cho Docker rằng image sẽ lắng nghe trên các cổng được chỉ định khi chạy. Lưu ý là cái này chỉ để khai báo, chứ ko có chức năng nat port từ máy host vào container. Muốn nat port, thì phải sử dụng cờ -p
(nat một vài port) hoặc -P
(nat tất cả các port được khai báo trong EXPOSE) trong quá trình khởi tạo container.
Cú pháp:
EXPOSE <port> [<port>...]
WORKDIR
Chỉ thị WORKDIR dùng để đặt thư mục đang làm việc cho các chỉ thị khác như: RUN, CMD, ENTRYPOINT, COPY, ADD,…
Cú pháp:
WORKDIR /path/to/workdir
ARG
Chỉ thị ARG dùng để định nghĩa các giá trị của biến được dùng trong quá trình build image (lệnh docker build --build-arg =
). Biến ARG sẽ không bền vững như khi sử dụng ENV.
Cú pháp:
ARG <name>[=<default value>]
STOPSIGNAL
Gửi tín hiệu để container tắt đúng cách.
Cú pháp:
STOPSIGNAL signal
VOLUME
Chỉ thị mount thư mục từ máy host và container. Tương tự option -v
khi tạo container.
Cú pháp:
VOLUME ["/data"]
Tạo Dockerfile đơn giản
Để minh hoạ những kiến thức ở trên, chung ta sẽ tạo Dockerfile để run một React app với Docker
Bước 1: Cài đặt create-react-app
.
npm install -g create-react-app
Bước 2: Tạo React project.
create-react-app docker-build
Bước 3: Tạo file dockerfile.sh
trong thư mục của project với nội dung như sau:
cat << EOF > dockerfile
FROM node:10
# A directory within the virtualized Docker environment
# Becomes more relevant when using Docker Compose later
WORKDIR /usr/src/app
# Copies package.json and package-lock.json to Docker environment
COPY package*.json ./
# Installs all node packages
RUN npm install
# Copies everything over to Docker environment
COPY . .
# Uses port which is used by the actual application
EXPOSE 3000
# Finally runs the application
CMD [ "npm", "start" ]
EOF
docker build -t react_app_docker .
Bước 4: Run file dockerfile.sh
để tạo image tên là react_app_docker
.
bash dockerfile.sh
Bước 5: Kiểm tra image có tên react_app_docker
vừa tạo.
docker images
Bước 6: Tạo container từ image vừa tạo
docker run --name react_app_docker -p 8080:3000 -d react_app_docker
Bước 7: Kiểm tra container có tên react_app_docker
vừa tạo.
docker ps
Sau khi thực hiện thành công các bước ở trên, chúng ta có thể xem được ứng dụng trên trình duyệt.