Đối với mỗi quá trình phát triển một web application, việc xây dựng môi trường phát triển là không thể thiếu. Thời đại Devops chưa thực sự rõ ràng, các developer thường tự cài đặt trên máy thật của chính mình, như là cái XAMPP nếu code PHP, cài JDK với Java,... và cả các Database căn bản.

Sau đó với sự ra đời của Vagrant, kết hợp với ứng dụng tạo máy ảo miễn phí Virtualbox, dần dần việc cài đặt trở nên linh hoạt và hiệu quả hơn, cô lập mức tới mức OS để giữ cho máy thật ổn định.

Sự phát triển không ngừng của phần Devops vốn không kém phần quan trọng, thì Docker đã đời, đặc biệt có Kubenetes hiện đang làm mưa làm gió ở trong ngành để giải quyết các vấn đề trong hệ thống cực lớn... Vậy với các hệ thống nhỏ thì sao?

Hôm nay mình xin giới thiệu Docker Compose với cách thiết lập hết sức căn bản để xây dựng môi trường dev cho Laravel.

1. Cài đặt

Docker compose vốn là công cụ để định nghĩa và quản lý container trong Docker một cách rõ ràng và rành mạch nhất. Trước hết, chúng ta cần cài đặt Docker đã.

https://docs.docker.com/install/linux/docker-ce/centos/
(*) Đối với các OS khác, bạn có thể nhìn sang sidebar bên trái để lựa chọn phù hợp.

Sau đó bạn tiếp tục vào trang này, lựa chọn OS phù hợp và chạy command theo hướng dẫn để tải và cài đặt docker compose.

# Tải docker compose
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# Thêm quyền execute cho file
$ sudo chmod +x /usr/local/bin/docker-compose

Vậy là chúng ta đã xong bước cài đặt.

2. Cấu hình

Docker compose sử dụng YAML file để cấu hình các container, những ai đã làm với Ansible có lẽ đã rất quen thuộc với định dạng này, rất rõ ràng, đơn giản mà lại vô cùng dễ hiểu.

Mặc định docker compose sẽ đọc từ file docker-compose.yml, bước đầu thiết kế một môi trường ta cần định nghĩa rõ các thành phần cần thiết, ở đây, mình sẽ thử thiết lập môi trường cho một ứng dụng Laravel, ta sẽ cần tối thiểu:

  • Nginx: dùng làm proxy server chuyển request cho PHP-FPM xử lý.
  • PHP-FPM: dùng để compile code php của Laravel.
  • MariaDB: cơ sở dữ liệu.

docker-compose.yml:

version: '3'

services:
    web:
        image: nginx:1.11.9
        ports:
            - "80:80"
            - "443:443"
        depends_on:
            - php
        volumes:
            - /var/www/web:/var/www/web
            - ./nginx/nginx.conf:/etc/nginx/nginx.conf
            - ./nginx/config/vnlab_dev.conf:/etc/nginx/conf.d/default.conf
        restart: always
        networks:
            - app-network

    php:
        build: ./php
        image: php_fpm:7.1
        working_dir: /var/www/web
        depends_on:
            - database
        volumes:
            - /var/www/web:/var/www/web
        restart: always
        networks:
            - app-network

    database:
        image: mariadb:10.1
        volumes:
            - vietnamlab_db:/var/lib/mysql
        restart: always
        environment:
            MYSQL_ROOT_PASSWORD: 'root'
            MYSQL_DATABASE: 'vnlab'
            MYSQL_USER: 'vnlab'
            MYSQL_PASSWORD: 'vnlab'
        networks:
            - app-network

volumes:
    vietnamlab_db:

networks:
    app-network:
        driver: bridge

Với các parameter được thiết lập, bạn dễ dàng tìm thấy tài liệu ở trên chính trang chủ của Docker compose. Nhưng hiểu nhanh gọn, mình sẽ giải thích đơn giản:

  • build: Nơi có Dockerfile để build lên một image.
  • image: Đọc file image từ bên trong hệ thống, nếu không tìm thấy nó sẽ tìm trên Docker Hub hoặc Private Registry (nếu có) để tải về và sử dụng.
  • working_dir: Trỏ trực tiếp để ngay thư mục mà bạn muốn container trỏ và thao tác ngay trên đó (như chạy command, bash,...)
  • volumes: map folder/file từ ngoài máy thật vào trong container, hoặc map từ Docker Volume vào bên trong máy ảo, chi tiết về các loại volume bạn tham khảm tại đây.
  • networks: Áp dụng một/hoặc nhiều network cho container đó. Ở đây cả 3 sẽ sử dụng chung một private network tên là app-network được định nghĩa bên dưới.
  • environment: Thiết lập các biến môi trường để dụng bên trong container.

Như ở trên có thể thấy mình đã mount: /var/www/web từ máy thật /var/www/web vào bên trong container, nó chứa source của Laravel để chạy. Tiếp đó mình mount: ./nginx/nginx.conf:/etc/nginx/nginx.conf./nginx/config/vnlab_dev.conf:/etc/nginx/conf.d/default.conf để thiết lập proxy trỏ tới PHP-FPM.

./nginx/config/vnlab_dev.conf:

server {
        listen       80 default_server;
        server_name  laravel;
        root /var/www/web/public;

        client_max_body_size 64M;

        location ~* /(?:uploads|files)/.*\.php$ {
                deny all;
        }

        location / {
                index index.php index.html index.htm;
                try_files $uri $uri/ /index.php?$args;
        }

        location ~* \.(gif|jpg|jpeg|png|css|js)$ {
                expires max;
        }

        location ~ \.php$ {
                try_files $uri =404;

                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_index   index.php;
                fastcgi_pass    php:9000;
                include         fastcgi_params;
                fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
                fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;
        }
}

Cuối cùng, để chạy được Laravel, chúng ta không thể chỉ sử dụng image php-fpm đơn thuần được mà sẽ cần phải cài thêm một vài packages cần thiết, để cài chúng ta sẽ cần viết một Dockerfile đơn giản.

./php/Dockerfile:

FROM php:7.1-fpm

RUN apt-get update

RUN apt-get install -y libmcrypt-dev unzip && \
    docker-php-ext-install mbstring mcrypt pdo_mysql

RUN groupmod -g 1000 www-data && \
    usermod -u 1000 www-data

# Chú ý: File này sẽ cần tạo riêng nếu muốn thay đổi cài đặt gốc!!!
COPY php.ini /usr/local/etc/php/

3. Chạy thử

Sau khi đã thiết lập xong toàn bộ các bước trên, kiểm tra lại các cấu hình, ta sẽ chạy duy nhất một lệnh để Docker tải và thiết lập các container như mong muốn.

$ docker-compose up -d

Cực kì đơn giản và tiện lợi phải không nào? ^^!

Như có thể thấy, đối với việc xây dựng môi trường dev ở local, hoặc đối với các dự án nhỏ thì Docker Compose rất tiện lợi và nhanh chóng. Hẹn gặp lại các bạn ở một mức cao hơn, đó là quản lý cluster với Docker Swarm kết hợp với Docker compose nhé!