Xin chào mọi người, bài viết hôm nay mình xin giới thiệu về một công nghệ đã trở thành hot trend trong ngành IT, đó là Docker. Về căn bản, Docker là một công cụ để tạo ra và chạy các container (một đơn vị vừa đủ với hệ điều hành, tool và các thư viện cần thiết để chúng ta có thể chạy code trên một môi trường độc lập). Nhờ có Docker, các dev sẽ không phải lo lắng về sự khác biệt về kiến trúc hệ điều hành cũng như các thư viện giữa môi trường phát triển và môi trường production. Docker giải quyết được vấn đề thường gặp của dev khi deploy code lên production là: "Nhưng mà nó chạy trên máy mình được mà".
Lần lượt chúng ta sẽ tìm hiểu các nội dung sau để cùng khám xem Docker thú vị thế nào qua bài viết này:
Docker container có thể được coi là gói phần mềm chứa đầy đủ những thứ cần thiết để phần mềm đó có thể chạy được độc lập. Có thể có nhiều container trên một host machine và các container thì hoàn toàn độc lập với nhau và độc lập với host machine
Comment line trong Dockerfile được bắt đầu bằng #, dấu # ở sau instruction sẽ được xem là argument. Dấu # có khoảng trắng phía trước thì sẽ được coi là unknown instruction và bỏ qua dòng đó
Giả sử ta có file compress.tar bao gồm (text1.txt, text2.txt) và chúng ta muốn thêm các file này vào thư mục /var/www của image, thì ta chỉ cần sử dụng lệnh ADD thì file compress.tar sẽ được giải nén và đồng thời chép các file sau khi giản nén vào thư mục /var/www của image
WORKDIR có tác dụng thay đổi đường dẫn thư mục làm việc từ "/" thành giá trị trong tham số của lệnh
EXPOSE sẽ mở port của container để giúp nó tương tác với bên ngoài. Chúng ta có thể gán giao thức internet đối với port được mở. Mặc định là TCP
RUN cho phép thực thi bất kì command nào trong build time. Chúng ta nên thực thi nhiều command trong cùng 1 lệnh RUN
CMD cũng tương tự RUN, có thể chạy bất kì command nào, tuy nhiên nếu RUN được thực thi khi build time thì các command của CMD sẽ được thực thi khi container được tạo ra từ image được chạy
Để chạy được server này ta chỉ cần dùng lệnh
Trong thư mục demo-docker, chạy lệnh
Chúng ta sẽ thấy dòng cuối cùng có "4f254e6ba4be" đó chính là id của image vừa được build. Ta sẽ dùng nó ở bước tiếp theo.
Ta thực hiện lệnh sau
Chúng ta cần tạo repository trên Docker hub tại đây
Ta đặt tên image là first-node-server
Docker |
- Introduction of Docker
- Một số khái niệm căn bản về của Docker
- Tạo Docker Images
- Demo
1. Introduction of Docker
1.1. Virtualization vs Containerization
Virtualization là một quá trình chạy một thực thể ảo của một máy tính trên phần cứng thực tế. Nói cách khác, Virtualization cho phép chạy đồng thời nhiều hệ điều hành trên cùng một phần cứng. Đối với ứng dụng chạy trên máy ảo, nó sẽ vận hành như đang chạy trên một máy dành riêng cho nó, có hệ điều hành, thư viện và các phần mêm hỗ trợ khác mà không liên đới gì tới hệ điều hành của host operation system bên dưới nó. Tuy nhiên, virtualization có những hạn chế rất lớn như thiếu tính di động và giảm performance vì các máy ảo (virtual machine) rất nặng.
Để khắc phục những điểm trên, Containerization ra đời. Nó là một sự thay thế rất "nhẹ" so với virtualization, containerization sẽ đóng gói ứng dụng cùng với môi trường riêng của ứng dụng đó trong một container.
Containerization vs Virtualization |
1.2. What is Docker?
Docker là một containerization engine nguồn mở, cho phép tự động đóng gói, vận chuyển và triển khai bất kì một ứng dụng phần mềm nào dưới dạng một container dung lượng nhỏ, dễ vận chuyển và có thể chạy được ở bất kì đâu.Docker container có thể được coi là gói phần mềm chứa đầy đủ những thứ cần thiết để phần mềm đó có thể chạy được độc lập. Có thể có nhiều container trên một host machine và các container thì hoàn toàn độc lập với nhau và độc lập với host machine
2. Một số thuật ngữ sử dụng trong docker
Trong mục này chúng ta sẽ liệt kê và giải thích một số thuật ngữ được sử dụng thường xuyên trong Docker bên cạnh 2 khái niệm Docker và container đã được định nghĩa ở trên
2.1. Docker Image
Docker image là tập hợp các file cần thiết để tạo ra một ứng dụng phần mềm. Có thể ẩn dụ, Docker Image như 1 bản thiết kế hay là khuôn đúc để tạo nên container tương ứng.
Về căn bản, Image thông thường sẽ ở dạng read-only. Để tạo nên một container, ban đầu ta sẽ có một base image chứa hệ điều hành để chạy ứng dụng, sau đó ta sẽ bổ sung thêm các image chứa các module cần thiết lên trên base image từ đó tạo thành được container. Cách dễ hiểu nhất về container là một read-write layer nằm trên một hay nhiều read-only images.
Base image là Debian distribution, tiếp theo là 2 image của emacs và Apache server |
2.2. Docker registry
Docker registry là nơi lưu trữ các Docker image để các dev khác có thể tìm thấy truy cập và sử dụng để tạo nên các application của họ.
2.3. Docker repository
Docker repository là một namespace để lưu trữ Docker image. Ví dụ ban có một app tên là demoDocker, và tên cho Registry là julianDong thì trong Docker repository thì image có thể tìm được trong Docker Registry với tên julianDong/demoDocker
3.Tạo Docker Image
3.1. Dockerfile là gì?
Để tạo ra được image ta có thể chạy một container từ một base image, cài đặt các application cần thiết, thực hiện các cấu hình sau đó commit container như để tạo thành 1 image.
Ngoài ra chúng ta có thể chọn 1 hướng tiếp cận khác để tạo image một cách tự động bằng Dockerfile.
Dockerfile là đoạn script dạng text chứa những câu lệnh đặc biệt theo 1 thứ tự để tạo ra các Docker image từ base image. Những lệnh theo tuần tự trong Dockerfile bao gồm lựa chọn base image, cài đặt các ứng dụng cần thiết, thêm các file cấu hình và tự động chạy các service cũng như expose các service đó ra ngoài.
3.2. Cú pháp trong Dockerfile
Dockerfile được tạo ra từ 3 thành phần instruction line, comment line và empty line.
Instruction line được tạo thành từ 2 thành phần, instruction và tham số. Instruction không phân biệt chứ hoa chữ thường, tuy nhiên để dễ đọc, chúng ta sẽ viết instruction dưới dạng UPPERCASE để phân biệt với argument. Ví dụ như sau:
FROM busybox:latestInstruction FROM nhận busybox:latest là tham số
CMD echo Hello world!!Instruction CMD nhận echo Hello world!! là tham số
Comment line trong Dockerfile được bắt đầu bằng #, dấu # ở sau instruction sẽ được xem là argument. Dấu # có khoảng trắng phía trước thì sẽ được coi là unknown instruction và bỏ qua dòng đó
# This is comment line
CMD echo ## Hello ##Empty line sẽ bị bỏ qua trong Dockerfile, vì vậy để dễ đọc, comment line và empty line được khuyến khích sử dụng trong Dockerfile
3.3. Những build instruction được sử dụng trong Dockerfile
- FROM
FROM là câu lệnh quan trọng nhất và là câu lệnh đầu tiên trong Dockerfile. Nó có tác dụng set base image cho quá trình build.
Docker cho phép có nhiều lệnh FROM trong 1 Dockerfile để có thể tạo được nhiều image. Tuy nhiên Docker không có cơ chế nào để đặt tên và phân biệt các image được tạo ra từ các lệnh FROM, vì vậy, trong một Dockerfile, không khuyến khích có nhiều hơn 1 lệnh FROM để tránh việc conflict có thể xảy ra.
FROM centos
FROM ubuntu:14.04
- MAINTAINER
MAINTAINER là câu lệnh thông tin trong Dockerfile, nó cho phép tác giả bổ sung thêm thông tin của mình vào trong image
MAINTAINER Julian Dong <juliandong@gmail.com>
- COPY
COPY html /var/www/html/
COPY text1.txt text2.html /var/www
- ADD
Giả sử ta có file compress.tar bao gồm (text1.txt, text2.txt) và chúng ta muốn thêm các file này vào thư mục /var/www của image, thì ta chỉ cần sử dụng lệnh ADD thì file compress.tar sẽ được giải nén và đồng thời chép các file sau khi giản nén vào thư mục /var/www của image
ADD compress.tar /var/www
- ENV
ENV DB_PROD_URL 62bs263.aws.com:63017/db_prod
- USER
USER 37
- WORKDIR
WORKDIR có tác dụng thay đổi đường dẫn thư mục làm việc từ "/" thành giá trị trong tham số của lệnh
WORKDIR /var/www/html
- EXPOSE
EXPOSE sẽ mở port của container để giúp nó tương tác với bên ngoài. Chúng ta có thể gán giao thức internet đối với port được mở. Mặc định là TCP
EXPOSE 7373/udp 8080
- RUN
RUN cho phép thực thi bất kì command nào trong build time. Chúng ta nên thực thi nhiều command trong cùng 1 lệnh RUN
RUN ["bash", "-c", "rm", "-rf", "/temp/abc"]
RUN apt-get update && apt-get install -y apache2 && apt-get clean
- CMD
CMD cũng tương tự RUN, có thể chạy bất kì command nào, tuy nhiên nếu RUN được thực thi khi build time thì các command của CMD sẽ được thực thi khi container được tạo ra từ image được chạy
CMD ["echo", "Docker file demo"]
3.4. File .dockerignore
Trong quá trình build image, sẽ có nhiều file hoặc thư mực sẽ được thêm vào image mặc dù chúng không tham gia vào quá trình build image. Vì vậy, tương tự như .gitignore, file .dockerignore là nơi khai báo những file hay thư mục nào sẽ được bỏ quả trong quá trình build image. Nội dung của .dockerignore có dạng như sau
.git
4. Demo
4.1. Cài đặt Docker
Bước đầu tiên để chúng ta cần thực hiện là cài đặt Docker trên máy. Tuỳ thuộc vào hệ điều hành mà bạn đang sử dụng, hãy truy cập vào đây và tải về bản cài tương ứng. Trong bài viết này mình sẽ tải về Docker cho Mac.
Sau khi làm theo hướng dẫn và cài đặt, bạn dùng terminal và gõ lệnh sau để kiểm tra Docker đã được cài đặt thành công hay chưa?
Sau khi làm theo hướng dẫn và cài đặt, bạn dùng terminal và gõ lệnh sau để kiểm tra Docker đã được cài đặt thành công hay chưa?
docker -vVà kết quả được như sau
Docker version 18.09.1, build 4c52b90
4.2. Run hello-world container
Sau khi đã cài đặt Docker xong, chúng ta sẽ tiến hành chạy thử 1 image đơn giản nhất đó là image hello-world. Ta có thể tìm các image mà chúng ta mong muốn ở Docker hub
Trong terminal, gõ lệnh
Sau khi chạy lệnh trên, ta ngay lập tức sẽ nhận được kết quả là
Chúng ta đã hoàn thành việc chạy một image có sẵn, tiếp theo chúng ta sẽ tiến hành tự tạo image của chúng ta thông qua Dockerfile
Trong terminal, gõ lệnh
docker run -it hello-worldLệnh này sẽ yêu cầu Docker chạy image có tên là hello-world, còn tag -it là để gắn container vào process hiện tại của terminal, khi đó ta có thể dùng CMD + C để tắt container.
Sau khi chạy lệnh trên, ta ngay lập tức sẽ nhận được kết quả là
Unable to find image 'hello-world:latest' locallyĐiều này có nghĩa là hiện tại trên máy của chúng ta không có image "hello-world" vì đây là lần chạy đầu tiên, do đó, Docker sẽ phải kéo image "hello-world" về máy từ Docker hub. Và sau khi kéo image về thành công, ta sẽ nhận được thông báo như sau:
Status: Downloaded newer image for hello-world:latestVà sau đó docker sẽ thực hiện chạy image "hello-world" vừa kéo về được. Kết quả ta có thể thấy như hình
Run hello-world image |
4.3. Build your own container
- Bước 1: Tạo một thư mục và đặt tên là demo-docker
- Bước 2: Trong thư mục demo-docker tạo file server.js với nội dung như sau
const http = require('http');
const PORT = 8000;
http.createServer((request, response) => {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('Docker is awesome!!!');
}).listen(PORT);
// Console will print the message
console.log(`Server running on port: ${port}`);
Để chạy được server này ta chỉ cần dùng lệnh
node server.jsvà vào http://localhost:8000 để thấy message.
- Bước 3: Tạo dockerfile
# inherit from the Node official Image
FROM node:latest
# set a workdir inside docker
WORKDIR /usr/src/app
# copy . (all in the current directory) to . (WORKDIR)
COPY . .
# the port we wish to expose
EXPOSE 8000
# run a command when running the container
CMD node server.js
- Bước 4: Build image từ docker file
Trong thư mục demo-docker, chạy lệnh
docker build .Khi đó ta được kết quả như sau:
Build image from dockerfile |
Chúng ta sẽ thấy dòng cuối cùng có "4f254e6ba4be" đó chính là id của image vừa được build. Ta sẽ dùng nó ở bước tiếp theo.
- Bước 5: Chạy image vừa tạo
Ta thực hiện lệnh sau
docker run -it -p 8000:8000 4f254e6ba4beVà sẽ thấy trên terminal có dòng
Server running on port: 8000Và khi mở trên trình duyệt sẽ thấy kết quả
Docker is awesome!!!
- Bước 6: Push image lên Docker hub
Chúng ta cần tạo repository trên Docker hub tại đây
Docker hub |
Repository |
Tiếp theo chúng ta sẽ tag và đặt tên cho image vừa tạo ở local, lưu ý, tên phải ứng với tên trên repository vừa tạo
docker tag 4f254e6ba4be juliandong/first-node-serverSau đó ta có thể push image lên Docker hub
docker push juliandong/first-node-server
Push image to Docker hub |
Kết
Như vậy là chúng ta đã vừa tìm hiểu và thực hiện tạo thành công image trên docker hub, hi vọng qua bài viết này có thể giúp các bạn có những hiểu biết cơ bản về Docker để có thể sử dụng trong công việc sau này.
Code của server và dockerfile mình có để trên github tại đây để mọi người có thể đọc kĩ hơn.
Nếu các bạn thấy có ý kiến đóng góp cho blog, đừng ngại để lại comment ở cuối bài viết nhé, nếu thấy hay có thể share cho những người khác cùng đọc nhé. Xin cảm ơn!
Reference
- Official Documentation: https://docs.docker.com/
- Book: Learning Docker
- Course: Learning Docker from Lynda
Advertisement