Docker là gì?
Docker là một nền tảng dành cho các developer và sysadmin để phát triển, triển khai và chạy các ứng dụng bằng các container. Việc đóng gói thành container này giúp cho việc triển khai các ứng dụng trở nên dễ dàng hơn.
Công nghệ container ngày càng phổ biến bởi:
- Linh hoạt: Có thể đóng gói từ ứng dụng đơn giản đến phức tạp
- Nhỏ gọn: Các container tận dụng, sử dụng chung tài nguyên; kernel của host. Có thể chạy ở mọi nơi, mọi nền tảng.
- Khả năng thay đổi linh hoạt: Cập nhật và nâng cấp nhanh chóng.
- Khả năng mở rộng: Dễ dàng tăng và phân tán tự động các container
- Phân tầng dịch vụ: Mỗi dịch vụ khi deploy sẽ được phân tầng, nằm trên các dịch vụ đang có sẵn. Như vậy sẽ không làm ảnh hưởng tới dịch vụ đang chạy.
Khái niệm containers và images
- Một container được khởi chạy từ image. Như vậy, image là một gói thực thi chứa bên trong là tất cả những gì cần thiết, liên quan để chạy ứng dụng như mã nguồn, các thư viện, runtime, các biến môi trường và các file cấu hình liên quan.
- Một container là một instance đang chạy được khởi tạo từ image.
So sánh giữa VM với container
- Container chạy trực tiếp trên môi trường máy chủ như một tiến trình và chia sẻ phần kernel bên dưới dùng chung với máy chủ chứa nó
- VM tạo ra một môi trường giả lập hoàn toàn tách biệt như 1 máy hoàn chỉnh thông qua việc phân bổ tài nguyên của máy chủ, do đó sẽ tốn tài nguyên nhiều hơn cho hệ điều hành của máy ảo
Cấu trúc và thành phần của Docker
Docker bao gồm:
- Docker Client: Giao diện để tương tác giữa người dùng với Docker Daemon - HOST
- Docker Daemon (HOST): Lưu trữ image local và khởi chạy container từ những image đó
- Docker Hub (registry): Nơi lưu trữ các images
Docker Client
Docker client dùng để tương tác giữa người dùng và Docker Daemon, Daemon sẽ biên dịch và thực thi các câu lệnh đã tương tác qua Docker client.
Xem phiên bản đang sử dụng
docker version
Câu lệnh sẽ trả về phiên bản của Docker client và Daemon (server)
Client: Version: 18.09.6 API version: 1.39 Go version: go1.10.8 Git commit: 481bc77156 Built: Sat May 4 02:34:58 2019 OS/Arch: linux/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 18.09.6 API version: 1.39 (minimum version 1.12) Go version: go1.10.8 Git commit: 481bc77 Built: Sat May 4 02:02:43 2019 OS/Arch: linux/amd64 Experimental: false
Xem thông tin chi tiết về Docker
Cung cấp thông tin về tài nguyên máy chủ, chi tiết về Docker.
docker info
Containers: 3 Running: 3 Paused: 0 Stopped: 0 Images: 7 Server Version: 18.09.6 Storage Driver: overlay2 Backing Filesystem: xfs Supports d_type: true Native Overlay Diff: true Logging Driver: json-file Cgroup Driver: cgroupfs Plugins: Volume: local Network: bridge host macvlan null overlay Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog Swarm: inactive Runtimes: runc Default Runtime: runc Init Binary: docker-init containerd version: bb71b10fd8f58240ca47fbb579b9d1028eea7c84 runc version: 2b18fe1d885ee5083ef9f0838fee39b62d653e30 init version: fec3683 Security Options: seccomp Profile: default Kernel Version: 3.10.0-957.10.1.el7.x86_64 Operating System: CentOS Linux 7 (Core) OSType: linux Architecture: x86_64 CPUs: 1 Total Memory: 991.2MiB Name: minion4 ID: 6BBX:UEEB:SDZ4:LGES:HSFN:WIEY:TASR:5MRK:JMV6:7O7W:CTGY:ATPX Docker Root Dir: /var/lib/docker Debug Mode (client): false Debug Mode (server): false Registry: https://index.docker.io/v1/ Labels: Experimental: false Insecure Registries: 127.0.0.0/8 Live Restore Enabled: false Product License: Community Engine
Tìm kiếm image trên registry
docker search python
- NAME: Tên của Image
- DESCRIPTION: Mô tả về image
- STARS: Số lượt rating. Số này càng cao thì chất lượng của Image càng tốt.
- OFFICIAL: Được cung cấp bởi Hãng hoặc Tổ chức đã được xác nhận trên Registry
Chạy một container từ Image
docker run -i -t --name web1 ubuntu
Khi chạy docker pull, mặc định sẽ tìm trên localhost xem có image nào trùng với yêu cầu trong câu lệnh hay không. Nếu image không có sẵn trên localhost, Docker sẽ tìm kiếm và tải về (pull) từ Registry mặc định.
- -i: Vào chế độ tương tác trực tiếp với Container
- -t: Hiển thị tty
- --name: Đặt tên cho container. Mặc định, nếu không đặt thì sẽ có tên ngẫu nhiên.
Để thoát ra khỏi chế độ tương tác, thao tác lần lượt CTRL + P sau đó CTRL + Q
Khởi động container ở chế độ chạy nền
docker run -d --name web1 ubuntu
Liệt kê các container
docker ps -a
-a hoặc --all: Hiển thị toàn bộ số container có trên hệ thống
- CONTAINER ID: ID của container
- IMAGE: Tên của Image khởi tạo
- COMMAND: Câu lệnh chính khi khởi động của container/image
- CREATE: Thời gian container được tạo
- STATUS: Trạng thái của container
- PORT: Cổng của container được ánh xạ với host (HOST:CONTAINER)
- NAMES: Tên của container
Liệt kê các image
docker images
Hoặc
docker image list
- REPOSITORY: Tên của image
- TAG: Phiên bản của image
Dừng hoạt động của container
docker stop web1
Khởi động của container
docker start web1
Có thể thêm -i để có thể tương tác trực tiếp với container.
Tương tác với Container đang hoạt động
docker attach web1
Hoặc tương tác sử dụng môi trường /bin/bash
docker exec -it web1 /bin/bash
Xóa container
Container chỉ bị xóa khi ở trạng thái dừng hoạt động.
docker rm web1
Tạo container ánh xạ port với HOST (Máy chủ)
Ánh xạ port ngẫu nhiên với HOST
docker run -d --name db4 -P -e MYSQL_ROOT_PASSWORD=mysql-1 mysql
-P: Ánh xạ ngẫu nhiên
-e: Gán biến môi trường của trong container
Kiểm tra các port ánh xạ của container
> docker port db4 3306/tcp -> 0.0.0.0:32777 33060/tcp -> 0.0.0.0:32776
Chỉ định port ánh xạ giữa container với HOST
docker run -d --name db5 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=mysql-1 mysql
Kiểm tra các port ánh xạ của container
> docker port db5 3306/tcp -> 0.0.0.0:3306
Ánh xạ một thư mục trên HOST vào bên trong container
Để ánh xạ, tùy chọn -v được sử dụng khi khởi tạo container. Ví dụ, ánh xạ thư mục lưu trữ dữ liệu của mysql trong container với một thư mục trên host.
mkdir -p /opt/mysql_data docker run -d -v /opt/mysql_data:/var/lib/mysql --name db6 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=mysql@123 mysql
Liên kết giữa các container với nhau
Việc liên kết các container để chúng có thể ‘trò chuyện’ với nhau thường được dùng bằng cách expose các port, điều này vô cùng bất lợi. Docker hỗ trợ liên kết các container với nhau bằng cách sử dụng tham số --link khi khởi tạo một container mới. Ví dụ, tạo một container khác để chạy ứng dụng webserver sử dụng database là container db6 vừa tạo ở bước trên:
docker run -d --link db6:db.example.com --name wp1 -p 80:80,443:443 wordpress
--link db6:db.example.com: Liên kết với container có tên là db6 và có alias là db.example.com (giá trị này tương đương với FDQN)
Docker Hub (Registry)
Docker Hub hay thường được gọi là Registry, nơi lưu trữ các image được cộng đồng hoặc các nhà phát triển đóng góp và cung cấp miễn phí, chúng ta có thể tìm các bản images tại đây. Điều này vô cùng tiện lợi, chúng ta chỉ cần pull (tải xuống) các image phục vụ cho nhu cầu ở mọi lúc mọi nơi.
Chúng ta cũng có thể dễ dàng tạo ra những bản image của riêng mình phục vụ cho việc học tập, nghiên cứu, làm việc và chia sẻ chúng cho cộng đồng. Các bước để thực hiện được điều đó như sau:
- Đăng kí một tài khoản tại https://hub.docker.com
- Đưa image của lên Hub
Các bước đưa (push) lên Hub
Ở ví dụ này, ta sẽ tạo một image và tạo một vài file trong đó rồi đóng gói lại thành một image.
Bước 1: Sử dụng một image có sẵn nhỏ gọn là alpine
docker run -it --name myimage1 alpine
Bước 2: Sau khi vào chế độ tương tác của container, tạo vài file bất kỳ và thoát khỏi container
touch a b c d e f ls exit
Bước 3: Lưu lại image tại Host local (commit)
docker commit myimage1 username/myimage1
username: Tên đăng nhập Hub
myimage1: Tên image muốn lưu trên Hub. Có thể kèm theo Tag. VD: myimage1:latest để đánh dấu image bản mới nhất.
Bước 4: Đăng nhập vào Docker Hub
docker login
Nhập user/password để đăng nhập
- Bước 5: Đưa image lên Hub (push)
docker push username/myimage1
Network trong Docker
Một trong những điểm mạnh của Docker đó là khả năng kết nối các container để chúng có thể giao tiếp được với nhau và có thể kết nối các container chạy trên các nền tảng khác nhau. (Linux, Windows,…)
Để liệt kê danh sách Network ở Docker, ta sử dụng câu lệnh sau:
docker network ls
Để xem các thông tin chi tiết của một Network nào đó, sử dụng câu lệnh:
docker network inspect <Network-name>
Các loại Network trong Docker
Sau khi cài đặt, Docker sẽ tạo mặc định 3 network: brigde, none và host. Khi khởi tạo container, ta có thể chỉ định cho chúng sử dụng network nào thông qua tùy chọn --network.
- brigde: Network driver mặc định. Mặc định sử dụng brigde khi không khai báo trong lúc khởi tạo container. Nó cho phép các container riêng biệt, đơn lẻ (standalone) có thể giao tiếp được với nhau. Dải IP mặc định được cấp cho brigde là 172.17.0.0/16
- host: Sử dụng thông tin về Network của host cho container. Được hỗ trợ từ phiên bản Docker 17.06 trở lên.
- none: Không sử dụng Network trong container.
- overlay: là một network driver cho phép kết nối các container nằm trên các Docker Host khác nhau, kích hoạt Swarm sử dụng để truyền thông. Các overlay network làm đơn giản hóa việc truyền thông giữa dịch vụ Swarm với container riêng biệt, đơn lẻ hay việc truyền thông giữa 2 container riêng lẻ nằm trên các Docker deamon (Host) khác nhau. Cách này sẽ xóa bỏ việc phải định tuyến (routing) phức tạp ở mức OS giữa các container với nhau.
Giao thức | Cổng | Mục đích |
---|---|---|
TCP | 4789 | Truyền dữ liệu (data) |
TCP/UDP | 7946 | Điều khiển (control) |
- macvlan: Sử dụng để gán địa chỉ MAC cho container với mục đích là cho container có vai trò như một thiết bị vật lý. Docker daemon sẽ định tuyến luồng gói tin tới các container thông qua các địa chỉ MAC này. Cách này vô cùng hữu hiệu cho các ứng dụng cũ /lỗi thời (legacy app) các kết nối sẽ được chuyển trực tiếp tới lớp Vật lý thay vì phải định tuyến thông qua lớp mạng bên trong Docker.
Tóm tắt về Network trong Docker
- User-defined bridge networks: là sự lựa chọn tốt nhất khi muốn các container trên cùng một host có thể giao tiếp với nhau. (Bridge driver)
- Host networks: được sử dụng trong trường hợp muốn sử dụng chung các thông tin về Network trong container nhưng tách biệt các thông tin khác.
- Overlay network: Trong trường hợp muốn các container trên các host khác nhau có thể truyền thông qua lại hay muốn nhiều container làm việc cùng nhau khi sử dụng Swarm thì đây là một sự lựa chọn.
- MACVlan network: Sử dụng trong trường hợp muốn container có thể giao tiếp như một thiết bị vật lý, mỗi container sẽ có một địa chỉ MAC duy nhất, không trùng lặp.
Volume trong Docker
Docker volumes vô cùng hữu ích với 2 TH muốn lưu trữ và chia sẻ dữ liệu của các container. Điều này vô cùng quan trọng, khi một container bị xóa bỏ có nghĩa rằng mọi dữ liệu bên trong chúng cũng đều bị ‘bốc hơi’. Do vậy, để dữ liệu đó không bị mất thì Docker Volume là một tính năng hữu hiệu.
Để sử dụng Docker volume, khi khởi chạy một container hãy thêm tùy chọn -v vào sau câu lệnh docker run.
Khi nào cần sử dụng Volume?
Giả sử, ta có một container làm web server. Khi đó ta sẽ ánh xạ một thư mục trên host để chứa mã nguồn với thư mục /var/www/html (thư mục chứa mã nguồn mặc định. Điều này vô cùng hữu ích khi ta muốn cập nhật mã nguồn (thêm xóa dữ liệu) của trang web; thay vì phải vào bên trong container để thao tác, ta có thể thao tác trực tiếp ở thư mục được ánh xạ trên host.
Các loại Volume trong Docker
Docker hỗ trợ 3 kiểu Volume như sau:
- Bind mount
- Volume
- tmpfs mount
Bind mount
- Bind mount: là một kỹ thuật để ánh xạ trực tiếp một thư mục trên host với một thư mục cụ thể nào đó bên trong container. Khi container bị xóa, dữ liệu bên trong thư mục sẽ không bị ảnh hưởng.
Volume
- Volume: giống với bind mount nhưng thư mục ánh xạ sẽ được quản lý bởi Docker. Thư mục chứa mặc dịnh tại /var/lib/docker/volumes/
tmpfs mount
- tmpfs mounts được sử dụng trong các trường hợp ta không muốn dữ liệu tồn tại trên Docker host hay containers vì lý do bảo mật hoặc đảm bảo hiệu suất của containers khi ghi một lượng lớn dữ liệu một cách không liên tục.
Dockerfile
Dockerfile là một tập tin dạng text chứa một chuỗi các câu lệnh, chỉ thị để tạo nên một image. Dockerfile bao gồm các câu lệnh liên tiếp thực hiện tự động dựa trên một image có sẵn để tạo ra một image mới.
Cú pháp trong Dockerfile
# Comment INSTRUCTION arguments
Trong đó:
- INSTRUCTION: Là các câu lệnh, chỉ thị được Docker quy định và toàn bộ những chỉ thị này phải được viết bằng chữ IN HOA.
- arguments: Phần nội dung của chỉ thị
Ví dụ:
RUN echo "Hello world!"
Các câu lệnh/chỉ thị trong Dockerfile
Dockerfile chứa một tập hợp các câu lệnh bao gồm cả của Docker và các câu lệnh của OS. Trước hết, cần tìm hiểu rõ các câu lệnh của Dockerfile.
- FROM: Dựa trên một image có sẵn để tạo ra một image mới. Chỉ thị này phải được đặt ở đầu Dockerfile.
- MAINTAINER: (Tùy chọn) Điền thông tin của tác giả, người tạo ra image.
- RUN: Chỉ thị dùng để thực thi câu lệnh ở bên trong image
- ADD: Dùng để sao chép một file hoặc folder từ Host vào trong image. Có thể sử dụng một URL, Docker sẽ tải về thư mục đích bên trong image.
- ENV: Khởi tạo một biến môi trường bên trong image.
- CMD: Sử dụng để thực thi một câu lệnh khi tạo container được tạo từ image.
- ENTRYPOINT: Chỉ ra một câu lệnh được thực thi khi container chạy.
- WORKDIR: Chỉ ra thư mục làm việc khi tạo image hoặc khi khởi chạy container
- USER: Xác định user (UID) thực thi các câu lệnh ở các chỉ thị CMD, RUN, ENTRYPOINT,… được xác định ở phía sau nó.
- VOLUME: Cho phép truy cập/liên kết thư mục giữa container với host.
- EXPOSE: Khai báo các Port Container sử dụng.
- ARG: Khai báo sử dụng tham số khi build image sử dụng câu lệnh docker build với cờ--build-arg <varname>=<value>
Chia sẻ một số Dockerfile
- KMS Server
FROM alpine MAINTAINER hoangdh <github.com/hoangdh> ENV LIB python3-tkinter python3-dev sqlite-dev ENV DEP build-base git py-pip RUN apk update \ && apk add --no-cache $LIB $DEP \ && git clone https://github.com/SystemRage/py-kms /tmp/py-kms \ && mv /tmp/py-kms/py-kms /opt/ \ && pip install tzlocal pysqlite3 \ && apk del $DEP; rm -rf /tmp/* EXPOSE 1688 CMD python3 /opt/py-kms/pykms_Server.py --logfile /var/log/pykms.log --logsize 1 -w RANDOM
FROM alpine
MAINTAINER hoangdh <github.com/hoangdh>
RUN apk add --no-cache build-base git \
&& git clone https://github.com/Wind4/vlmcsd /tmp/vlmcsd \
&& cd /tmp/vlmcsd \
&& make \
&& mv /tmp/vlmcsd/bin/vlmcsd /usr/sbin/vlmcsd \
&& cd / && rm -rf /tmp/* \
&& apk del build-base git
EXPOSE 1688
CMD /usr/sbin/vlmcsd -p /var/run/kmsd.pid -l /var/log/kmsd.log -D
Docker-compose
Ref: https://docs.docker.com/compose/overview/
docker-compose là một công cụ để tạo, xác định và chạy nhiều container có mối liên quan với nhau trong cùng một thời điểm; được khai báo trong một file với định dạng YAML. Khởi động tất cả các dịch vụ chỉ với 1 câu lệnh duy nhất.
Với 3 bước cơ bản như sau:
- Định nghĩa các ứng dụng thông qua Dockerfile
- Định nghĩa các ứng dụng chạy tách biệt và khởi động cùng nhau trong docker-compose.yml
- Thực thi câu lệnh docker-compose up -d để hoàn tất
Một file docker-compose.xml mẫu:
version: '3' services: web: build: . ports: - "5000:5000" volumes: - .:/code - logvolume01:/var/log links: - redis redis: image: redis volumes: logvolume01: {}
Sử dụng docker-compose để quản lý vòng đời ứng dụng cụ thể xem và quản lý trạng thái của các service (Start, stop, rebuild,…); chuyển log của các ứng dụng đang chạy.
Tính năng, lợi ích
- Tạo ra nhiều môi trường riêng biệt trên cùng 1 host
- Dữ liệu được bảo toàn
- Chỉ khởi tạo lại khi có sư thay đổi
- Các thành phần và biến được sử dụng giữa các môi trường