2020.06.10
DOCKER LÀ GÌ?
Chắc các bạn cũng ít nhiều đã nghe những lời đồn về sự hay ho của docker rồi, vậy docker thực chất có hay ho như vậy không, hay chỉ là một mớ hỗn độn với một đống lệnh lạ lùng mà dev dính phải nữa đây? Bài viết này mình sẽ cùng với các bạn xem thử docker là gì, tại sao nó lại “hot” đến thế, cấu trúc và cách thức hoạt động nó như thế nào. Qua đó các bạn sẽ có một cái nhìn tổng quát nhất về Docker và có thể tiếp cận sử dụng nó một cách dễ dàng nhất.
Tôi đã bắt đầu với docker như thế nào?
Mình chia sẻ câu chuyện xàm của bản thân mình trước nhé. Trước đây khi mới lập trình PHP, mình hay sử dụng XAMPP hay WAMP để lập trình (cục này là web apache, mysql và php), mọi chuyện vẫn tốt đẹp đến khi có yêu cầu mới là sử dụng SQL Server thay cho MySQL, và từ đây câu chuyện của mình với XAMPP WAMP đã không còn mấy vui vẻ nữa.
Đó chỉ mới đơn giản thôi, sau này với dự án xài các công nghệ khác, thư viện khác, database khác, chẳng hạn python – flask làm backend, Vue.js làm front end, Mongodb làm database, chưa kể version nữa nhé, theo cách cũ mà cài hết đống này vô máy đã mệt, đụng với phần mềm nào đó trong máy nữa thì tèo luôn hệ điều hành và cài lại hết 🙁 , còn chưa kể nếu bạn làm 2-3 dự án khác nhau với công nghệ khác nhau nữa.
Và mình đã được tiếp cận với Docker để có thể tạo ra một môi trường ảo hóa chứa đầy đủ các cài đặt cần thiết tùy theo từng dự án, chuyển đổi linh động dễ dàng mà ko ảnh hưởng đến máy host (máy thật của mình đang cài docker – ở bài này mình gọi là máy host cho dễ nhé).
Tại sao lại chọn Docker?
- Khi lập trình thì team dev phải đồng nhất các công nghệ, các version với nhau: Sử dụng docker để tạo ra container theo yêu cầu của dự án, dev chỉ ôm về chạy thôi là đồng bộ hết, khi cần chuyển dự án khác thì ôm cái container của dự án đó về chạy là được rồi.
- Test: Khi tester kiểm tra thì ôm cái container về chạy một cách đơn giản, không cần cài đặt gì nhiều.
- Deploy: Hiện nay có nhiều Cloud service đã tích hợp hỗ trợ docker lên các dịch vụ của họ như Amazon hay Google Platform,… nên việc deploy sẽ được hỗ trợ dễ dàng hơn nhiều với docker
- Ngoài ra, với xu hướng sử dụng công nghệ microservice hiện nay thì docker là một phần không thể thiếu được, thử tưởng tượng xem nếu bạn có 100 cái microservice và không có docker, bạn sẽ phải quản lý 100 cái server hoặc vps? Việc này sẽ cực kỳ vất vả và tốn nhiều thời gian. Với việc sử dụng Docker thì việc đó đơn giản hơn rất nhiều.
Thêm nữa các công ty lớn đã tích hợp Docker vào sản phẩm của họ khá nhiều rồi, cùng điểm danh nhé
- Docker có thể được tích hợp vào các công cụ, bao gồm cả Amazon Web Services, Ansible, CFEngine, Chef, Google Cloud Platform, IBM, Jelastic, Jenkins, Microsoft Azure, OpenStack Nova, OpenSVC, HPE Helion Stackato, Puppet, Salt, Vagrant, và VMware vSphere Containers.
- Dự án Cloud Foundry Diego tích hợp Docker vào Cloud Foundry PaaS
- Red Hat cũng tích hợp Docker vào OpenShift
- Apprenda tích hợp Docker trong phiên bản 6.0 sản phẩm của mình
Tại sao lại chọn Docker?
Bắt đầu từ những ngày đầu tiên, mô hình server thường sẽ là Máy chủ vật lý + Hệ điều hành OS + Application
Vậy muốn xài 2 dịch vụ thì ta phải có 2 server như vậy, và chi phí cho mỗi server như vậy là không hề ít một tí nào.Tiếp theo là sự ra đời của công nghệ ảo hóa virtualization
Okie vậy xài 2 service thì không cần đến 2 server nữa, cần 1 server và tạo 2 virtual machine riêng là xong. Cũng ổn nhỉ?
Nhưng giờ 1 server 100Gb ổ cứng, 8Gb ram, 4 core CPU, còn một virtual machine mở lên cần 20Gb ổ cứng, 2Gb ram và 2 core CPU; vậy mở cái virtual đó lên ngắm cái cũng tốn từng đó tài nguyên rồi, mở 2- 3 cái là full resource dù chả làm gì với nó cả. Cũng hơi hơi phí phạm nhỉ.Vậy đến lượt công nghệ ảo hóa containerization được sinh ra
Vậy công nghệ này khác virtualization chỗ nào? Đó chính là containerization sử dụng các container, các container này sẽ sử dụng chung nhân OS kernel với máy chủ host, điều này có nghĩa là khi container hoạt động cần tài nguyên, nó sẽ trực tiếp lấy từ máy host như một phần mềm bình thường chạy trên máy host vậy, điều này tránh lãng phí tài nguyên từ máy ảo khi không sử dụng như trong công nghệ virtualization.
Giờ quay lại với Docker nhé.
Với công nghệ ảo hóa virtualization chắc đa số mọi người đều đã quen với Virtualbox hay VMware rồi nhỉ? Vậy thì công nghệ containerization dùng cái gì đây? Đó là Docker.
Như vậy, Docker đơn giản là tên một phần mềm – công cụ – công ty sử dụng công nghệ ảo hóa containerization để triển khai các ứng dụng application vào trong container ảo hóa.
Docker sử dụng nhân kernel linux để chạy các container, trên hệ điều hành Linux Docker có thể sử dụng trực tiếp nhân của máy host; còn với các hệ điều hành Windows, MacOS – có thể vì lý do bảo mật nên docker không thể trực tiếp xài chung kernel với các hệ điều hành này nên trên các hệ điều hành này docker sẽ tạo ra một máy ảo virtual guest với nhân linux để chạy các container.
Docker architecture
Docker Engine
Docker Engine là phần cốt lõi của Docker, được xây dựng theo kiểu kiến trúc client-server và được cài đặt trên máy Host. Docker Engine có 3 thành phần:
- Server: Docker daemon (dockerd) dùng để tạo và quản lý các images, containers, networks, volumes.
- Rest API: controller cho docker daemon, chỉ ra những gì docker daemon sẽ làm.
- Command Line Interface (CLI): Nơi mà Client sử dụng các câu lệnh Rest API để tương tác với Docker daemon
The Docker client
Người dùng tương tác với docker thông qua command trong terminal. Docker Client sẽ sử dụng API gửi lệnh tới Docker Daemon.
Docker registries
Đây là nơi lưu trữ riêng của Docker Images. Images được push vào registry và client sẽ pull images từ registry. Có thể sử dụng registry của riêng bạn hoặc registry của nhà cung cấp như: AWS, Google Cloud, Microsoft Azure.
Docker objects
Khi làm việc với Docker sử dụng các images, containers, volumes, networks; đó là các Docker Object
Images
Docker images là một dạng read-only templates với các lệnh cấu trúc để tạo ra một container. Docker images có thể được tải về từ Docker hub và sử dụng, hoặc có thể xây dựng dựa trên một images cơ sở – thường là bản ubuntu tối giản chỉ có cài đặt duy nhất các service cần dùng – cùng với các lệnh cấu trúc cài đặt để xây dựng ra một images mới. Cũng có thể xây dựng một Docker images bằng Dockerfile – chứa tất các các lệnh để cấu trúc nên một container, khi chạy file này sẽ sinh ra một custom Docker images.Giả sử ở đây mình muốn sử dụng database mysql version 5.7, mình có thể dễ dàng tải image này một cách dễ dàng bằng commandline “docker pull mysql:5.7”, mysql là tên của image và 5.7 là tag phiên bản của image đó, các bạn có thể xem cụ thể ở Docker hub nhé
Containers
Sau khi run docker image sẽ tạo ra docker container tương ứng. Tất cả ứng dụng và môi trường cài đặt trong image sẽ được chạy trong container. Có thể sử dụng Docker API hoặc CLI để quản lý run, start, stop, delete docker container.
Thử chạy một docker container với image mysql đã tải về bằng lệnh
Kiểm tra các container đang chạy bằng lệnh “docker ps”
Như vậy chúng ta đã khởi tạo một container có tên là mysql-5.7 từ images mysql tag 5.7 với pass root là my-secret-pw
Các bạn có thể tìm hiểu thêm nhiều lệnh tại đây nhé
Volumes
Dữ liệu được sinh ra và sử dụng bởi các container được lưu trữ trong volumes – được quản lý bởi Docker API hoặc CLI.
Các dữ liệu trong container chỉ tồn tại khi container đó hoạt động và sẽ mất khi xóa container, việc sử dụng volumes không làm tăng kích thước của một container.
Có thể sử dụng -v hoặc -mount flag để tạo container với volume.
Ở trên chúng ta đã có được container chạy mysql rồi, vậy vấn đề là khi có update data trên container đó, làm sao chúng ta có thể lưu được data lại vào máy host của mình? Chúng ta có thể tạo một volumes mới và mount vào folder lưu trữ dữ liệu của mysql để lấy dữ liệu ra máy host
Tạo một volume tên là database và ánh xạ vào máy host theo đường dẫn /Users/nhanvien6/Documents/database bằng lệnh
docker volume create --driver local \ --opt type=nfs \ --opt device=/Users/nhanvien6/Documents/database \ database
Mount vào container mysql
Networks
Cho phép kết nối các container lại với nhau. Kết nối này có thể trên 1 host hoặc nhiều host. Có 5 network drivers trong docker:
- Bridge: Các bridge driver tạo một Linux bridge trên host và được quản lý bởi Docker. Theo mặc định các container trên một bridge có thể giao tiếp với nhau. Truy cập bên ngoài vào container cũng có thể được cấu hình thông qua bridge driver. Người dùng có thể tự định nghĩa trong lúc tạo ra networking. Ngược lại sẽ mặc định là docker0. Đơn giản hơn là kiểu này thì container sẽ truy cập được Internet thông qua máy Host
- Host: Một container sử dụng network stack của host và không có sự phân tách namespace. Các container có thể sử dụng tất cả các interface trên host.
- Overlay: Tạo một overlay network hỗ trợ các mạng nhiều máy chủ(host). Sử dụng kết hợp các Linux bridge local và VXLAN để overlay các giao tiếp giữa container sang container trên cơ sở hạ tầng mạng vật lý (physical network infrastructure). Sử dụng cho dịch vụ Docker swarm có thể liên lạc được với nhau
- None: Vô hiệu hóa mạng
- Macvlan: Truyền tải theo địa chỉ Mac (layer 2 trong mô hình OSI). Sử dụng khi muốn dùng các container như những thiết bị physical devices.
Dockerfile
Dockerfile là một file dạng text, không có đuôi, giúp thiết lập cấu trúc cho docker image nhờ chứa một tập hợp các câu lệnh. Từ những câu lệnh đó, Docker có thể thực hiện đóng gói một docker images theo yêu cầu tùy biến của riêng bạn.
Giờ ta cần một container PHP kết nối với MySQL, công việc ta cần là tạo một container từ image php và cài thêm extender hỗ trợ kết nối MySQL cho PHP. Với Dockerfile ta có thể xây dựng một customs image từ image php và hỗ trợ kết nối MySQL một cách đơn giản như sau
FROM php:7.2-fpm # Install dependencies RUN apt-get update && apt-get install -y # Install extensions RUN docker-php-ext-install pdo_mysql exif pcntl CMD ["php-fpm"]
Các bạn có thể tìm hiểu thêm về dockerfile tại đây
Docker-compose
Okie, vậy với các câu lệnh trong Docker objects chúng ta đã có thể xây dựng một Container từ Image được tải về từ Docker registries (Docker hub) với các service về lưu trữ và mạng bằng các Volumes – Networks. Chúng ta cũng có thể tự xây dựng một custom docker image bằng cách sử dụng Dockerfile. Vậy với một dự án mà chúng ta cần sử dụng nhiều container thì sao? Lần lượt xây dựng 5 6 cái container như vậy thì khá mất thời gian và cũng không vui cho lắm nhỉ. 🙂
Đừng lo lắng vì đã có Docker-compose rồi nhé. Docker-compose là một công cụ tuyệt vời để định nghĩa và chạy nhiều container trong Docker. Tạo 1 file cấu hình YAML, định nghĩa các services trên ứng dụng của bạn và định nghĩa tất cả các bước, các cấu hình cần thiết để xây dựng các image, up các container và liên kết chúng với nhau. Cuối cùng, chúng ta có thể chạy tất cả container với một lệnh duy nhất.Như vậy Docker compose giúp ta tự động tải các image, thiết lập cấu hình tốt hơn rất nhiều so với docker. Nó sẽ cần một file cấu hình docker-compose.yml để chạy theo các image và cấu hình trong đó để tạo thành một hệ thống các container.
Ví dụ mình đang cần xây dựng mô hình gồm Nginx – PHP – MySQL, thì mình có thể tạo một docker-compose đơn giản như sau
# file name: docker-compose.yml version: '3' # make services services: # make service websever by nginx laravel-nginx: image: nginx:1.18 container_name: laravel-nginx hostname: nginx ports: - "80:80" volumes: - ./docker/config/nginx/:/etc/nginx/conf.d/ - ./source/:/home/website/ # make service language by PHP laravel-php: build: context: ./docker/config/php dockerfile: Dockerfile container_name: laravel-php hostname: php volumes: - ./source/:/home/website/ working_dir: /home/website/ # make service database by mysql laravel-mysql: image: mysql:8.0.19 container_name: laravel-mysql hostname: mysql command: --default-authentication-plugin=mysql_native_password environment: MYSQL_DATABASE: db_laravel MYSQL_ROOT_PASSWORD: 123456 MYSQL_USER: homestead MYSQL_PASSWORD: secret ports: - "3306:3306"
Giờ mình chỉ cần chạy lệnh docker-compose up là sẽ start được cả 3 dịch vụ này lên rồi, lợi hại quá =))
Giả sử mình không muốn xài mysql 8.0.19 mà xài MySQL 5.7 thì mình chỉ cần chỉnh phiên bản của MySQL trong file docker-compose.yml và chạy lại lệnh docker-compose up là xong rồi. Quá tiện lợi nhỉ.
Kết
Tóm lại, sử dụng docker có rất nhiều lợi ích cho việc khởi tạo môi trường cho lập trình, test, deploy, microservice và đang là công nghệ được sử dụng rộng rãi thay cho các môi trường cài trực tiếp vào máy host.
Tìm hiểu về docker các bạn có thể tìm hiểu:
- Các lệnh Docker API hoặc CLI để quản lý trực tiếp các images và container.
- Dùng Dockerfile để tùy biến tạo một images theo các custom cần thiết
- Dùng Docker-compose để cài đặt, quản lý, cấu hình cho nhiều container
- Kết hợp Dockerfile và Docker-compose để xây dựng mô hình với nhiều tùy biến hơn.