Docker for Newbie: Phần 3 - Giới thiệu Dockerfile và một số câu lệnh
Bài đăng này đã không được cập nhật trong 4 năm
Đôi lời mở đầu
Tiếp nối chủ đề Docker for Newbie, nay mình xin phép hướng dẫn các bạn sử dụng thực hành sử dụng Docker để chạy 1 webserver bằng NodeJS. Mình chọn NodeJS vì thấy là ngôn ngữ phổ biến hiện nay, nếu bạn có khó khăn gì với ngôn ngữ của các bạn hãy comment bài viết này mình sẽ cố gắng giải đáp nếu có thể
Bắt đầu nào
Hãy suy nghĩ theo hướng dockerize
Quay lại series trước mình đã giới thiệu cho các bạn khái niệm Docker Images và Docker Container. Vậy để có thể sử dụng mình hãy cùng nhau cách mạng tư tưởng trước đã. Giả sử, bây giờ mình có 1 source code NodeJS rồi làm như nào để chạy. Trước hết, bạn cần tạo ra máy ảo chạy ubuntu, rồi cài NodeJS vào rồi copy code vào trong đó rồi cài dependency các kiểu con đà điểu rồi chạy node index.js
đúng không? Đây là cách mấy ông không có docker hay làm như thế trên server. Được rồi, thế bây giờ mình sẽ suy nghĩ theo hướng docker hơn (mình gọi là dockerize). Đầu tiên mình có 1 cái images chạy sẵn NodeJS rồi (Bản chất images chạy NodeJS cũng từ images debian rồi xào nấu cài nodejs rồi npm mà ra) rồi copy code, cài dependency rồi cũng node index.js
Nếu như nhìn số cách bạn thấy giảm được bớt mỗi cái phải cài NodeJS vào thôi Xong lại nghĩ thà cài trên máy còn hơn cài cả cục docker to đùng. Nếu suy nghĩ xa hơn với docker bạn có thể fix version NodeJS trong file rồi chỉ cần chạy đúng 1 câu lệnh thôi, điều này sẽ giảm tối đa thời gian cho các lần chạy sau (vì chỉ cần run container lên) và giảm tối đa lỗi các lần sau (Vì nó chạy theo 1 file config từ sẵn)
Thôi không lôi thôi nữa, hãy cùng config 1 file docker chạy server NodeJS với express.js nhé
Thực hành nào
Tạo project cùng với Dockerfile
Trước hết, mình tạo file package.json và cài package express
yarn init -y # Tạo package.json
yarn add express # Cài express
Đối với bạn nào không biết sử dụng NodeJS thì package.json cũng giống như gemfile
của ruby hay requirement.txt
của python
Tiếp theo, mình index.js
với nội dung như sau
const app = require("express")();
const PORT = 3000;
app.listen(PORT, () => console.log("Server is running"));
app.get("/", (req, res) => res.send("hello world"));
với ngôn ngữ khác thì hãy tạo các file tương ứng để dựng server, và hãy thử lại bằng curl như hình bên dưới là được
Tiếp theo là hãy bê nó vào docker nhé, bạn tạo Dockerfile bằng câu lệnh sau
touch Dockerfile
Trước hết, ở dòng đầu tiên của Dockerfile
, ta phải chỉ ra rằng chúng ta muốn build từ image nào (Ở đây của mình là node)
Ở đây mình dùng phiên bản lts
# Choose images
FROM node:lts
Ở dòng tiếp theo ta sẽ khai báo đường dẫn của code chúng ta trong container, mình sẽ để ở /usr/src/app
# Create app directory
WORKDIR /usr/src/app
Ở dòng tiếp theo ta sẽ copy toàn bộ source của project vào trong image và download các dependencies
# Copy source code
COPY . .
- Dấu
.
đầu tiên là đường dẫn đến file của bạn trên máy tính, mình để là chấm vì mình sẽ lấy toàn bộ file cùng context với Dockerfile - Dấu
.
thứ 2 chính làusr/src/app
. Nếu bạn không khai báoWORKDIR
thì bạn sẽ phải trỏ đến vị trí chứa code của container
Nếu ngôn ngữ bạn sử dụng cần yêu cầu cài packages nếu có thì hãy thêm vào dòng
RUN npm install
Với một số ngôn ngữ có folder package ngay trong chính folder project như node_modules của NodeJS hãy tạo file .dockerignore và ignore node_modeles, giống .gitignore
Và cuối cùng thêm dòng sau để chạy server
CMD [ "node", "index.js" ]
Nếu các bạn tinh ý thì npm install
hay node index.js
đều là các câu lệnh bash bình thường, vậy tại sao không dùng RUN node index.js
hay CMD npm install
Đó là ví do sự khác nhau về ý nghĩa của các câu lệnh đó như sau
RUN
: thực thi (các) lệnh trong một layer mới và tạo một containers mới. Ví dụ: nó thường được sử dụng để cài đặt các gói phần mềm.CMD
: đặt lệnh và/hoặc là đặt các tham số mặc định trong dockerfile, lệnh hoặc các tham số mặc định này có thể được ghi đè từ dòng lệnh khi docker container chạy Ngoài ra, còn cóENTRYPOINT
: cấu hình một container sẽ chạy như một executable
Tham khảo tại đây
Ngoài ra còn nhiều thứ thú vị hơn ở Dockerfile
bạn có thể tham khảo tại đây
Build dockerfile
Ta sử dụng câu lệnh để build từ Dockerfile ra images
docker build -f Dockerfile -t docker-express .
Giải thích:
-f Tên_file
: Bạn có thể tạo những file nhưDockerfile.development
. Với-f
bạn có thể custom tên file-t Tên_images_mới
: Ở đây mình đang build images với tên làdocker-express
. Trong thực tế người ta sẽ dùng thêm cả tag nhưlastest
,development
bằng cách thêm:
và tên tag sau tên images nhưdocker-express:latest
.
: Là context của docker. Bạn có thể ngầm hiểu là thư mục chứa Dockerfile cho đơn giản
Để kiểm tra images đã được tạo ra chưa hãy sử dụng câu lệnh sau trong Terminal
docker images
Chạy container với docker images
Sử dụng câu lệnh sau
docker run --rm -d -p 3000:3000 --name test docker-express
Giải thích:
--rm
: Thường khi bạn stop docker thì docker đó sẽ ở trạng thái stop chứ không được terminate hoàn toàn. Thêm params này sẽ giúp terminate ngay khi stop-d
: Giúp container chạy ở background-p l:c
:l
là port của máy tính của bạn vàc
là port của container. Params này sẽ có tác dụng map port. Nếu bạn sử dụng80:3000
thì sẽ reverse port 3000 của container thành port 80 của máy tính--name tên_container
: đặt tên container giúp bạn có thể dễ dàng thao tác hơndocker-express
: tên images ở trên
Sau khi chạy ta sẽ được 1 string như sau e7f5f8b86ee1b4e7a16ef38cc24547c598c9aaafccd1de23efeb668ec33a6c0d
, đây chính là ID của container để tương tác, bạn có thể thao tác với container bằng 7-8 kí tự đầu của string này (thường mình copy bừa Được bao nhiêu thì được) hoặc tên container
Một số câu lệnh hữu ích với docker
Ngoài run
và build
chúng ta có thể sử dụng một số câu lệnh như sau. Đối với trường name
có thể thay bằng id
như lưu ý ở trên
List các container đang chạy
docker ps
Sử dụng tham số -a
để xem những container đã stop. Đối với các container chạy với tham số --rm
container sẽ được xoá ngay sau khi stop
Stop 1 container
docker stop name
Start lại 1 container đã dừng
docker start name
Xoá hoàn toàn 1 container
docker rm name
# Có thể thêm tham số -f với các container đang ch
Xoá hoàn toàn 1 container
docker rm name
# Có thể thêm tham số -f với các container đang ch
Inspect lại 1 container
docker inspect name
Dừng hoặc xoá tất cả các container (Đối với Windows sử dụng trên Powershell)
docker rm -f $(docker ps -aq)
List các images
docker images
Xoá hoàn toàn 1 images
docker rmi name
Dừng hoặc xoá tất cả các container (Đối với Windows sử dụng trên Powershell)
docker rmi $(docker images -q)
Đối với images, bạn cần xoá các container đang chạy với images đó
Ở bài sau mình sẽ hướng dẫn chạy nhiều containers với Docker compose và thực hành CRUD với NodeJS nhé
All rights reserved