Architecture
Docker là 1 công nghệ cực kỳ mạnh mẽ, và điều này thường có nghĩa là một thứ gì đó đi kèm độ phức tạp cực kỳ cao. Nhưng nền tảng kiến trúc của Docker thì chỉ là dạng Client/Server đơn giản, cùng với duy nhất 1 cách thực thi là hoạt động giống như cả 1 khối, dựa vào cách bạn gọi docker command. Ta sẽ đi vào cách mà client và server hoạt động và giới thiệu về lớp network (mạng) hoạt động bên dưới Docker container.
1. Client/Server Model.
Docker bao gồm ít nhất 2 phần: client và server.
Thông thường nó gồm 3 thành phần là: Docker Registry (nơi lưu trữ Docker images và metadata về đống images đó). Server làm nhiệm vụ chạy và quản lý các container và bạn sử dụng client để nói với server nhiệm vụ nó phải làm. Docker daemon (chả biết dịch cái này dư lào) có thể chạy trên bất kỳ server nào và mỗi client có thể nói chuyện với bất kỳ số lượng server. Client điều khiển mọi giao tiếp, nhưng Docker server có thể giao tiếp trực tiếp với Image registries (chính là cái Docker Registry) khi hành động. Client có nghĩa vũ điều khiển trực tiếp server phải làm gì và server tập trung vào việc tổ chức đóng gói ứng dụng.
Docker có chút khác biệt trong cấu trúc so với các phần mềm client/server khác. Thay vì có clietn và server thực thi riêng biệt, nó lại sử dụng cùng dạng nhị phân cho cả 2 thành phần (ý là việc thực thi). Khi cài docker, ta có 2 thành phần trên, nhưng server chỉ chạy trên host linux. Chạy Docker server/daemon là đơn giản như chạy docker với config -d (config này ở đây tác giả muốn nói là chạy ngầm vậy). Mỗi docker host thường có 1 Docker daemon chạy và có thể quản lý số lượng container. Bạn có thể sử dụng docker command-line tool client để giao tiếp với server.

2. Network Ports and Unix Sockets.
Docker command-line tool và docker -d daemon giao tiếp qua net-work sockets. Bạn có thể chọn để cho Docker daemon nghe trên 1 hoặc nhiều cổng TCP hoặc Unix socket.
Daemon là 1 tiến trình chạy nền tức là thay vì hiển thị lên cho bạn thấy mọi request đến đi, tên server các kiểu thì nó âm thầm chạy ở phía sau
3. Container Networking.

Docker and Images

Nếu bạn đã quen với hướng đối tượng, chúng ta có thể hiểu images như những class còn cointaner là những object. Tương tự như việc các object được khởi tạo từ những class, container cũng được khởi tạo từ image. Bạn có thể tạo ra nhiều container từ 1 image, và chúng đều bị cô lập như cách các object khởi tạo. Bất kỳ thay đổi nào trên object, nó sẽ không ảnh hưởng đến định nghĩa và function của class.
Mặc dù Docker containers là lớn và có nhiều tiến trình chạy trên chính nó, tuy nhiên nó có chút khác biệt trên các tiến trình trong 1 tầng mạng. Mỗi Docker container như chạy trên 1 mạng giống như được host ở trên 1 private network. Docker server thực hiện như 1 cầu nối ảo, và các container là clients ở sau nó. Cây cầu này chỉ là 1 thiết bị mạng mà lặp lại giao tiếp từ 1 đến số còn lại. Nó có thể coi như 1 mạng ảo nhỏ với các host được đính kèm.
Điều này có nghĩa là mỗi container có 1 giao diện mạng kết nối tới Docker của riêng nó và IP address của chính nó được kết nối tới 1 giao diện ảo. Docker cho phép bạn đặt cổng trên host tới container do đó bên ngoài có thể kết nối tới container của bạn. Các giao tiếp được chạy qua 1 proxy cái mà là 1 phần của Docker daemon trước khi đến với container.
Docker kết nối các private subnet từ 1 chuẩn kết nối RFC 1918 (chả hiểu đây là cái gì nhưng cứ dịch vào, anhem click vào link xem sao). Nó phát hiện network nào là khoogn được sử dụng khi khởi tạo và kết nối nó với mạng ảo. Nó kết nối tới máy chủ mạng cục bộ qua các giao diện trên server ( được gọi là docker0). Có nghĩa là tất cả các container là chung 1 mạng và có thể nói chuyện trực tiếp với nhau. Nhưng để lấy host ở bên ngoài (ngoài docker), chúng ta đi qua giao diện mạng ảo docker0. Nó không giới hạn giao tiếp qua proxy. Proxy này có hiệu năng cao như có thể bị limit nếu chạy quá nhiều ứng dụng trên 1 container.
Có 1 ti tỉ cách mà chúng ta có thể config tầng mạng của docker, từ kết nối mạng của chúng ta tới config giao diện kết nối. Chúng ta cũng có thể chạy với mặc đinh trừ trường hơi quá phức tạp hoặc cần chạy riêng cho ứng dụng. Bạn có thể tìm thấy chi tiết về mạng Docker trong Documentation của Docker.
Trong số rất nhiều thứ dẫn dắt cho Docker phát triển là các công cụ hỗ trợ đơn giản mà đầy sức mạnh. Nó đã phát triển rộng hơn bởi về nó bắt đầu được release bởi docker và bởi cộng đồng docker. Công cụ mà Docker kèm theo và hỗ trợ cả xây dựng Docker Images và khả năng deploy 1 cách đơn giản đến Docker daemons, cũng như có đầy đủ chức năng cần thiết để quản lý từ xa Docker server. Cộng đồng chú ý về quản lý tất cả các cụm Docker server và tổ chức cho việc deploy các container. Docker cũng xây nên các tool của chính mình bao gồm: Docker Compose, Docker Machine và Docker Swarm. Điều này làm tăng khả năng gắn kết việc deploy trong nhiều môi trường bởi vì Docker cung cấp cả command-line tool và web API nên nó rất dễ để thêm tool với nhiều ngôn ngữ.
Docker Command-line Tool là giao diện chính mà phần lớn người dùng sử dụng. Nó sử dụng ngôn ngữ Golang để thực thi và chạy chung kiến trúc và hệ thống. Command-line tool được dùng cho mọi nền tảng và được thực thi trực tiếp từ source Go. 1 vài thứ chúng ta có thể thực hiện với Docker command-line tool:
- Tạo ra container, image.
- Kéo image từ kho lưu trữ của Docker daemon và đẩy image lên ngược lại.
- Khởi tạo 1 container ở trên Docker server trên nền hoặc dưới nền hệ thống.
- Xem được Docker logs từ server.
- Khởi tạo 1 command-line shell trong các container trên server.
Docker được sinh ra để build, ship, và run phần mềm ở bất kỳ đâu có cài docker. Với end user (tức là chúng ta), Docker là 1 command-line program mà chúng ta có thể chạy nó. Giống git, chương trình này có những subcommands thực hiện các biểu thức khác nhau. Các subcommand chính của Docker bao gồm:
Command | Tác dụng |
---|
docker build | Khởi chạy 1 docker image. |
docker run | Chạy 1 docker image như 1 container |
docker commit | Commit 1 docker container như 1 image |
docker tag | Tag 1 docker image |
6. Cách thức làm việc với Docker qua ví dụ cơ bản
Khi đó một container tương ứng với image sẽ được tạo ra. imageName ở đây chính là tên của image trong cột Repository mà mình nhắc tới trong phần khái niệm image
Bạn muốn export cổng 3306 trong container ra máy local là 3307
Mã:$ docker run --port 3307:3306 image
Bạn muốn đặt tên cho container của mình khi nó đượct tạo ra
Mã:$docker run --name containerName image
Bạn muốn mount giữa folder làm việc bên ngoài với thằng trong container tương ứng
$docker run --volume pathOnMyComputer:intheContainer image
Bây giờ bạn muốn nhiều tùy chọn vừa đặt tên, export cổng, vừa mount thư mục thì gộp các lênh bên trên lại
$ docker run --port 3307:3306 --name MySql .... mysql
Giả sử image name của mình là mysql chẳng hạn
Khi đó $ docker ps sẽ cho mình thấy thằng container nào đã được tạo ra và đang chạy
Start/stop một cách đơn giản thông qua
Mã: $ docker start/stop containerId
Khi show ra container mình sẽ biết được Id của từng thằng tương ứng.
Demo
Cài đặt docker: install docker
Pull image tutum/apache-php về bằng cách chạy
Mã: docker pull tutum/apache-php
Pull image mysql
Phiên bản của mysql và apache-php và mysql có thể tùy chọn được, bạn chỉ cần làm theo hướng dẫn trên 2 link mình đưa bên trên
Ok giờ bạn kiểm tra 2 images trên của mình đã được pull về hay chưa
- Bây giờ bạn có một folder như thế này ~/dokder-project/lara-new. Đây là một project laravel mà mình mới create. Thông thường mình sẽ để nó trong /var/www/html/lara-new để rồi chạy nó đúng không (Giả sử đường dẫn làm việc của apache trên máy mình vẫn để là mặc định).
- Bây giờ muốn chạy nó với docker mình làm như thế nào?
- Tương tự như khi bạn làm trực tiếp trên máy chủ của bạn thì trong container bạn cần vứt thằng lara-new này vào trong đường dẫn làm việc của apache trong container. Mình cần tưởng tượng là mọi thứ đang được chạy bên trong container
Mount folder trên máy chủ vào trong thư mục làm việc của apache trong containter
Mã:$ docker run -tid -p 9000:80 -v ~/www/sites:/var/www/html tutum/apache-php
Ở đây trong www/sites chứa các folder project web của mình. Đây cũng chính là thư mục làm việc của apache mà mình đã đổi từ mặc định /var/www/html sang
- Mở trình duyệt chạy localhost:9000 vì nãy mình export cổng 80 mà mặc định apache sử dụng trong container ra cổng 9000 bên ngoài và xem kết quả

- Ok mọi thứ ổn, giờ mình sẽ mở trình duyệt và chạy thử project của mình

- Giờ không muốn sử dụng server nữa(?)
Note : Lần sau sử dụng thì mình lại: docker start containerId
- Bây giờ muốn config file apache config trong site-enable chẳng hạn để tạo virtual host cho đường dẫn đẹp đẹp chẳng hạn thì làm như thế nào?
Mã:docker exec -it containerName bash
Note: containerName mình dùng docker ps để xem
- Nếu bạn muốn tự làm mọi việc từ đầu bạn có thể tìm hiểu kỹ hơn với từ khóa dockerfile, tìm hiểu cú pháp trong dockerfile để build một image của riêng mình và chia sẻ cho người khác. Theo mình hiểu đơn giản thì dockerfiles khai báo một loạt những câu lệnh có thứ tự và được chạy khi bạn bắt đầu build một image
Ví dụ một Dockerfile đơn giản của mình như sau
FROM busybox ENTRYPOINT sudo apt-get udate && sudo apt-get install -y apache2 && tail /var/log/apache2/error.log
ENTRYPOINT service apache2 restart
EXPOSE 80
Đó là ví dụ đơn giản bạn build một image với cài đặt của bản apache và Expose cổng 80.
Chú ý
- Folder project của bạn nên để quền user, tránh để quyền root vì khi mount folder của mình sẽ bị chuyển sang quyền www-data do apache bên trong container change, dẫn tới lỗi
- Nếu bạn làm việc với Laravel hay các phiên bản famework nào đó thì có thể lên docker hub để tìm được những image có chứa phiên bản php hay apache mới nhất
Tài liệu tham khảo