Triển khai môi trường web bằng Docker

trong danh mục Technology

docker introduction

Số là dạo này làm việc và nghiên cứu nhiều về kiến trúc Microservice và đang chuyển toàn bộ kiến trúc sang Microservice. Trong quá trình này, Docker là một công nghệ không thể nào bỏ qua vì Docker sẽ giúp ích rất nhiều trong quá trình triển khai và quản lý các service. Trong phạm vi bài viết này mình sẽ không đi sâu vào chi tiết kiến trúc Microservice cũng như mô tả kỹ về hoạt động của Docker mà sẽ tập trung vào giới thiệu sơ về Docker và dựng một môi trường thực tế dùng Docker để triển khai Web Server cho một website.

Docker là gì

Nếu bạn là một công dân của ngành lập trình, mạng thì chắc hẳn bạn đã nghe nói đến Docker và một số công ty lớn trên thế giới đã bắt đầu ứng dụng Docker vào hệ thống của họ. Vậy Docker là gì? Nói một cách đơn giản và dễ hiểu (vì thực ra đối với những người chưa biết thì Docker khó hiểu lắm ^^!) thì nó là cái phần mềm chạy trên Linux. Do đó, các hướng dẫn hầu như là thực hiện các câu lệnh command line như “docker run…”, “docker ps”, “docker images”,…

Nhiệm vụ của Docker là sẽ giúp xây dựng được một cơ chế ảo hóa, như dạng chạy mấy cái mấy ảo (Vmware) mà các bạn đã từng quen biết. Mục đích là tạo ra một môi trường riêng biệt (hệ điều hành, phần mềm…) để dễ quản lý, bảo trì, di chuyển các phần mềm, code đã được đóng gói. Một cách dễ hiểu hơn là câu lệnh “docker run …” sẽ giúp chạy một cái “máy ảo” từ một file nén (chứa hệ điều hành, phần mềm, code…) nào đó đã được tạo sẵn.

Các file nén này gọi là các “image“. Bạn có thể sử dụng các image có sẵn như ubuntu, php, mysql, wordpress… hoặc tự tùy chỉnh để tạo ra các image riêng cho nhu cầu của mình. Có thể tạo image thông qua câu lệnh “docker build…”. Các image có thể chứa ở những store thông dụng như Docker Hub (https://hub.docker.com/) hoặc bạn có thể tự dựng một nơi lưu trữ các image riêng vì nhu cầu bảo mật của doanh nghiệp. Nơi lưu trữ này gọi là “docker registry” và bạn có thể tham khảo các bài viết trên mạng để dựng cho mình một registry (https://docs.docker.com/registry/).

Ứng dụng Docker

Với cơ chế image và các cơ chế khác kèm theo giúp cho việc đóng gói và triển khai các phần mềm đơn giản và nhanh chóng hơn. Trong phạm vi nội dung này, mình sẽ chia sẻ với các bạn cách dựng một môi trường web có sử dụng database (MySQL). Nội dung cài đặt được thực hiện trên một máy (1 host) và trên môi trường Ubuntu 14 (điều này không quan trọng lắm). Bạn có thể tham khảo website Docker để biết cách cài đặt và cấu hình Docker trên máy của bạn. Việc cài đặt Docker không thuộc phạm vi bài viết này (có thể tham khảo tại docker.com) và mặc định mọi người đã cài đặt thành công Docker.

Đối tượng của phần này là các bạn đã quen biết với môi trường web hiện tại, không dành cho Newbie. Bạn đã biết một website (Apache, PHP, MySQL) hoạt động thế nào và các thành phần của LAMP stack đã hoạt động và kết nối với nhau ra sao. Nếu bạn chưa biết những điều này thì các nội dung bên dưới sẽ không “dễ tiêu hóa”.

MySQL trên Docker

Hầu hết ứng dụng web đều có sử dụng database và mục này mình sẽ cài đặt MySQL. MySQL có image chính thức và mình chọn image “mysql” và tag phiên bản “latest” để bắt đầu.

Cài đặt MySQL Image

Chỉ cần chạy câu lệnh sau là bạn đã có 1 MySQL Server:
~ > docker run -it -d --name mysql01 -v /data/mysql/mysql01:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:latest
Hướng dẫn các tham số:
– “docker run“: câu lệnh để chạy 1 image và bắt đầu 1 container. Container là một process sử dụng 1 image là nội dung bên trong.
– “-it“: tham số để cho phép thao tác về sau như can thiệp vào container để thực thi các câu lệnh hệ thống.
– “-d“: tham số để nói sau khi thực hiện câu lệnh trên thì cho nó chạy background và con trỏ vẫn ở host hiện tại.
– “–name mysql01“: đặt tên cho cái container này. Bởi vì bạn có thể tạo nhiều container từ chung 1 image (đây chính là điểm ưu việt của Docker), mỗi container cần có cái tên để dễ làm việc, không thì docker sẽ tự tạo 1 cái tên ngẫu nhiên. Tốt nhất là nên đặt một cái tên cho dễ nhớ. Và lưu ý, không được phép có 2 container cùng 1 tên.
– “-v /data/mysql/mysql01:/var/lib/mysql“: cho phép mount volume (link thư mục) từ bên trong container ra một thư mục bên ngoài máy đang chạy. Thử tưởng tượng, nếu bạn không sử dụng volume để mapping thư mục, khi container này stop và bị xóa (bạn xóa) thì toàn bộ dữ liệu trong container cũng bị mất. Do đó, phải mapping ra thư mục bên ngoài để khi container bị xóa thì dữ liệu vẫn còn. Và khi start 1 container mới thì sẽ có dữ liệu trước đó. tham số “-v” là một tham số rất quan trọng và bạn cần tìm hiểu nhiều hơn về nó. Trong ví dụ này thì thư mục “/data/mysql/mysql01” là thư mục trên máy của mình và “/var/lib/mysql” là chuỗi cố định được cài đặt sẵn trong image.
– “-e MYSQL_ROOT_PASSWORD=123456“: Tham số “-e” sẽ set một biến môi trường. Ở đây, set biến môi trường làm password root cho mysql server. Thường mỗi image đều có ghi chú về các biến môi trường và công dụng của nó khi chạy một image. Bạn có thể xem thêm các biến môi trường khác của image “mysql” tại https://hub.docker.com/_/mysql/.
– “mysql:latest“: tên image và tag phiên bản của image sẽ chạy.

Sau khi thực hiện câu lệnh trên, nếu docker đã được cài đặt ngon lành thì sẽ có 1 container với tên “mysql01” được tạo. Bạn có thể chạy câu lệnh “docker ps” để xem container với tên mysql01 đã chạy chưa. Nếu không có thì bạn có thể kiểm tra xem có sai sót gì không nhé.

Truy cập vào MySQL container

Sau khi container mysql01 đã được chạy và đang chạy (thấy được từ “docker ps”), bạn có thể truy cập vào mysql command line để thực hiện các câu lệnh SQL bạn muốn như setup user, tạo, xóa db…thông qua câu lệnh sau:
~ > docker exec -it mysql01 mysql -uroot -p

Bạn nhập password ở trên (123456) để tiếp tục và thế là đã vào được command line của mysql. Việc còn lại là việc của bạn.

Import file .sql vào MySQL container

Trong phần lớn trường hợp, sau khi đã có MySQL Server, bạn thường muốn import từ file .sql. Bạn có thể chạy câu lệnh sau để import file sql.

~ > docker exec -i mysql01 mysql -uroot -p123456 --default-character-set=utf8 DATABASENAME < /data/database.sql

Câu lệnh trên sẽ chạy các câu truy vấn trong file database.sql vào database DATABASENAME.

Web Server trên Docker

Triển khai web server có phần đơn giản hơn. Bạn cần chuẩn bị source code của mình vào một thư mục và có config đầy đủ đến MySQL ở trên. Lưu ý là bạn sẽ không sử dụng ip 127.0.0.1 hoặc localhost để kết nối đến MySQL server mà dùng IP của container. Để biết IP của một container, bạn có thể sử dụng câu lệnh “docker inspect mysql01” để xem các thông tin của container, trong đó có field IP Address của container, ví dụ: “IPAddress”: “172.17.0.1”. IP này chính là IP của “mysql01” container.

Sau khi đã có source code của dự án (giả sử bạn đặt source code tại thư mục /data/apitoy.com/) và chỉnh các config của mysql connection (IP, Account..) thì tiến hành thực hiện câu lệnh sau:

~ > docker run -ti -d -p 8080:80 --name apitoyweb --link mysql01:mysql -v /data/apitoy.com:/var/www/site voduytuan/docker-apache-php:latest

Hướng dẫn các tham số:
– “-p 8080:80“: binding port từ máy host (8080) sang port của container (80). Mỗi web server container thường chạy trên port 80, nếu bạn muốn start nhiều container web server thì không thể nào cho tất cả container có port 80 ra ngoài. Cách thường thấy đối với web server trên môi trường docker là mapping từ 1 port nào đó sang port 80 của web server container ví dụ 8080, 8081, 8082…
– “–link mysql01:mysql“: tham số quan trọng để link container này với mysql container trước đó. Nhờ cơ chế link của docker thì web server container mới kết nối đến mysql container như là local, tức là kết nối đến port 3306 bình thường và mysql01 không cần config cho kết nối external.
– “-v /data/apitoy.com:/var/www/site“: binding volume source code vào thư mục /var/www/site đã được cấu hình là web root của web server container.
– “voduytuan/docker-apache-php:latest“: là một public image mà mình đã tạo riêng cho các web server production của mình. Cài sẵn php, apache, extension memcached, redis và một số config php khác…Bạn có thể tìm hiểu thêm về image này tại https://hub.docker.com/r/voduytuan/docker-apache-php/.

Sau khi chạy câu lệnh trên, nếu bạn chạy “docker ps” sẽ thấy có 2 container đang chạy, một tên là “mysql01” đã chạy trước đó và một là “apitoyweb” vừa được tạo. Để thử nghiệm xem web server đã chạy chưa thì bạn truy cập vào IP của máy và port 8080 để xem có load được nội dung của website không.

Haproxy

Như vậy, bạn đã dựng xong môi trường web server và mysql thông qua Docker container. Còn một vấn đề cuối cùng là bạn không thể nào bắt người dùng gõ port 8080, 8081..trên trình duyệt. Bạn cần một công cụ giúp điều hướng vào đúng container. Haproxy là một phần mềm chia tải đơn giản trên linux và mình sẽ hướng dẫn mọi người cấu hình haproxy để chia tải vào container vừa chạy.

Mình sẽ không cài Haproxy từ Docker mà muốn nó chạy trực tiếp trên Host nên chỉ cần cài haproxy bình thường. Tạo file config như sau để điều hướng tên miền (vd: apitoy.com) vào đúng container có tên “apitoyweb” đang chạy trên port 8080.

global
  # daemon
  maxconn 256

defaults
  mode http
  timeout connect 5000ms
  timeout client 50000ms
  timeout server 50000ms

frontend http-in
  bind *:80
  default_backend farm_apitoy

  acl host_apitoy hdr(host) -i apitoy.com

  use_backend farm_apitoy if host_apitoy

backend farm_apitoy
  mode http
  balance roundrobin
  option forwardfor
  server web01 127.0.0.1:8080

Sau đó, bạn có thể start haproxy dùng file config bằng nhiều cách như copy đè vào file config của haproxy hoặc chạy trực tiếp câu lệnh:
~ > haproxy -D -f haproxy.cfg
Hướng dẫn tham số:
– “-D“: chạy ở chế độ background
– “-f haproxy.cfg“: sử dụng file config haproxy.cfg

Sau khi Haproxy đã chạy và hệ thống đã tự động điều hướng port 80 http và nếu tên miền là apitoy.com sẽ tự động dẫn vào container “apitoyweb”. Bạn có thể cấu hình haproxy để điều hướng đến nhiều container cùng chạy web apitoy hoặc dựa vào domain khác để dẫn đến các container của các website khác trong hệ thống container đang chạy của bạn.

—-
Như vậy, mình đã hướng dẫn các bạn setup xong hệ thống web sử dụng Haproxy, Web Server Apache, PHP và MySQL trên môi trường Docker. Hy vọng sau bài viết này thì sẽ có nhiều bạn hiểu hơn về cách sử dụng Docker và đóng góp nhiều hơn cho cộng đồng non trẻ này.

Nên nhớ, luôn có nhiều cách khác nhau để triển khai một hệ thống web dùng Docker, cách mình nêu ra đây chỉ là cách đơn giản nhất mà mình chia sẻ đến với những bạn chưa có nhiều kiến thức về deploy, build để có thể tiếp cận được với công nghệ Docker.

Trong các bài tới, mình sẽ chia sẻ về cách ứng dụng Docker trong các mô hình microservice mà mình đang theo đuổi.

2 bình luận

  1. Trình Phú Sơn says:

    Anh ơi hướng dẫn em cấu hình haproxy để điều hướng đến nhiều container cùng chạy web apitoy hoặc dựa vào domain khác để dẫn đến các container của các website khác được không ạ? Ví dụ em có 2 domain: apitoyweb.com(port 8080) và epitoyweb.com (port 8081), em muốn khi gõ vào browser domain nào thì vào đúng container chứa website đó, em thử rồi vẫn chưa làm được ạ.

  2. Dũng says:

    Mình thường dùng Docker để team có thể dùng chung 1 môi trường, triển khai nhanh.
    Mình đang phân vân các công ty vừa và lớn có đang chạy các website của họ trực tiếp trên docker hay là chạy trên Nginx , apache như thường nhỉ?

Gởi bình luận