Docker đối với lập trình viên Web
Chào mọi người! Hôm nay sẽ tiếp tục loạt bài " Mình biết thì mình chia sẻ " của mình mong tiếp tục nhận được sự ủng hộ từ anh em (hehe) Mục đích chính của bài viết này là chúng ta sẽ có được cái nhìn tổng quan về Docker và làm sao chạy một ứng dụng web với PHP Mysql mà không cần cài Apache, ...
Chào mọi người!
Hôm nay sẽ tiếp tục loạt bài "Mình biết thì mình chia sẻ" của mình mong tiếp tục nhận được sự ủng hộ từ anh em (hehe)
Mục đích chính của bài viết này là chúng ta sẽ có được cái nhìn tổng quan về Docker và làm sao chạy một ứng dụng web với PHP Mysql mà không cần cài Apache, Mysql trực tiếp vào máy thông qua việc chúng ta sẽ sử dụng những gì mình tìm hiểu được về Docker để làm việc đó.
Cái tên Docker có lẽ các bạn cũng như mình đã từng nghe tuy nhiên chưa làm việc với nó và cũng chưa tìm hiểu nhiều về nó nên mình nghĩ bài viết này của mình sẽ khá hữu ích đối với new new newbie Docker như mình
Tuần trước mình có có một project về web với ngôn ngữ PHP và sử dụng Mysql server. Do đó trên máy mình có cài Apache2, PHP7 và Mysql 5.7 và mình đang dùng trên hệ điều hàng Linux với phiên bản Ubuntu 16.04 LTS. Mình có một thằng bạn nó khuyên mình là dùng Docker đi không cần cài từng cái như vậy. Mình chỉ cần tìm các image cài đặt và làm theo các hướng dẫn của nó là có thể start server apache và mysql khi nào mình muốn và chạy ứng dụng web trên máy của mình.
Nghe lời nó mình đã thử tìm hiểu về Docker xem có gì hay và mình đã bắt đầu thực sự thích tên này
Mình mất khá ít thời gian để setup một môi trường đầy đủ cho việc chạy một ứng dụng web mà mình đang phát triển. Quả thật Docker theo các nhân mình đánh giá là khá tốt về khả năng vượt qua các vấn đề liên quan đến cài đặt ứng dụng trên Ubuntu, các việc cần thiết mà phải như đối với việc mình cài đặt từng phần như đã nói ở trên. Start khi muốn sử dụng và stop khi không cần đến, dễ dàng bảo trì thay đổi phiên bản, gỡ bỏ cài đặt dễ dàng
Thôi không lan man nữa chúng ta hãy cùng đi vào nội dung chính của bài chia sẻ này
Ok. Let's make it awesome =))
DOCKER là gì?
Là một công cụ tạo môi trường được "đóng gói" (còn gọi là Container) trên máy tính mà không làm tác động tới môi trường hiện tại của máy. Một số developer thường tạo sẵn các môi trường này, và upload lên mạng để mọi người lấy về dùng, và mấy cái này gọi là các Images
-
Nó giống như virtual machine, chỉ là tiện dụng hơn, dễ dàng sử dụng hơn và độc lập với hệ điều hành máy chủ chúng ta đang sử dụng
-
Cùng nhìn qua kiến trúc để thấy sự khác biệt:
Docker Container
- Khi sử dụng môi trường Vitualization thì chúng ta cần cài các hệ điều hành cùng các tool cần thiết để chạy một ứng dụng có sẵn, nhưng với docker việc đó trở nên đơn giản với việc mình tìm và sử dụng lại các images (tại đây các cài đặt cần thiết để cho việc khởi chạy là có sẵn). Sau đó đóng gói vào trong các Container và chạy thôi. Cài đặt và khởi chạy, các khái niệm mình sẽ trình bày bên dưới
Tại sao chúng ta nên sử dụng docker?
-
Immutability: Tính không thay đổi
- Một Immutablity image chứa mọi thứ để chạy một ứng dụng bao gồm cả source code của mình
-
Repeatability: Tính lặp lại, có thể tái sử dụng dễ dàng
-
Shared enviroment: Mình có thể chia sẻ cho bất cứ ai, bạn bè mà muốn chạy ứng dụng của mình, chỉ cần sử dụng các image có sẵn mà mình đang sử dụng vậy là chúng ta đã có một same enviroment.
- Ok giờ mấy đứa bạn mình đang phát triển web với Ruby, đơn giản nó muốn nhờ mình test hộ nó trên máy của mình mà ứng dụng chưa được đẩy lên host nghĩa là vẫn local. Tuy nhiên mình thì chưa bao giờ lập trình với Ruby nên các tool cần thiết để chạy ứng dụng của nó trên máy mình không có.
- Vậy chẳng lẽ chỉ cần test hay contribute một số thứ đơn giản cho nó mà lại phải cài một đống thứ vào máy à? Vấn đề đã được giải quyết với docker. Mình hỏi thằng bạn cần cài đặt những ứng dụng nào để chạy app của nó và các câu lệnh cần thực hiện trước khi start ứng dụng là gì. Sau đó lên google tìm các image cần thiết để chứa môi trường khởi chạy ứng dụng mình cần và chạy thôi.
-
Versioning: Về phiên bản của các ứng dụng cần thiết ví dụ như Apache, Mysql, mình có thể dễ dàng lựa chọn các phiên bản cần thiết vì hầu hết được cộng đồng lập trình viên docker update khá nhanh chóng.
- Việc chuyển đổi giữa các phiên bản dễ dàng. Bạn có các image với các version khác nhau của mysql chẳng hạn, sử dụng bất cứ version nào bạn muốn phù hợp với ứng dụng của mình
-
Automation: Tính tự động, khác dễ dàng đễ start server chỉ thông qua vài dòng lệnh trên terminal
-
Isolate: Tính độc lập.
- Mình không cài trực tiếp các ứng dụng server cần thiết cho app của mình lên máy một các locally mà các cài đặt cần thiết được build trong các gói (image)
Các khái niệm cần biết
Image
"Docker images are OS boxes that contain some pre-installed and configured software"
Hiểu đơn giản nó sẽ chứa các cài đặt sẵn để cho chúng ta sử dụng. Nó như cái hộp bọc lấy phần setup của mình
-
Ví dụ trên máy mình cài Apache2 thì mình sẽ chạy câu lệnh cần thiết để cài đặt nó, tuy nhiên nếu mình sử dụng docker mình chỉ cần lên mạng tìm lấy image nào chứa thằng Apache2 này mà dùng thôi, mọi gói và setup cần thiết đã được đặt trong image.
-
Để xem trên máy mình có những image nào mình dùng lệnh sau
-
$ docker images
Repository là tên của image mà mình pull về Tag: Là version tương ứng
-
Container
"Docker containers are separate instances that we create from images"
-
Qua hình các bạn rất dễ để hình dung ra container là gì rồi đúng không?
-
Nó chính là các instance của các image mà mình có. Chúng ta có các image về service cần thiết rồi, việc cần làm là run các thằng image đó vào trong các container và dùng thằng nào thì start thằng đó
-
Docker container còn được gọi là Linux Container (LXC).
-
Để xem trên máy có những container nào sử dụng
- $docker ps -a
-
Nếu muốn xem những container nào đang được start thì mình sẽ dùng
- $docker ps
Volume
Volume là cách dễ dàng để chia sẻ vùng nhớ giữa máy chủ của mình và container. Nó được tạo ra trong suốt quá trình container được chạy và luôn được đồng bộ
Ví dụ mình muốn mount /var/www/html trong container tới đường dẫn local trên máy chủ của mình ~/docker-project/lara-new
docker run -v <local dir>:<container dir>
Expose port
Cổng của ứng dụng
- Ví dụ mình dùng mysql container, bên ngoài mình cài mysql-workbench để làm việc, mặc định bên trong container sẽ setup cổng đối với mysql là 3306 đúng không, nhưng nếu mà bên ngoài máy local của mình đã sử dụng port 3306 cho mục đích nào đó => Conflict. Và mình sẽ không thể dùng workbench tạo connection tới port 3306 được.
- Làm việc với docker mình có thể export cổng bên trong container ra cổng bên ngoài tương ứng. Ví dụ trong conatainer port 3306 của mysql thì mình sẽ export nó ra bên ngoài là 3307 chẳng hạn => Vấn đề được giải quyết
Một số lệnh cơ bản làm việc với docker
-
Bạn có image Mysql, bạn muốn start server mysql để làm việc với cơ sở dữ liệu, chỉ cần chạy
$ docker run image
-
Khi đó một container tương ứng với image sẽ được tạo ra. image ở đâ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
-
Mình muốn export cổng 3306 trong container ra máy local là 3307
$$docker run --port 3307:3306 image
-
Mình muốn đặt tên cho container của mình khi nó đượct tạo ra
$$ocker run --name containerName image
-
Mình muốn mount giữa folder làm việc bên ngoài với thằng trong container tương ứng
$$ocker run --volume pathOnMyComputer:intheContainer image
-
Đó bây giờ mình 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
$ 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
docker pull tutum/apache-php
-
Pull image mysql
docker pull 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
docker images
- Ok mình 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
- Bây giờ muốn chạy nó với docker mình làm như thế nào?
-
Mount folder trên máy chủ vào trong thư mục làm việc của apache trong containter
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
-
Giờ sử kiểm tra xem container đã được create và đang chạy chưa
docker ps
- 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à 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(?)
- docker stop containerId
- Lần sau sử dụng thì mình lại docker start contianerId
- 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ình cần chạy vào bên trong container và làm các thao tác tương tự như khi mình đang làm trên máy local mà bình thường mình vẫn làm thôi
-
Để vào container chạy
docker exec -it containerName bash
-
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.
-
Cùng tìm hiểu về dockerfiles sau nhé mình thấy nó cũng khá hay. Tạm thời ăn nhanh mình cứ dụng image có sẵn đã (haha)
-
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