Triển khai stack đến Docker Swarm

Ở bài trước chúng ta giới thiệu tổng quan về docker swarm mà nói về các tính năng, cũng như chạy một service đơn giản trong docker swarm. Trong phần này chúng ta đi vào phần Deploy một stack (gồm các service/container liên kết với nhau) trong docker swarm mà được gọi là “Docker Stack

Reference: Deploy a stack to a swarm

1. Về Docker Stack

  • Docker Swarm đơn thuần điều phối các container chạy trên nhiều các docker host. Nhưng giữa các container đấy không có sự phụ thuộc lẫn nhau. Chính vì vậy, để liên kết các container ấy thành một ứng dụng chúng ta cần phải thao tác thủ công cho phép kết nối giữa chúng.
  • Docker Compose là công cụ mà cho phép liên kết các container với nhau để chạy ứng dụng. Nhưng các container đấy lại chạy trên cùng một docker host. Vì vậy, nó sẽ có mặt hạn chế khi muốn high availability và horizontal scaling.
  • Với Docker Stack, nó cho phép chúng ta kết nối 2 công nghệ trên với nhau. Nó sử dụng tệp tin docker compose (mặc định docker-compose.yml) để định nghĩa, liên kết các container với nhau và chạy trong một cluster docker host (docker swarm). Hình dưới minh họa về Docker Stack

docker stack - docker swarm

2. Triển khai một stack

Chúng ta thực hiện deploy “LEMP” stack đến docker swarm với Docker Stack.

LEMP là stack gồm: Nginx, MySQL/MariaDB và PHP trên Linux

Thực hiện một số công việc sau:

  • Thiết lập docker swarm
  • Định nghĩa các services cho stack
  • Triển khai docker stack

2.1 Thiết lập docker swarm

Chúng ta tham khảo bài viết trước để thiết lập docker swarm

Xác nhận docker swarm đã tạo xong, với một số node

show docker nodes

2.2 Định nghĩa các services cho stack

Chúng ta thực hiện tạo tệp tin docker-compose.yml để định nghĩa các services cho stack, để cho phép triển khai trên docker swarm.

Tệp docker-compose.yml trong docker swarm không hỗ trợ  tùy chọn “build”, vì vậy mà chúng ta sẽ khai báo các image name trực tiếp ở mỗi service. Để sử dụng image name, chúng ta cần thực hiện build image trước với Dockerfile và push lên registry (private hoặc public).

Step1: Dựng private docker registry

Trong bài viết này tôi sử dụng private registry chứa các image, vì vậy chúng ta cần dựng private docker registry. Tham khảo qua bài viết dựng private docker registry

Nếu sử dụng một số public registry (như hub.docker.com), chúng ta có thể bỏ qua bước này.

Step2: Build các docker image

– Build php7-fpm image

Tạo tệp tin Dockerfile để build image cho php7-fpm với nội dung sau

FROM php:7.2-fpm

RUN apt-get update
RUN apt-get install libxml2-dev unzip libmcrypt-dev zlib1g-dev -y
#Using docker-php-ext-install to install php modules
RUN docker-php-ext-install pdo_mysql mysqli mbstring xml opcache zip

EXPOSE 9000
CMD ["php-fpm", "-F"]

Chúng ta sử dụng image gốc là php:7.2-fpm và thực hiện cài một số thư viện và một số module cho php

Thực hiện build image với tên hub.example.local/php7-fpm

 docker build -t hub.example.local/php7-fpm .

build image php7-fpm

– Build nginx image

Nội dung tệp tệp Dockerfile có nội dung như sau:

FROM nginx:latest

MAINTAINER KeepWalking86

ADD ./default.conf /etc/nginx/conf.d/
RUN mkdir -p /var/www/example/
RUN chown -R nginx:nginx /var/www/example

EXPOSE 80

Trong đó, chúng ta build lại từ image gốc nginx:latest, và thực hiện một số tùy như:

Add tệp ‘default.conf’ để thay nội dung tệp cấu hình chính mặc định của nginx. Nội dung tệp như sau:

server {
        listen 80;
        listen [::]:80 ipv6only=on;

    # Log files for Debugging
        access_log /var/log/nginx/laravel-access.log;
        error_log /var/log/nginx/laravel-error.log;

    # Webroot Directory for Laravel project
        root /var/www/example/public;
        index index.php index.html index.htm;

        # Your Domain Name
        server_name example.local;
        location ~* \.(jpg|jpeg|gif|css|png|js|ico|txt|srt|swf|zip|rar|html|htm|pdf)$ {
                access_log        off;
                log_not_found     off;
                expires 30d; # caching, expire after 30 days
        }

        location / {
                try_files $uri $uri/ /index.php?$query_string;
        }

    # PHP-FPM Configuration Nginx
        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                #fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
                fastcgi_pass web-phpfpm:9000;
        }
}

Ở đây, tôi khai báo một host với tên site “example.local”; vị trí thư mục root của website là “/var/www/example/public”. Website chạy php và sử dụng bộ dịch là FastCGI. Trong đó sử dụng chỉ thị “fastcgi_pass” để thiết lập kết nối đến server FastCGI, mà trong trường  hợp này là kết nối đến server web-phpfpm:9000. Ở đây web-phpfpm là tên service mà ta sẽ định nghĩa ở trong tệp docker-compose.yml trong Step tiếp theo.

Thực hiện build image với tên hub.example.local/nginx

docker build -t hub.example.local/nginx .

build nginx nginx

Step3: Tạo tệp tin docker-compose.yml

Chúng ta định nghĩa 03 service: db, web-phpfpm và web-nginx.

Một số tùy chọn cho mỗi service ở tệp docker compose như sau:

– image: xác định tên image để tạo container

– deploy: tùy chọn cấu hình cho việc triển khai

+ replicas: Số lượng bản sao container

+ constraints: [node.role == worker/manager] → Xác định container sẽ được triển khai ở host nào trong docker swarm. Ở đây, chúng ta xác định vị trí docker host theo vai trò manager/worker trong docker swarm.

– volumes: để mount source code giữa docker host và container. Mục đích của tôi là muốn mount source code tại thư mục ./src trên node manager vào web-phpfpm và web-nginx.

– Ở service “db”, tôi khai báo một số biến ENV để tạo thông tin database như: user, password, … Sau khi tạo và chạy stack, chúng ta có thể kiểm tra kết nối web và db

Tham khảo thêm về cấu hình tệp docker-compose cho docker stack từ:

https://docs.docker.com/compose/compose-file/#deploy

Nội dung tệp docker-compose.yml như sau:

version: "3"

services:
    db:
      image: mariadb:latest
      deploy:
        replicas: 2
        placement:
          constraints: [node.role == worker]
      networks:
        - mynet
      environment:
        MYSQL_ROOT_PASSWORD: P@ssw0rd
        MYSQL_DATABASE: laravel
        MYSQL_USER: keepwalking
        MYSQL_PASSWORD: P@ssw0rd

    web-phpfpm:
      image: hub.example.local/php7-fpm
      deploy:
        replicas: 2
        placement:
          constraints: [node.role == manager]
      volumes:
        - ./src:/var/www/example
      networks:
        - mynet

    web-nginx:
      image: hub.example.local/nginx
      deploy:
        replicas: 2
        placement:
          constraints: [node.role == manager]
      depends_on:
        - db
        - web-phpfpm
      ports:
        - 8080:80
      networks:
        - mynet
      volumes:
        - ./src:/var/www/example

networks:
  mynet:

2.3 Thực hiện deploy docker stack

Chúng ta thực hiện lệnh sau để triển khai stack với tên “lemp”

​docker stack deploy --compose-file docker-compose.yml lemp

Thực hiện một số lệnh sau để kiểm tra stack

Check docker stack lemp

Như vậy, chúng ta đã tạo lemp stack với 03 services. Mỗi service đều nhân bản với 02 replicas. Trong đó service: web-nginx và web-phpfpm được phân bố ở node vnsys (là node manager); service db được phân bố vào node02 và node03 là các node worker.

Advertisement

Chia sẻ:

Thích bài này:

Thích

Đang tải…