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 emMì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
Rất xin lỗi vì sau bài viết trước Docker với lập trình viên web của mình thì mình lại ngắt quãng không thể đi luôn vào phần tìm hiểu tiếp tục kết nối với cơ sở dữ liệu. Hôm nay chúng ta sẽ cùng đi giải quyết vấn đề đó.
Bài toán
Mình có một project php tên là selfproject xây dựng dựa trên laravel framework. Project này làm việc với hệ quản trị CSDL là MySql.
Vấn đề là bây giờ mình muốn chạy nó với docker! `docker! `
Giải quyết
Cách 1
Theo như bài tìm hiểu lần trước mình sẽ sử dụng các images đã được chia sẻ bởi các lập trình viên khác trên dockerhub.
Mình sẽ sử dụng 2 images đó là tutum/apache-php cho service apache-php và mysql cho mysql server.
Đầu tiên mình cần tạo MySQL container trước
docker run -p 3307:3306 --name mysqlserver -e MYSQL_ROOT_PASSWORD=root -d mysql
Sau đó tạo web server container
docker run -tid -p 9000:80 -v ~/www/sites/FrProject/Github/selfproject:/var/www/html --name selfproject-server --link mysqlserver:mysql tutum/apache-php
Ở đây mình cần mở rộng hơn trong bài tìm hiểu lần trước, đó là mình có 2 container là
5 vàdocker run -tid -p 9000:80 -v ~/www/sites/FrProject/Github/selfproject:/var/www/html --name selfproject-server --link mysqlserver:mysql tutum/apache-php
6, để chúng có thể giao tiếp với nhau cần link web server với mysql thông qua tùy chọndocker run -tid -p 9000:80 -v ~/www/sites/FrProject/Github/selfproject:/var/www/html --name selfproject-server --link mysqlserver:mysql tutum/apache-php
7docker run -tid -p 9000:80 -v ~/www/sites/FrProject/Github/selfproject:/var/www/html --name selfproject-server --link mysqlserver:mysql tutum/apache-php
Bây giờ mở trình duyệt và thử kết quả
Lý do?
Mình quên config lại trong file .env
DB_CONNECTION=mysql
# host bên ngoài local
# DB_HOST=127.0.0.1
# Sửa trong container nên sẽ config lại
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=selfproject
DB_USERNAME=root
DB_PASSWORD=root
- Kết nối tới database trong container tạo db có tên
8. Ở command tạo MYSQL container mình cần expose port ra bên ngoài container là 3307. Do ở máy mình cổng 3306 đã được sử dụng cho ứng dụng khác.docker run -tid -p 9000:80 -v ~/www/sites/FrProject/Github/selfproject:/var/www/html --name selfproject-server --link mysqlserver:mysql tutum/apache-php
Ở đây mình sử dụng công cụ trực quan mysql-workbench để thao tác với mysql, các bạn có thể dụng công cụ khác như php-myadmin...
Giờ vào vào trong container để
9 dữ liệudocker run -tid -p 9000:80 -v ~/www/sites/FrProject/Github/selfproject:/var/www/html --name selfproject-server --link mysqlserver:mysql tutum/apache-php
docker exec -it containerName/containerId bash # Với mình docker exec -it selfproject-server bash
Và giờ là kết quả
- Nhưng khi muốn vào đăng ký mình gặp phải
Vấn đề: không thể truy cập được url nào khác ngoài public. Khắc phục: trong container mình cần sửa lại file apache.conf đoạn
0 thànhDB_CONNECTION=mysql # host bên ngoài local # DB_HOST=127.0.0.1 # Sửa trong container nên sẽ config lại DB_HOST=mysql DB_PORT=3306 DB_DATABASE=selfproject DB_USERNAME=root DB_PASSWORD=root
1 trongDB_CONNECTION=mysql # host bên ngoài local # DB_HOST=127.0.0.1 # Sửa trong container nên sẽ config lại DB_HOST=mysql DB_PORT=3306 DB_DATABASE=selfproject DB_USERNAME=root DB_PASSWORD=root
2DB_CONNECTION=mysql # host bên ngoài local # DB_HOST=127.0.0.1 # Sửa trong container nên sẽ config lại DB_HOST=mysql DB_PORT=3306 DB_DATABASE=selfproject DB_USERNAME=root DB_PASSWORD=root
- Vào trong container
docker exec -it containerName/caintainerId bash
- Sử dụng vim để sửa lại file apache.conf [Do container mình đang dùng không có nano =]] ]
vi /etc/apache2/apache2.conf
**Sửa như sau**
Options Indexes FollowSymLinks
AllowOverride ALL
Require all granted
- Save lại và restart service apache bên trong container.
service apache2 restart
- Lúc này thì web server container này của mình sẽ bị terminate [ngắt kết nối] và mình cần start nó lại
Bên ngoài máy chủ của mình
docker start containerName/containerId
Với mình
docker start selfproject-server
Kết quả thu được
Ngon chạy rồi [hehe]. Thử tương tác với db coi sao. Mình thử tạo một bài post và đây là kết quả
Các bạn thử stop cả mysqlserver với web server đi rối start lại xem còn chạy và dữ liệu ok không nhé. Với mình thì tuyệt vời!
DB_CONNECTION=mysql
# host bên ngoài local
# DB_HOST=127.0.0.1
# Sửa trong container nên sẽ config lại
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=selfproject
DB_USERNAME=root
DB_PASSWORD=root
3
DB_CONNECTION=mysql
# host bên ngoài local
# DB_HOST=127.0.0.1
# Sửa trong container nên sẽ config lại
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=selfproject
DB_USERNAME=root
DB_PASSWORD=root
Vậy dữ liệu hắn lưu ở đâu?
Vào trong mysql container nhé và trong /var/lib/mysql/
Nên cẩn thận khi xóa container này nhé. Mình có thể khắc phục được vấn đề này là cũng
4 /var/lib/mysql trong container ra một folder nào đó ngoài máy chủ của mình chẳng hạn "mysql-data" do mình tự tạo giống như mình mount folder project [nhớ nên để folder quyền user nhé, tránh để root] làm việc vào trong /var/www/html khi create web server container vậy!khắc phục được vấn đề này là cũngDB_CONNECTION=mysql # host bên ngoài local # DB_HOST=127.0.0.1 # Sửa trong container nên sẽ config lại DB_HOST=mysql DB_PORT=3306 DB_DATABASE=selfproject DB_USERNAME=root DB_PASSWORD=root
4 /var/lib/mysql trong container ra một folder nào đó ngoài máy chủ của mình chẳng hạn "mysql-data" do mình tự tạo giống như mình mount folder project [nhớ nên để folder quyền user nhé, tránh để root] làm việc vào trong /var/www/html khi create web server container vậy!DB_CONNECTION=mysql # host bên ngoài local # DB_HOST=127.0.0.1 # Sửa trong container nên sẽ config lại DB_HOST=mysql DB_PORT=3306 DB_DATABASE=selfproject DB_USERNAME=root DB_PASSWORD=root
Stop tất cả các container đang chạy
0docker run -tid -p 9000:80 -v ~/www/sites/FrProject/Github/selfproject:/var/www/html --name selfproject-server --link mysqlserver:mysql tutum/apache-php
Khi mình chỉnh sửa, làm việc với project thì sẽ gặp phải vấn đề permission do khi
4 vào trong container thì nó sửa toàn bộ dữ liệu trong folder của mình về owner và group là www-data, chứ không còn là current user của mình hoặc root nữa. Vậy nên mình vào trong container và cấp quyền ghi cho project của mình với user là guest.container thì nó sửa toàn bộ dữ liệu trong folder của mình về owner và group là www-data, chứ không còn là current user của mình hoặc root nữa. Vậy nên mình vào trong container và cấp quyền ghi cho project của mình với user là guest.DB_CONNECTION=mysql # host bên ngoài local # DB_HOST=127.0.0.1 # Sửa trong container nên sẽ config lại DB_HOST=mysql DB_PORT=3306 DB_DATABASE=selfproject DB_USERNAME=root DB_PASSWORD=root
1docker run -tid -p 9000:80 -v ~/www/sites/FrProject/Github/selfproject:/var/www/html --name selfproject-server --link mysqlserver:mysql tutum/apache-php
Với laravel 5.3 mình không thể chạy
6 trong container mặc dù bên ngoài vẫn okDB_CONNECTION=mysql # host bên ngoài local # DB_HOST=127.0.0.1 # Sửa trong container nên sẽ config lại DB_HOST=mysql DB_PORT=3306 DB_DATABASE=selfproject DB_USERNAME=root DB_PASSWORD=root
- Lý do: laravel 5.3 yêu cầu version của php > 5.6 trong khi image mình đang dùng là tutum/apache-php với version php 5.5.9. Khá đau đầu với ông này mình mới nhìn ra được =]]tutum/apache-php với version php 5.5.9. Khá đau đầu với ông này mình mới nhìn ra được =]]
- Khắc phục: Tự build image hoặc sử dụng image khác có sẵn mà phiên bản > 5.6. Với mình chọn sử dụng image được chia sẻ bởi cộng đồng docker-hub. Thay vì dùng tutum/apache-php thì dùng webdevops/php-apache [Ông này cũng có vấn đề với bản laravel 5.4 nên nếu có lỗi bạn có thể thử với nimmis/apache-php7 hoặc bất cứ ông nào mà bạn tìm thấy trên docker hub và cảm thấy phù hợp với project của mình]tutum/apache-php thì dùng webdevops/php-apache [Ông này cũng có vấn đề với bản laravel 5.4 nên nếu có lỗi bạn có thể thử với nimmis/apache-php7 hoặc bất cứ ông nào mà bạn tìm thấy trên docker hub và cảm thấy phù hợp với project của mình]
Cách 2
DB_CONNECTION=mysql
# host bên ngoài local
# DB_HOST=127.0.0.1
# Sửa trong container nên sẽ config lại
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=selfproject
DB_USERNAME=root
DB_PASSWORD=root
7 với Docker compose
DB_CONNECTION=mysql
# host bên ngoài local
# DB_HOST=127.0.0.1
# Sửa trong container nên sẽ config lại
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=selfproject
DB_USERNAME=root
DB_PASSWORD=root
Chẳng lẽ mỗi lần code lại start từng con server một, nếu có 3 hay nhiều hơn nữa thì mệt quá, phải nhớ container name vì id là bất khả thi rồi =]]. Rồi lại cần nhớ thứ tự start nữa.
- Như việc link Mysql với Apache thì cần start server MySql trước sau đó start Apache container
Điều đó dẫn đến việc mình bắt đầu thử sử dụng Docker composeDocker compose
What is Docker composer
Docker compose là một công cụ cho việc định nghĩa và khởi chạy nhiều container với docker. Với compose mình sẽ khai báo nhiều container trong cùng một file và chỉ việc chạy một dòng lệnh là nó sẽ làm mọi việc start container cho mình. là một công cụ cho việc định nghĩa và khởi chạy nhiều container với docker. Với compose mình sẽ khai báo nhiều container trong cùng một file và chỉ việc chạy một dòng lệnh là nó sẽ làm mọi việc start container cho mình.
Bạn có thể tham khảo tại đây
Sử dụng docker compose cho ứng dụng của mình
Cài đặt docker-compose thì các bạn cài đặt theo hướng dẫn tại trang chủ docker nhé.
Tạo docker compose file với tên
8DB_CONNECTION=mysql # host bên ngoài local # DB_HOST=127.0.0.1 # Sửa trong container nên sẽ config lại DB_HOST=mysql DB_PORT=3306 DB_DATABASE=selfproject DB_USERNAME=root DB_PASSWORD=root
Khai báo mysql server và web server trong compose file này
2docker run -tid -p 9000:80 -v ~/www/sites/FrProject/Github/selfproject:/var/www/html --name selfproject-server --link mysqlserver:mysql tutum/apache-php
Về các options trong compose file mình sẽ không nói nhiều vì nó được mô tả khá chi tiết tại Composefile reference trên trang chủ của docker
Giải thích chút về nội dung file compose của mình
- Trước tiên là về version sử dụng đối với docker file là version '2'. Bạn có thể tìm hiểu thêm trên trang chủ docker. Version '1' là 'legacy format', version hiện tại là '2.1' và '2' là version được khuyến khích sử dụng có một số thay đổi về options so với version '1'.
- Với service mysql:
- image sử dụng là mysql
- ports ở đây như mình đã nói với phần sử dụng command. 3306 là port được sử dụng bên trong container, 3307 được export ra bên ngoài để mình có thể xem và thao tác với dữ liệu.
- networks sử dụng là back-tier
- volumes ở đây chính là mount folder bên ngoài với bên trong container như phần sử dụng command. './mysql-data' là folder mình muốn lưu trữ dữ liệu ở bên ngoài, bạn có thể link bất kỳ tới đâu bạn muốn.
- hostname: mysql
- Với web service
- image mình sử dụ là tutum/apache-php. Lưu ý là với laravel 5.2 trở về trước nhé, hay là với project mình không yêu cầu version php > 5.6
- links tới mysql container
- networks: cũng phải sử dụng là back-tier cùng với mysql cho toàn bộ service trong compose file để các container có thể giao tiếp với nhau
- volumes: Do docker-compose.yml file này của mình đặt ngày trong folder selfproject của mình nên đường dẫn đến project bên ngoài máy chủ là "." thư mục hiện tại và mount vào "/var/www/html/selproject" trong container
3docker run -tid -p 9000:80 -v ~/www/sites/FrProject/Github/selfproject:/var/www/html --name selfproject-server --link mysqlserver:mysql tutum/apache-php
- Như vấn đề với Override mà mình đã nói bên trên và đoạn config này giải quyết vấn đề đó.
OK việc cần làm là start nó
4docker run -tid -p 9000:80 -v ~/www/sites/FrProject/Github/selfproject:/var/www/html --name selfproject-server --link mysqlserver:mysql tutum/apache-php
Nhớ lưu ý tới việc quyền hạn và config nhá
Kết luận
Cảm ơn các bạn đã dành thời gian đọc bài viết của mình. Thời gian mình tìm hiểu về docker chưa được nhiều nên có thể có nhiều sai xót, rất mong nhận được sự góp ý từ mọi người để sửa đổi nội dung bài viết được tốt hơn.
Hiện tại trong tài liệu chính thức của docker compose không khuyến nghị sử dụng cho production, chỉ nên sử dụng ở môi trường development, staging, continous integration