Đến đây chúng ta có thể sử dụng Dockerfile để khởi tạo một server và cài đặt các service cần thiết lên đó rồi.

Tuy nhiên sẽ có những bất cập, đó là chúng ta phải cài tất cả service lên 1 container (kiến trúc 1 khối - monolithic), mà các service này lại phải cài đặt thủ công (apt-get install xxxyyy gì gì đó), trong khi chúng ta muốn sử dụng các image service có sẵn trên Docker hub ???

Hoặc 1 dự án thực tế sử dụng các service chạy độc lập (kiến trúc nhiều dịch vụ - microservice) chẳng lẽ chúng ta lại phải viết vài cái Dockerfile nữa sao. Không không, ở đây chúng ta không làm như vậy.

Vậy giải pháp là Docker compose (nghe giống giống cái php composer nhỉ, thực ra có giống đấy, lát mình nói sau).

Docker compose là công cụ cho phép chúng ta run nhiều container 1 lúc, mình có chém qua về nó ở P1.

Docker compose: thay vì cài đặt tất cả service (mysql, php, redis…) lên 1 container thì chúng ta có thể sử dụng docker-compose để chạy mỗi service trên mỗi container và kết nối các container lại với nhau. Giống như một hệ thống thực tế vậy.

Docker composer

Cài đặt

Mình xài Windows cài xong Docker cái thấy nó có sẵn Docker compose luôn, ai xài Linux thì tham khảo hướng dẫn ở đây nha https://docs.docker.com/compose/install/

Kiểm tra xem cài đặt thành công chưa

docker-compose -v

Viết docker-compose.yml

Trước tiên phải xác định các container sẽ sử dụng trong project. Ví dụ dự án mình là dự án php cần có 1 máy chạy source code và 1 máy để chạy mysql. Vậy là mình cần có 2 container.

Như vậy nội dung file docker-compose.yml cho project của mình về cơ bản sẽ như sau:

version: '3.5'
services:
    php-apache:
        build: .
        ports:
            - 8080:80 #<host>:<container>
        volumes:
            - ./source:/var/www/html #Mapping source code giữa máy thật (host) và container
            - ./apache/log:/var/log/apache2
        links:
            - mysql
        environment:
            DB_HOST: mysql #Là tên của container database nha
            DB_PORT: 3306
            DB_NAME: my-db
            DB_USER: devuser
            DB_PWD: devuser
    mysql:
        image: mysql:5.6
        ports:
            - "3307:3306" #<host>:<container>
        environment:
            MYSQL_ROOT_PASSWORD: root #Mặc định đã có user root rồi nên chỉ cần thiết lập password cho user này.
            MYSQL_DATABASE: my-db #Tạo sẵn db my-db
            MYSQL_USER: devuser #User này sẽ được tạo và grant cho my-db, không để root vì user root mặc định có sẵn rồi.
            MYSQL_PASSWORD: devuser
        volumes: #Vì dữ liệu sẽ mất nếu stop container vì vậy phải backup data vào máy thật
            - ./db/data:/var/lib/mysql 
            - ./db/log:/var/log/mysql

Và nội dung của Dockerfile như sau:

FROM php:7.3-apache
#https://hub.docker.com/_/php
LABEL maintainer="ChungTran<chungtran4078@gmail.com>"
RUN docker-php-ext-install pdo pdo_mysql mysqli
RUN cp "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
RUN apt-get update && apt-get install -y vim

** Giải thích chút:

Cấu trúc file docker-compose.yml của mình ở trên như sau:

version: '3.5'
services:
    php-apache:
        ...
    mysql:
        ...
  • Mỗi container là một service, ở đây mình có 2 service có tên php-apachemysql (tên này do mình tự đặt nha)
php-apache:
        build: .

Chỗ này là lý do có file Dockerfile ở trên. Do mình muốn cài đặt thêm một số thành phần nên mình sẽ chạy service này với image build từ Dockerfile.

Hiện tại file Dockerfile đang ở cùng cấp với file docker-compose.yml nên mình để build: . nha, nếu Dockerfile nằm thư mục khác, VD docker thì:

build:
    context: ./docker

**Lưu ý: docker-compose.yml có version nha các bạn, ở VD trên mình đang dùng version 3.5, các version có thể khác nhau về một số cú pháp, chi tiết tại đây: https://docs.docker.com/compose/compose-file/compose-versioning/

Ok xong xuôi, thực hiện docker-composer up, ta sẽ thấy các container lần lượt được start.

Bây giờ nếu nhấn Ctrl + C thì các container sẽ stop, trường hợp này sử dụng docker-composer up -d để chạy với chế độ nền.

##Testing Vào thư mục source, tạo file index.php:

<?php
$dbhost = $_ENV['DB_HOST'];;
$username = $_ENV['DB_USER'];
$password = $_ENV['DB_PWD'];
$dbname = $_ENV['DB_NAME'];
$port = $_ENV['DB_PORT'];

// Create connection
$conn = mysqli_connect($dbhost, $username, $password, $dbname, $port);

// Check connection
if (!$conn) {
    die("Connection failed: " . mysqli_connect_error());
}
echo "Connected successfully";

Sau đó truy cập localhost:8080 để xem kết quả.

Một số trường hợp có thể sẽ xảy ra lỗi Call to undefined function mysqli_connect() hoặc Connection refused hoặc No such file or directory thì kiểm tra lại file php.ini trong /usr/local/etc/php nhé.

  • Enable mysqli extension (extension=mysqli)
  • Kiểm tra giá trị của variables_order, sửa lại thành “EGPCS”. Đây là chuỗi ký tự đại diện cho các biến môi trường (http://php.net/variables-order)

Thế Docker Compose thì liên quan gì PHP Composer?

CHẢ LIÊN QUAN.

Nhưng mục đích thì có phần giống nhau.

  • php composer: cứ nhập tên package vào file composer.json, composer sẽ làm việc còn lại.
  • docker compose: cứ nhập tên service và image đi kèm vào file docker-compose.yml, docker compose sẽ làm việc còn lại.