-->
ads here

Docker cho người mới bắt đầu

advertise here
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à".
Image result for docker
Docker
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:

  1. Introduction of Docker
  2. Một số khái niệm căn bản về của Docker
  3. Tạo Docker Images
  4. 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.
Image result for virtualization vs containerization
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:latest
Instruction 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 là lệnh cho phép sao chép file từ Docker host vào file system của imagege
COPY html /var/www/html/ 
COPY text1.txt text2.html /var/www 

  • ADD
ADD là lệnh tương tự COPY nhưng có khả năng xử lý file .tar và file ở dạng URL

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 là lệnh cho phép set các biến môi trường vào image, biến môi trường này ở dạng 1 cặp giá trị key-value và có thể được truy cập bởi bất kì script hay app nào
ENV DB_PROD_URL 62bs263.aws.com:63017/db_prod 

  • USER 
Lệnh USER sẽ gán user cho image khi khởi động. Mặc định, container sẽ được gán user root  khi khởi động, lệnh USER sẽ thay đổi user mặc đinh này thành cái mà ta mong muốn. Ví dụ ta muốn container mới sẽ chạy với user có ID là 37 thì ta làm như sau
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?
docker -v
Và 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
docker run -it hello-world
Lệ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:latest
Và 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
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  

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.js
và vào http://localhost:8000 để thấy message.

  • Bước 3: Tạo dockerfile 
Trong thư mục demo-docker, tạo file Dockerfile (không có phần mở rộng) và điền nội dung như sau
  # 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 4f254e6ba4be
Và sẽ thấy trên terminal có dòng
Server running on port: 8000
Và 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
Ta đặt tên image là first-node-server
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-server
Sau đó 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

Advertisement
COMMENTS ()