Giới thiệu về Docker

Trong bài viết này, mình sẽ giải thích các khái niệm cơ bản của Docker một cách đơn giản và dễ hiểu nhất để mọi người có thể hình dung và bắt tay vào sử dụng được.

Các khái niệm cơ bản về Docker

Tại sao cần phải sử dụng Docker?

Trước khi đi sâu vào chủ đề, chúng ta cần xác định rõ một số lý do hay trường hợp sẽ cần tới Docker:

  • Trong phát triển phần mềm, có thể sử dụng Docker như một cách đóng gói phần mềm và đảm bảo ứng dụng của bạn chạy ổn định ở nhiều môi trường (Từ môi trường Development lên Production)
  • Bạn cần triển khai mô hình kiến trúc Microservices hay một hệ thống cần khả năng Scaling tốt.
  • Triển khai nhanh chóng một số ứng dụng Web, công cụ hỗ trợ. Với các hoạt động Testing, mình sử dụng Docker để dựng Selenium Grid hay các hệ thống cluster cho JMeter, Locust.

Vậy Docker là gì?

Để hiểu về Docker, chúng ta cần biết về khái niệm “Container” – Những máy tính con chạy trên một máy tính cha và Docker Engine.

Giả sử, bạn đang sử dụng hệ điều hành Windows hay MacOS và chạy hàng loạt các Process khác nhau, bạn có thể theo dõi những Process này bằng cách sử dụng lệnh “top” trong Terminal hoặc mở cửa sổ Tasks Manager của Windows hay Activity Monitor của MacOS.

Screen Shot 2018-11-17 at 4.43.14 PM.png

Điều cần lưu ý ở đây là những Process này cùng sử dụng một nguồn tài nguyên cố định (CPU, Memory, Disk I/O, Network) và không hề có sự phân cách (Isolation). Việc này có thể dẫn đến trường hợp khi một Process chiếm dụng hết CPU hay Memory sẵn có, những Process khác không thể được thực hiện.

Và chúng ta có Docker! Đầu tiên chúng ta sẽ cần có Docker Engine chạy trên máy tính chủ.

WithoutDocker.png

Giả sử đây là hệ thống của chúng ta khi chạy hai Process: Một với Python và một với Node.js

Với Docker Engine (Hay còn gọi tắt là Docker), chúng ta có thể tạo ra và thực thi những Container (hình dung tương tự như những Process ở trên):

WithDocker.png

 

Có 1 vài sự thay đổi ở hình bên:

  1. Trong môi trường Docker, thay cho những Process là các Container – Các Process có sự tách biệt.
  2. Container nói chuyện với Docker Engine và thông qua đó, sẽ gửi yêu cầu để được sử dụng nguồn tài nguyên của hệ điều hành trực tiếp tới Kernel.

 

 

Lợi ích của việc “Container hoá” (Containerized) các Process này sẽ giúp chúng ta quản lý sử dụng nguồn tài nguyên máy và tách biệt (isolating) môi trường giữa các Process.

Tóm lại, Container là một thuật ngữ để chỉ những Process được quản lý bởi một Container Enginer (Ngoài Docker Engine ra thì còn một số công cụ khác như Solaris Zones, LXC, etc). Với bài viết này, mình chỉ tập trung về Docker Container và những lợi ích của công nghệ này.

Docker Image là gì?

Một khái niệm khác trong Docker: Image – Những mẫu (template) chứa những dòng quy định một Container chạy lên như thế nào.

Nếu hiểu theo lập trình hướng đối tượng thì ta có thể xem Image như một Class và những Containers được tạo từ Image này như một Object Instance của Class đó.

Imagetocontainer.png

Ở mô hình trên, ta có thể thấy container 1 và 2 được khởi tạo từ Image có tên là Python. Một Docker Image thường được build từ một Base Image khác (Thường sẽ bắt nguồn từ các phân nhánh của Linux như Ubuntu, Alpine, Slim, etc). Những Base Image này cũng có Base Image cho chính nó và gốc cuối cùng là Scratch Image.

Các thuật ngữ khác

Ngoài Docker ContainerDocker Image, chúng ta cần biết thêm về:

  • Dockerfile: Là một tập tin chứa những mô tả để build một Docker Image
  • Docker Registry: Là một kho chứa các Docker Image, về cơ bản chúng ta sẽ có sẵn 2 Docker Registry sẵn sàng để sử dụng:
    • Local Registry: Những Image được kéo về máy chủ hay được build tại máy chủ sẽ nằm tại đây. Cũng giống như source code khi bạn clone về máy từ GitHub.
    • Docker Hub: Đây là Public Registry và là Registry mặc định của Docker. Đa số các Image sẽ đuộc pull (kéo về) từ đây.
  • Volume / Binding Volume: Khi một Container được khởi tạo, nó sẽ có một Volume (Ổ chứa dữ liệu) tách biệt để chứa các tập tin hệ thống hay source code, nếu Container đó ngừng chạy, chúng ta sẽ không còn access được những tập tin này nữa. Do đó, việc binding giữa Docker Volume và một ổ chứa của máy chủ (Host machine) là cần thiết nếu chúng ta muốn lưu giữ những tập tin sinh ra từ Container (ví dụ như log files, configuration files, etc)
  • Container Port / Binding Ports: Tương tự như Volume, Container cũng có riêng những Network ports, và để access những Port này từ máy chủ, chúng ta cũng phải bind các port trên máy chủ với Containers.
  • Docker Client: công cụ chính để chúng ta giao tiếp với Docker Engine.
  • Docker Daemon: đóng vai trò như Listener để thực thi các lệnh quản lý Docker như build Image, run Container, get Image list và get Container list, etc.

Bắt đầu với Docker

Cài đặt Docker

Các bạn có thể tìm hướng dẫn cài đặt trên phần tài liệu của Docker: https://docs.docker.com/install/

Phần này mình sẽ đề cập một số lưu ý khi cài đặt Docker:

  • Enable Virtualization cho Windows 10: Nếu bạn sử dụng Windows 10, hãy nhớ enable Hyper-V và enable Virtualization (ở trong bios menu), và uninstall tất cả virtualization tool khác như VMWare hay VirtualBox.
  • Docker Desktop cho Windows 10 / MacOS: Đây là phiên bản ổn định, dễ cài đặt và có nhiều tính năng hỗ trợ tiện dụng nhất. Bạn có thể dễ dàng điều chỉnh Docker thông qua Desktop Tool được cung cấp. Bộ cài đặt gói gọn đầy đủ những thứ cần thiết: https://www.docker.com/products/docker-desktopScreen Shot 2018-11-17 at 8.13.12 PM.pngĐồng thời khi sử dụng Docker Desktop, bạn có thể dễ dàng chuyển đổi giữa 2 phiên bản Stable và Edge của Docker, mình hay sử dụng tính năng này để trải nghiệm các tính năng mới của bản Edge và quay trở lại bản Stable để né những lỗi từ bản build mới :)).
  • Docker Enterprise for Windows Server 2016+: Với các bản Windows Server, lựa chọn tốt nhất mình từng trải nghiệm là sử dụng Docker Enterprise. Phiên bản tương thích tốt nhất với Windows Server và sẽ tránh làm bạn “wtf” nhất khi sử dụng.
  • Với Linux distributions: Docker chạy tốt với các hệ điều hành Linux, một lưu ý nhỏ là bạn cần phải để ý các thành phần cần thiết và những hướng dẫn cài cụ thể do hiện tại chưa có một Installer cụ thể chung cho Linux như phiên bản Docker Desktop.
  • Restart-máy là tuyệt kĩ cuối cùng: Nếu bạn đã làm theo mọi hướng dẫn cài đặt và vẫn không thể chạy được Docker ( dấu hiệu là con cá voi sẽ bị đỏ lè và vài cái cửa sổ với hình cá voi khóc 😥 ) . Bạn có thể thử tuyệt kĩ Restart-máy. Không phải lúc nào cũng thành công, nhưng tuyệt kĩ này đã giúp mình vượt qua vô số lần trầy trật khi cài đặt Docker trên Windows. Chúc bạn may mắn :))

Sau khi cài đặt xong, bạn có thể mở Terminal (Linux / MacOS) hay Command Prompt / Powershell (Windows) và gõ lệnh “docker ps”, nếu màn hình in ra một chuỗi “CONTAINER ID IMAGE …” thì chúng ta đã cài đặt thành công!

Ngoài ra, nếu chưa quen sử dụng câu lệnh (command line), bạn có thể sử dụng thử Kitematic – UI tool cho Docker.

Viết Dockerfile

Cho những ví dụ về sau, chúng ta sẽ build trước một Docker Image.

Để build một Docker Image, chúng ta cần có Dockerfile – Một tập những chỉ dẫn mô tả Image được build. Một ví dụ nhỏ, với source code và một file requirements.txt đi kèm cho ứng dụng Python “Hello World” của mình – repo trên GitHub:

Screen Shot 2018-11-17 at 6.31.53 PM.png

Giải thích chi tiết hơn về Dockerfile của chúng ta:

Screen Shot 2018-11-17 at 6.32.25 PM.png

  1. Trước khi build một Image, chúng ta cần build từ một Base Image khác, ở đây mình sử dụng keyword “FROM” và chọn Ubuntu với tag (sau “:”) 16.04 chỉ thị bản build của Image cũng là phiên bản của Ubuntu mà mình muốn. Tuỳ thuộc vào nhu cầu khi build cũng như việc lựa chọn Base Image như thế nào cho phù hợp, mình sẽ viết thêm về phần này ở một bài viết khác về cách optimize cho việc build một Docker Image.
  2. Do sử dụng hệ điều hành Ubuntu 16.04, mình dùng “RUN” để sử dụng câu lệnh chạy Package manager của hệ điều hành này và cài đặt ‘pip’ – (Package manager dành cho Python)
  3. Mình dùng “COPY” để tạo bản sao của toàn bộ source code (“.” biểu thị thư mục hiện tại) vào folder “app” ở trong Image.
  4. Sử dụng “WORKDIR” để chỉ thị thư mục hoạt động trong Image, do mình đã copy source code vào thư mục “app”, mình sẽ muốn chạy từ đó.
  5. Dùng “RUN” để chạy lệnh “pip” và cài đặt những Python package mình đã chỉ định trong file requirements.txt
  6. Đặt câu lệnh bắt đầu một Container bằng keyword “CMD” (Một keyword tương tự khác là “ENTRYPOINT”). Chỉ thị rằng khi khởi chạy Container của Image này, sẽ chạy với lệnh “python3 /app/main.py”

Sử dụng Docker Client

Tới lúc đụng tay vào máu me rồi. Sau đây chúng ta sẽ sử dụng Terminal / Command Prompt là chủ yếu. Trong trường hợp bạn không nhớ những dòng lệnh kế tiếp, bạn có thể gõ “docker” vào Terminal (mình sẽ gọi chung cho cả Command Prompt) và nó sẽ in ra danh sách các câu lệnh cần thiết.

Đầu tiên chúng ta cần kiểm tra những Container đang chạy để đảm bảo Docker Daemon đã chạy:

docker ps

Nếu Terminal chỉ hiện ra một dòng những header như CONTAINER ID, NAME, etc. thì Docker Daemon đã chạy rồi đó! Trong trường hợp Terminal báo:

Cannot connect to the Docker daemon. Is the docker daemon running on this host?

Check lại con cá voi ở Menu Bar, hoặc nếu bạn đang sử dụng Linux OS, hãy thử thêm “sudo” vào trước câu lệnh trên.

Tiếp theo, chúng ta sẽ build image từ Dockerfile đã viết ở phần trước:

docker build -t <tên của image> -f <địa chỉ docker file> <địa chỉ thư mục gốc>

  • -t: Sử dụng flag này để đặt tên cho Image cũng như đánh tag <tên image>:<tag>
  • -f: Chỉ định Dockerfile, nếu bạn không có flag này, Docker sẽ tự tìm Dockerfile với tên default (Dockerfile)
  • Phần cuối cùng là địa chỉ tới thư mục gốc.

Mình có thể build image đầu tiên sau khi chuyển Terminal tới thư mục chứa Dockerfile (sử dụng lệnh cd, nếu chưa quen với command line, bạn có thể sử dụng lệnh sau):

git clone https://github.com/locmai/docker-sample.git

cd docker-sample

docker build -t docker-test:1.0 .

Giải thích:

  • Ở đây có thể thấy mình đã bỏ qua flag -f , do mình đặt tên Dockerfile như mặc định.
  • Phần tử cuối cùng của dòng lệnh build sẽ là đường dẫn chính khi build, do mình đang ở địa chỉ đó nên có thể dùng tắt bằng dấu “.” chỉ thị tại chỗ

Khi chạy, màn hình Terminal sẽ hiện ra những bước khi build image, giống với bên dưới:

➜ docker_sample git:(master) docker build -t docker-test:1.0 .
Sending build context to Docker daemon 69.63kB
Step 1/6 : FROM ubuntu:16.04
—> 4a689991aa24
Step 2/6 : RUN apt-get update && apt-get install -y python3-pip
—> Running in 42bc3ec0a6bd
Get:1 http://archive.ubuntu.com/ubuntu xenial InRelease [247 kB]
Get:2 http://security.ubuntu.com/ubuntu xenial-security InRelease [107 kB]
Get:3 http://archive.ubuntu.com/ubuntu xenial-updates InRelease [109 kB]

Running hooks in /etc/ca-certificates/update.d…
done.
Removing intermediate container 42bc3ec0a6bd
—> cd63958b9606
Step 3/6 : COPY . /app
—> ebcf013e4e77
Step 4/6 : WORKDIR /app
—> Running in aa366a88e2ed
Removing intermediate container aa366a88e2ed
—> 5d427440dc7f
Step 5/6 : RUN pip3 install -r requirements.txt
—> 6037dfec5df8
Step 6/6 : CMD python3 /app/main.py
—> Running in 22333acd1ff8
Removing intermediate container 22333acd1ff8
—> 0312aa41b74f
Successfully built 0312aa41b74f
Successfully tagged docker-test:1.0

Note: Bạn để ý sẽ thấy những dòng “—> xxxxxxxxxx” được in ra ở trên. Đó là những đoạn ID của các Images được sinh ra qua từng Step được thực hiện. Ví dụ sau khi COPY source code vào Image, Docker sẽ sinh ra một Image tạm thời khác và đánh ID cho nó. việc đánh ID này và cache lại trạng thái build của Image sẽ giúp tăng tốc độ build cho những lần build sau. Giả sử bạn build lại một image khác với dòng lệnh:

docker build -t docker-test:2.0 .

Bạn sẽ thấy thời gian build nhanh hơn và số dòng log cũng ít hơn rất nhiều.

Để kiểm tra Image đã được build, bạn dùng lệnh:

docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
docker-test 1.0 2451fc6aaa3b 9 seconds ago 429MB

Một danh sách Image trên Local Registry của chúng ta sẽ hiện ra. Bao gồm Repository (tên Image), Tag, Image ID, Create time, Size.

Okie, giờ đã có cái để chúng ta có thể chạy thử:

docker run < ID của Image hoặc tên của Image kèm theo Tag>

Để chạy docker-test image vừa build:

docker run 0312aa41b74f

# hoặc

docker run docker-test:1.0

Cả 2 dòng lệnh trên đều in ra kết quả như sau:

➜ docker_sample git:(master) docker run docker-test:1.0
* Serving Flask app “main” (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 265-615-895

Nếu để ý sẽ thấy dòng sau: Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

Đây là đoạn log khi chạy ứng dụng của chúng ta. Dù bạn thấy rằng hiện ứng dụng đã chạy ở địa chỉ 127.0.0.1 và port 5000, thì khi vào browser trên máy vẫn không thể access được. Lý do là vì địa chỉ được in ra thuộc network của Docker Container, hãy thử dùng một dòng lệnh khác để chạy Container khác nhé (để thoát khỏi log của Container đang chạy, nhấn Ctrl+C, sau đó dùng lệnh kế:

docker run -d –name binded_port_container -p 8000:5000 docker-test:1.0

Giải thích:

  • Với -d, Docker sẽ chạy Container với Detached Mode, có nghĩa là Container sẽ chạy nền và log của Container sẽ không hiện ra như dòng lệnh trước
  • Dùng cờ –name để đặt tên cho Container, một xí nữa bạn sẽ thấy sự khác biệt
  • Dùng cờ -p để binding port lại, số ở phía trước “:” là port của máy chủ (8000), ở sau là port của Container (5000).

Sau khi chạy xong bạn sẽ thấy một dòng báo hiệu Container đã chạy, mở browser và access thử localhost:8000 bạn sẽ thấy dòng Hello World

Để kiểm tra các Container đang chạy, chúng ta sẽ dùng lệnh “docker ps” và một danh sách sẽ được in ra:

➜ docker_sample git:(master) docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
032dbf3da035 docker-test:2.0 “/bin/sh -c ‘python3…” About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp trusting_thompson
b07485e03132 docker-test:1.0 “/bin/sh -c ‘python3…” 9 minutes ago Up 9 minutes 0.0.0.0:8000->5000/tcp binded_port_container
43306dfd95b1 docker-test:1.0 “/bin/sh -c ‘python3…” 18 minutes ago Up 18 minutes tender_murdock
d3b52a7b4a0c 0312aa41b74f “/bin/sh -c ‘python3…” 19 minutes ago Up 19 minutes frosty_murdock

Chúng ta có thể thấy các thông tin như tên của Container (sẽ random generate nếu không được chỉ định) và các Port được bind với nhau, mỗi Container cũng có một ID khác nhau, ví dụ thông tin của Container vừa được run:

  • CONTAINER ID: b07485e03132
  • IMAGE: docker-test:1.0
  • PORTS:  0.0.0.0:8000->5000/tcp
  • NAME: binded_port_container
  • CREATED: 9 minutes ago

Okay, giờ chúng ta sẽ thử một số thao tác khác:

Dừng một Container:

# docker stop < Tên của Container hoặc ID của Container>

docker stop binded_port_containter

# docker stop b07485e03132

Nếu gõ “docker ps” , bạn sẽ không thấy Container đó nữa. Container đó thực chất vẫn còn tồn tại với trạng thái Existed (Stopped). Với “docker ps -a” , bạn sẽ thấy được Container này. Để restart lại Container đó, dùng lệnh “docker start”:

docker start binded_port_container

# docker start b07485e03132

Gõ “docker ps” để kiểm tra Container đã được restart lại.

Bạn có thể một vài câu lệnh và cờ khác liên quan tới vòng đời của một Container. Và dọn dẹp sau đó. Để dọn dẹp hoàn toàn các Container,  bạn có thể dùng những lệnh sau (sau khi stop các Container):

# Xoá những Container đã Existed / Stopped

docker container prune

# Xoá toàn bộ những Container đã stopped, những Image “ảo” được cache lại trong quá trình build Image, xoá những Docker Network (Khi chạy một Container, Docker sẽ đăng ký một Network interface trên máy chủ)

docker system prune

# Xoá những local volume không sử dụng (Mình sẽ demo công dụng của binding volume tí nữa)

docker volume prune

Khi chạy xong thì bạn sẽ phải nhập y (Yes) hoặc N (No) để confirm rằng mình muốn xoá:

➜ ~ docker system prune
WARNING! This will remove:
– all stopped containers
– all networks not used by at least one container
– all dangling images
– all dangling build cache
Are you sure you want to continue? [y/N]

Gõ “docker ps -a” để đảm bảo đã dọn dẹp gọn gàng đống Container.

Bạn cũng có thể xoá hẳn luôn cả Docker Image được ra:

# docker rmi < Tên và tag của Image hay ID của Image>

docker rmi docker-test:1.0

# Hoặc

docker rmi 0312aa41b74f # <=== ID của Image docker-test:1.0

Nếu xoá không được Image thì có thể do một Container nào đó vẫn còn đang chạy dựa trên Image đó.

Chúng ta vừa đi qua một số lệnh cơ bản sau:

  • docker ps: liệt kê danh sách các Container và trạng thái của chúng
  • docker build: dùng để build một Docker Image từ Dockerfile.
  • docker images: dùng để liệt kê danh sách cái Image có sẵn trong Local Registry
  • docker run: dùng để khởi tạo một Container instance từ một Docker Image.
  • docker stop: dùng để dừng một Container đang chạy.
  • docker start: dùng để chạy lại một Container đang dừng.
  • docker <gì đó> prune: dọn dẹp các Container, cached images, volume và network được tạo bởi Docker trong quá trình khởi tạo Container.
  •  docker rmi: xoá một Image ở trên Local Registry

Tiếp đến, chúng ta sẽ thử chạy một Image đã build sẵn. Hầu hết các dịch vụ nổi tiếng và được nhiều người sử dụng đều đã được viết sẵn Dockerfile và build Image, những Image và Dockerfile này được share public trên trang https://hub.docker.com .

Việc đầu tiên cần làm là truy cập trang Web trên, đăng ký một Docker ID (Một lát nữa chúng ta sẽ dùng tới nó ^^).

Giả định, mình đang cần dựng nhanh một instance Mongo database để tạo Collection, vọc linh tinh. Mình có thể sử dụng Docker Image đã build sẵn và được publish ở trên Docker Hub:

docker pull mongo

# Ý nghĩ tương tự với git clone

Nếu không chỉ định Tag của Image, Docker sẽ pull Image với tag là latest từ Docker Hub.

➜ ~ docker pull mongo
Using default tag: latest
latest: Pulling from library/mongo
18d680d61657: Already exists
0addb6fece63: Already exists
78e58219b215: Already exists
eb6959a66df2: Already exists
1bb66a4db707: Already exists
b18fa018e44b: Already exists
66804df38cf1: Pull complete
49311c56c330: Pull complete
178125f0d942: Pull complete
26df264cf5ba: Pull complete
d3cc397c5b0b: Downloading [=====> ] 10.2MB/87.07MB
41e1e68a27fe: Download complete
4c9327cacf3d: Download complete

Cơ chế của pull cũng gần giống với build Image, đó là nó sẽ check các bản Image ID có sẵn và sẽ chỉ pull những phần build khác còn thiếu. Việc này sẽ giúp quá trình pull nhanh hơn.

Dùng “docker images” để check lại danh sách các Image tại Local:

➜ docker_sample git:(master) docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
mongo latest f4f3756fa507 40 hours ago 382MB
mongo 4.0.3 05b3651ee24e 4 weeks ago 382MB

Với Mongo image này, chúng ta cũng có thể chạy tương tự như những Image khác bằng “docker run”, nhưng phần lớn chúng ta muốn lưu lại và access được những system file của Mongo. Trong trường hợp này, ta có sử dụng binding volume:

Đầu tiên, tạo một ổ chứa trên máy để có thể bind với Docker Volume:

# Với MacOS hoặc Linux OS

WORKING_DIR=$(pwd)

docker run -v $WORKING_DIR/data/:/data/db mongo

Giải thích:

  • Lệnh pwd sẽ giúp lấy đường dẫn thư mục hiện tại. Mình gán vào biến WORKING_DIR để sử dụng sau này
  • Sử dụng lệnh docker run cùng với cờ -v  sẽ giúp bind thư mục của máy chủ với thư ổ chức của Docker, ở đây mình dẫn thẳng tới thư mục /data/db (tương tự với Network phải không ^^).
  • Một vài lưu ý:
    • Nếu đường dẫn không tồn tại, Docker có thể tạo các thư mục và đường dẫn đúng theo lệnh nếu có quyền.
    • Do cần quyền nên nếu tạo không bind được, các bạn nên check lại permission của folder hay drive đã được shared hay chưa.
    • Nên sử dụng absolute path cho các mục trên host volume.

Check lại folder data bạn sẽ thấy một cơ số file đã được đồng bộ từ phía Container mongo qua:

docker_sample git:(master) ✗ tree data
data
├── WiredTiger
├── WiredTiger.lock
├── WiredTiger.turtle
├── WiredTiger.wt
├── WiredTigerLAS.wt
├── _mdb_catalog.wt
├── collection-0-7461225930492241826.wt
├── collection-2-7461225930492241826.wt
├── collection-4-7461225930492241826.wt
├── diagnostic.data
│   └── metrics.2018-11-17T17-40-10Z-00000
├── index-1-7461225930492241826.wt
├── index-3-7461225930492241826.wt
├── index-5-7461225930492241826.wt
├── index-6-7461225930492241826.wt
├── journal
│   ├── WiredTigerLog.0000000001
│   ├── WiredTigerPreplog.0000000001
│   └── WiredTigerPreplog.0000000002
├── mongod.lock
├── sizeStorer.wt
└── storage.bson

2 directories, 20 files

Okay, vậy là chúng ta đã hiểu thêm về binding volumes với Docker Container. Kế đến sẽ là về việc Push / Published một Image được build lên Docker Hub hay một Remote Registry khác, trước hơn hết chúng ta sẽ build lại Image ở phần đầu:

docker build -t locmai/docker-test:1.0 .

Sự khác biệt: Ở đây mình đã thêm một phần ở trước tên Image: Docker ID – locmai.

Kiểm tra lại images được build:

➜ docker_sample git:(master) docker images “locmai/*”
REPOSITORY TAG IMAGE ID CREATED SIZE
locmai/docker-test 1.0 65da2c265694 46 seconds ago 429MB

Để push lên Docker Hub:

docker push locmai/docker-test:1.0

Docker có thể sẽ yêu cầu bạn phải login với Docker ID đã đăng ký. Ở đây sử dụng Docker ID mà bạn đã đăng ký để đặt tên cho Image để Docker có thể tìm repo chính chủ trên Docker Hub và push lên đó.

Đây là Image của mình đã push lên sau khi build: https://hub.docker.com/r/locmai/docker-test/

Tóm gọn về một số lệnh mới:

  • docker pull: dùng để pull Image có sẵn từ Docker Hub hay một Remote Registry khác
  • docker push: dùng để push một Image từ Local Registry lên Docker Hub hay một Remote Registry khác.
  • docker run -v: binding volumes giữa máy chủ và Container

Ồ, hết rồi!!!

Trước khi kết thúc mình xin rút kết lại một số ý:

  • Sử dụng Docker nếu bạn cần triển khai một ứng dụng Web hay công cụ hỗ trợ nhanh nhất có thể.
  • Container là khái niệm về phân tách các Process bởi một Container Engine, giúp các Process mang tính đóng gói hơn.
  • Docker Image là một mẫu mô tả về Container. Xem Image như Class và Container như Instance của Class đó.
  • Các lệnh quản lý vòng đời của Container bao gồm: run, start, stop, ps.
  • Các lệnh quản lý Image bao gồm: images, rmi, build, pull, push.
  • Để dọn dẹp: docker system prune

Bài viết cũng đã khá dài, hi vọng những khái niệm về Docker sẽ trở nên dễ hiểu hơn với mọi người và có thể thử áp dụng trong công việc hàng ngày. Good luck guys! ^^

Phụ lục

Sự khác biệt giữa Container và Virtual Machine (Máy Ảo)

Container khác biệt với Virtual Machine như VMWare hay VirtualBox ở điểm công nghệ Container không giả lập toàn bộ phần cứng như các Virtualization tool mà thay vào đó các Container nói chuyện trực tiếp với Kernel của máy chủ thông qua Container Engine. Do đó các “máy-tính-con” container sẽ vô cùng nhẹ ký (light-weight). Một hình ảnh so sánh được sử dụng khá nhiều:

ContainervsVM.png

Advertisements

2 comments

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s