- Service
- Lệnh docker-compose
- Tạo Image HTTPD
- Tạo Image PHP (FPM)
- Chuẩn bị my.cnf cho MySQL
- Biên tập docker-compose.yml
- Cài đặt Joomla
Chia nhỏ ứng dụng của bạn thành các Service Docker
Khi phân phối các ứng hoàn thành, từng phần của ứng dụng đó ở dạng sản phẩm gọi nó là các service (dịch vụ), hãy nhớ lại ví dụ của phần trước bạn đã cài đặt một ứng dụng Wordpress
, hãy xem nó để trang web đó chạy được bạn đã tạo ra những thành phần gì:
- Một container chạy HTTPD Apache là webserver.
- Một container chạy PHP để thi hành code các file PHP.
- Một container chạy MySQL làm CSDL cho trang web.
Những thành phần này khi phân phối ứng dụng chúng đều được gọi là các dịch vụ service. Như vậy các service thực chất là các container chạy đáp ứng chức năng thành phần tạo nên ứng dụng. Bạn cần hiểu sơ qua về khái niệm này vì ta sẽ sử dụng nó trong docker-compose
giúp tạo ra các service trên một cách tự động.
Docker Compose với file docker-compose.yml
File docker-compose.yml
gần giống ý nghĩa với file Dockerfile
đã tìm hiểu trong
Sử dụng Dockerfile,
là một file text, viết với định dạng YAML (Ain’t Markup Language, đọc nhanh
định dạng Định dạng YML)
là cấu hình để tử đó lệnh docker compose
sinh ra và quản lý các service (container),
các network, các ổ đĩa ... cho một ứng dụng
hoàn chỉnh.
Lệnh docker-compose
Về nội dung bên trong file docker-compose.yml
sẽ tìm hiểu phía sau, giờ giả sử đang có file này, từ thư mục chứa file này gõ lệnh docker-compose
với tham số phù hợp để thi hành những tác vụ như:
-
Tạo và chạy các thành phần định nghĩa trong
docker-compose.yml
(các dịch vụ, image, container, mạng, đĩa ...).docker-compose up
- Dừng và xóa: image, container, mạng, đĩa tạo ra bởi
docker-compose up
docker-compose down
- Theo dõi Logs từ các dịch vụ
docker-compose logs [SERVICES]
- Ngoài ra còn có các lệnh nhỏ khác như
exec
ps
restart
... sẽ tìm hiều dần khi cần dùng đến.
Nội dung - Bài thực hành với docker-compose
Trong phần này, cơ bản thực hiện lại ví dụ ở phần Network, cài đặt PHP, APACHE, MYSQL, MEMCACHE, WORDPRESS với Docker nhưng sẽ sử dụng đến kỹ thuật
triển khai product với docker-compose.yml
, kết quả của ví dụ này đó là:
- Tạo được image chứa Server Memcache để sử dụng cached dữ liệu cho PHP cũng như SESSION PHP
- Tạo được một image chạy HTTPD APACHE
httpd
, cài và cấu hình lại phù hợp với ứng dụng web Wordpress, đặt tên làw-httpd:version2
- Tạo được một image chạy PHP-FPM, đã cấu hình lại: đặt tên image là
w-php:version2
- Tạo được file
docker-compose.yml
nó thiết lập để tạo ra các dịch vụ: chạy Apache, PHP từ 2 image trên, tạo dịch vụ chạy MySQL, tạo network để nối các dịch vụ trên vào, ánh xạ thư mục web chứa code WordPress vào dịch vụ Apache và PHP. - Chạy
docker-compose
để chạy các dịch vụ, tiến hành cài đặt Joomla: Có một website chạy Joomla!
Bây giờ sẽ tiến hành từng bước một để có được kết quả trên!. Trước tiên tạo ra một thư mục đặt tên là appproject
nơi đó lưu các file cấu hình, dữ liệu của dự án trên.
Tạo Image chạy Apache HTTPD
Tạo thư mục appproject/httpd
để lưu dữ liệu. Image này xây dựng từ image cơ sở httpd:latest
,
chỉnh sửa lại httpd.conf
, cài đặt thêm htop
, vim
. Trước tiên chạy lệnh sau để lấy ra file httpd.conf
nằm trong image httpd:latest
để mà chỉnh sửa.
Chuẩn bị dữ liệu
docker run -it --rm -v /mycode/:/home/conf httpd cp conf/httpd.conf /home/conf/httpd.conf
Như phần trước, lệnh trên chạy httpd:latest
, chạy xong xóa luôn container. Khi chạy nó copy httpd.conf
trong container ra thư mục host /mycode/
(bạn có thể đặt thư mục khác của bạn).
Sau lệnh này bạn có file /mycode/httpd.conf
, hãy copy nó vào dự án tại appproject/httpd/httpd.conf
, mở file này ra và chỉnh sửa các nội dung, bỏ comment #
để nạp các module cần thiết như:
LoadModule proxy_module modules/mod_proxy.so # hỗ trợ proxy LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so # để gọi PHP qua Proxy LoadModule deflate_module modules/mod_deflate.so # để apache nén dữ liệu trả về LoadModule rewrite_module modules/mod_rewrite.so # để sử dụng .htaccess, rewrite url LoadModule ssl_module modules/mod_ssl.so # để hỗ trợ SSL (https, port 443) Include conf/extra/httpd-vhosts.conf # để nạp các Virtual Host từ file httpd-vhosts.conf #Thêm vào AddHandler "proxy:fcgi://php-product:9000" .php # để chạy Script PHP qua Proxy
Tạo file appproject/httpd/httpd-vhosts.conf
và cập nhật nội dung sau, để tạo ra một HOST chạy với domain mywordpressblog.com
cổng 80, thư mục web là /home/sites/default/
<VirtualHost *:80> ServerName mywordpressblog.com ServerAdmin xuanthulab.net@gmail.com DocumentRoot /home/sites/default/ CustomLog /dev/null combined #LogLevel Debug ErrorLog /home/sites/default/error.log <Directory /home/sites/default/> Options -Indexes -ExecCGI +FollowSymLinks -SymLinksIfOwnerMatch DirectoryIndex index.php index.html Require all granted AllowOverride None </Directory> </VirtualHost>
Tạo file index.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"><title>TEST HTML APACHE</title> </head> <body> <h1>Apache HTTML đang chạy ...</h1> </body> </html>
Tương tự tạo một file index.php
<?php phpinfo();
File Dockerfile
để tạo Image Apache
Sau khi chuẩn bị dữ liệu trên, tạo file appproject/httpd/Dockerfile
với nội dung sau:
FROM httpd:latest # Cập nhật và cài đặt vim, htop RUN apt-get update -y \ && apt-get install vim -y \ && apt-get install htop \ && rm -rf /var/lib/apt/lists/* # Copy các file dữ liệu, cấu hình vào image ADD ./index.html /home/sites/default/index.html ADD ./index.php /home/sites/default/index.php ADD ./httpd.conf /usr/local/apache2/conf/httpd.conf ADD ./httpd-vhosts.conf /usr/local/apache2/conf/extra/httpd-vhosts.conf # Mở cổng 80, 443 trên network container nối vào EXPOSE 80 443 CMD [ "httpd-foreground"]
Đang ở thư mục httpd
gõ lệnh tạo để Tạo image từ Dockerfile
docker build -t httpd:version2 --force-rm -f Dockerfile . # tạo image từ Dockerfile docker save --output httpd.tar httpd:version2 # lưu image ra file (để gộp layer) docker image rm httpd:version2 # xóa image docker load -i httpd.tar # nạp lại image từ file
Đến đây đã có image chứa APACHE HTTPD với config lại như trên, có thể kiểm tra chạy thử nhanh bằng lệnh:
docker run -it --rm -p 3456:80 httpd:version2 # container tự xóa khi kết thúc
Truy cập http://localhost:3456
và http://localhost:3456/index.html
để kiểm tra.
Có thông báo lỗi vì chạy mà chưa có PHP (container php-product
)
Tạo Image chạy PHP-FPM
Tạo thư mục appproject/php
để lưu dữ liệu. Image này xây dựng từ image cơ sở php:7.3-fpm
Chuẩn bị dữ liệu
Trích xuất php.ini từ image php:7.3-fpm
.
docker run -it --rm -v /mycode/:/home/ php:7.3-fpm cp /usr/local/etc/php/php.ini-production /home/php.ini
Copy file php.ini
vào thư mục appproject/php/php.ini
. Mở file ra và chỉnh sửa các thiết lập:
short_open_tag = On expose_php = Off ; THIẾT LẬP PHP SESSION DÙNG MEMCACHED session.save_handler = memcached session.save_path = "c-memcached01:11211" memcached.sess_locking = 0 memcached.sess_prefix = 'memc.sess.' ; THIẾT LẬP OPCACHE NẾU CÓ DÙNG (cache mã nguồn PHP) ; zend_extension=opcache.so; ; opcache.interned_strings_buffer=4 ; opcache.max_accelerated_files=2000 ; opcache.memory_consumption=64 ; opcache.revalidate_freq=2 ; opcache.fast_shutdown=0 ; opcache.enable_cli=0 ; opcache.interned_strings_buffer=4 ; opcache.max_accelerated_files=2000 ; opcache.memory_consumption=64 ; opcache.revalidate_freq=2 ; opcache.fast_shutdown=0 ; opcache.enable_cli=0
File Dockerfile để tạo Image PHP
Tạo ra file appproject/php/Dockerfile
với nội dung sau:
FROM php:7.3-fpm # cài đặt và kích hoạt opcache, mysqli, pdo_mysql, memcached RUN apt-get update -y \ && apt-get install libzip-dev zip libmemcached-dev -y \ && apt-get install vim -y \ && apt-get install htop \ && docker-php-ext-install zip opcache mysqli pdo_mysql \ && docker-php-ext-enable mysqli \ && docker-php-ext-enable opcache \ && docker-php-ext-enable pdo_mysql \ && pecl install memcached \ && rm -rf /var/lib/apt/lists/* ADD ./php.ini /usr/local/etc/php/php.ini EXPOSE 9000 # CMD [ "httpd-foreground"]
Đang ở thư mục php gõ lệnh tạo để Tạo image từ Dockerfile, đặt tên image này là php:version2
docker build -t php:version2 --force-rm -f Dockerfile . # tạo image từ Dockerfile docker save --output php.tar php:version2 # lưu image ra file (để gộp layer) docker image rm php:version2 # xóa image docker load -i php.tar # nạp lại image từ file
Chuẩn bị file my.cnf
cho MySQL
Ở đây ta chuẩn bị dữ liệu để xây dựng container MySQL, tiến hành trích xuất file my.cnf
có trong mysql:latest
ra:
docker run -it --rm -v /mycode/:/home/ mysql:latest cp /etc/mysql/my.cnf /home/my.cnf
Sau lệnh này, hãy copy file my.cnf
vào thư mục /mycode/db/my.cnf
( nhớ thư mục này sau này sẽ dùng để ánh xạ
dữ liệu vào container), mở file này ra thêm vào nội dung:
[mysqld] default-authentication-plugin=mysql_native_password
Biên tập docker-compose.yml
Đến đây bạn có 2 image custome lại là php:version2
, httpd:version2
giờ ta sẽ tiến hành các bước biên tập ra file docker-compose.yml
để dùng với lệnh docker-compose
.
Tạo ra file này ở đường dẫn appproject/docker-compose.yml
, dùng một trình soạn thảo bất kỳ tiến hành biên tập nội dung. Mục đích trong trường hợp này của file docker-compose.yml
là: tạo ra 4 dịch vụ gồm: máy chủ HTTP, PHP, máy chủ MySQL, máy chủ Memcached và chúng được nối vào cùng một mạng.
Nội dung và ý nghĩa các dòng viết trong file này được giải thích trong các comment, bạn có thể chỉnh lại cho phù hợp với mục đích của mình:
# VIẾT THEO CÚ PHÁP YAML, CHÚ Ý CHÍNH XÁC KHOẢNG TRẮNG ĐẦU CÁC DÒNG version: "3" # chọn viết theo bản 3 docs.docker.com/compose/compose-file/ services: # CÁC DỊCH VỤ (CONTAINER) NĂM TRONG services
pro-memcached: # (((1))) BẮT ĐẦU TẠO DỊCH VỤ THỨ NHẤT image: "memcached:latest" # Image tạo ra dịch vụ container_name: c-memcached01 # Tên container khi chạy restart: always hostname: memcached networks: - my-network # nối vào mạng my-network (tạo mạng này ở dưới) command: - "--conn-limit=2048" # Giới hạn kết nối là 2048 - "--memory-limit=2048" # Giới hạn cho phép dùng tới 4096 MB bộ nhớ làm cache
xtlab-apache: # (((2))) TẠO DỊCH VỤ HTTPD image: "httpd:version2" # sử dụng image custome lại ở trên để tạo container container_name: c-httpd01 # tên khi chạy container HTTPD restart: always hostname: httpd01 networks: - my-network ports: - "8080:80" # Mở cổng 8080 public, ánh xạ vào 80 - "443:443" volumes: # Ánh xạ thự mục vào container - dir-site:/home/sites/ # Bind ổ đĩa - dir-site
xtlab-mysql: # (((3))) TẠO DỊCH VỤ MYSQL image: "mysql:latest" container_name: mysql-product restart: always hostname: mysql01 networks: - my-network environment: MYSQL_ROOT_PASSWORD: abc123 #Thiết lập password volumes: - /mycode/db:/var/lib/mysql # thư mục lưu DB - /mycode/db/my.cnf:/etc/mysql/my.cnf # ánh xạ file cấu hình
xtlab-php: # (((4))) TẠO DỊCH VỤ PHP image: "php:version2" container_name: php-product # tên container hostname: php01 restart: always networks: - my-network volumes: - dir-site:/home/sites/ # Bind ổ đĩa - dir-site
networks: # TẠO NETWORK my-network: driver: bridge
volumes: # TẠO Ổ ĐĨA dir-site: # ổ đĩa này lưu dữ liệu ở /mycode/ driver_opts: device: /mycode/ # Hãy đảm bảo có thư mục /mycode/default o: bind
Từ thư mục chứa file docker-compose.yml
trên, chạy lệnh sau để để tạo các thành phần mà nó mô tả:
docker-compose up
Kết quả thể hiện với mô hình hóa như sau:
Nhìn vào sơ đồ kết quả ta thấy:
- Có 4 container đang chạy (mysql-product, c-httpd01, php-product, c-memcached01), chúng được nối vào mạng
my-network
vậy giữa chúng có thể liên lạc với nhau qua cổng tương ứng (3304, 80, 9000, 11211). Riêng container có public cổng8080
ánh xạ vào cổng80
của nó, vậy bên ngoài mạng có thể kết nối tới nó qua cổng8080
- Có ổ đĩa
dir-site
dữ liệu nó lưu tại máy HOST/mycode/
, ổ đĩa này cũng nối vào containerc-http01
ở thư mục/home/sites
. Tương tự nó cũng nối vàophp-product
- Container
mysql-product
cũng ánh xạ thư mục/mycode/db
vào/var/lib/mysql
Nếu cần chỉnh sủa file docker-compose.yml
, thì hãy gỡ các thành phần tạo ra bởi lệnh docker-compose up
bằng cách gõ:
docker-compose down
Sau khi sửa xong chạy lại docker-compose up
Lưu ý về Container MYSQL
MySQL trên chạy là phiên bản mới 8.x
, nên tài khoản root mặc định tạo ra ban đầu dùng cơ chế xác thực mới, rất nhiều ứng dụng chưa sử dụng thư viện kết nối mới này,
nên có thể bạn cần chuyển sang xác thực mysql_native_password, ví dụ chuyển tài khoản root sang cơ chế xác thực mysql_native_password
:
docker exec -it mysql-product bash # vào container apt-get update && apt-get install vim -y # cài vim vim /etc/mysql/my.cnf # vào chỉnh sửa my.cnf # vào mysql với password abc123 mysql -pabc123 # chạy các query ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'abc123'; FLUSH PRIVILEGES; exit; # Ra khỏi container và gõ để khởi động lại docker restart mysql-product
Như vậy đã tạo được một hệ thống, chạy ứng dụng Web (Apache, PHP, MySQL) có dùng Memcached. Từ đây chỉ việc để mã nguồn của ứng dụng bất kỳ vào ổ đĩa dir-site
và sử dụng.
Ví dụ cài đặt Joomla
Ta thử cài đặt CMS nguồn mở Joomla vào hệ thống trên.
- Hãy Tải Joomla về, giải nén để có thư mục mã nguồn của Joomla.
- Hệ thống trên đang chạy ứng dụng mặc định ở thư mục
/home/sites/default
(tương ứng /mycode/default trong máy HOST), bạn có thể cấu hình Apache để chạy với nhiều tên miền, nhiều ứng dụng mỗi ứng dụng là một thư mục nào đó do bạn tạo - Copy tất cả các file trong thư mục mã nguồn tải về vào thư mục tại máy HOST
/mycode/default
Vào địa chỉ http://localhost:8080
để bắt đầu cài đặt.
Nhập thông tin website muốn cài và tài khoản quản trị muốn tạo, rồi bấm vào Tiếp theo
Khai báo kết nối đến MySQL: chú ý để nối đến MySQL tên máy chủ phải điền sao cho nó liên lạc đến container tưng ứng, đây chỉnh là mysql-product:3306
,
điền tài khoản kết nối MySQL đã tạo (root, pass là abc123
nếu chưa đổi), điền tên CSDL muốn tạo và bấm Tiếp Theo
Bấm vào cài đặt
Cài đặt thành công
Website kết quả