Cách mình khởi tạo Blog này như thế nào?


Hoàn cảnh lịch sử

Sau một thời gian nghỉ dài hạn không viết blog nữa, nên giờ mình đã comeback. Nội dung chủ yếu cũng quay quanh công việc hiện tại của mình mà thôi.

Tuy nhiên một thanh niên nghèo một vợ một con như mình thì lấy tiền đâu ra mà host cái blog này lên trên VPS, nên thành ra vẫn đâm đầu vào những cái VPS free của AWS, GCP, Azure,.. mà thôi.

Nhưng tụi hắn chỉ cho xài có 1 năm à, hết là phải đóng xiền vào. Thế là anh ta suy nghĩ viết vài ba cái script bé tí, quyết định mội lần mirate qua VPS mới thì dùng script để provision luôn. Nghĩ mình cũng ma lanh thật 😛


Blog này viết trên nền tảng nào?

Tất nhiên mình sẽ dùng một phần mềm bên thứ 3 để làm blog này rồi. Mình không có dại mà tự viết ra một trang blog 😉

Mình sử dụng WordPress, một phần mềm quản lý nội dung (CMS) khá mạnh cho tạo ra các trang web cho cá nhân cũng như tổ chức.

Rồi mình sẽ sử dụng 1 VPS (xài chùa của mấy bên Cloud Platform thôi) để triển khai trang web mình làm lên thôi.


Vậy mình đã triển khai như thế nào?

Vì mình muốn sẽ xài chùa lâu dài, nên mình đã nghĩ cách làm sao có thể mirate trang web của mình từ VPS này qua VPS khác một cách nhanh nhất và không bị mất dữ liệu.

Mình sẽ sử dụng Docker, đã đóng gói sẵn WordPress và các dependencies cần thiết, nên mình không cần phải nghĩ ngợi về việc cài đặt như thế nào nữa.

Deploy WordPress với Docker

Trước tiên bạn phải sắp xếp các file theo cấu trúc thư mục sau:

Directory
├─ .env
├─ docker-compose.yml
└─ scripts
   ├─ backup.sh
   ├─ destroy.sh
   ├─ provision.sh
   └─ restore.sh

Điều kiện tiên quyết đầu tiên là OS của bạn phải được cài docker và docker-compose nhé

Mình tạo ra 1 docker-compose để có thể triển khai đồng thời WordPress và MySQL (db cho wordpress). Nội dung cụ thể như sau:

version: '3.3'
services:
  db:
    image: ${MYSQL_IMAGE}
    container_name: db_container
    volumes:
      - db_data:/var/lib/mysql
      - db_config:/etc/mysql
    ports:
      - ${MYSQL_PORT}:3306
    restart: always
    env_file:
      - .env
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}

  wordpress:
    depends_on:
      - db
    image: ${WORKPRESS_IMAGE}
    container_name: wp_container
    volumes:
      - wp_data:/var/www/html
    ports:
      - ${WORDPRESS_PORT}:80
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:${MYSQL_PORT}
      WORDPRESS_DB_USER: ${WORDPRESS_DB_USER}
      WORDPRESS_DB_PASSWORD: ${WORDPRESS_DB_PASSWORD}
      WORDPRESS_DB_NAME: ${WORDPRESS_DB_NAME}
volumes:
  wp_data:
    external: true
  db_data:
    external: true
  db_config:
    external: true

Có 2 nội dung cần lưu ý ở file docker-compose trên:

  • Docker compose này sẽ đọc một file .env để get các giá trị cần thiết có thể thay đổi được
  • Các volumes mình sẽ cấu hình external = true để docker-compose này sẽ lấy các docker volume bên ngoài đã có sẵn.

Đây là thông tin file .env bạn cần phải đặt cùng thư mục với file docker-compose.yaml

MYSQL_ROOT_PASSWORD=somewordpress
MYSQL_DATABASE=wordpress
MYSQL_USER=wordpress
MYSQL_PASSWORD=wordpress
MYSQL_PORT=3306
MYSQL_IMAGE=mysql:5.7

WORDPRESS_PORT=8000
WORDPRESS_DB_USER=wordpress
WORDPRESS_DB_PASSWORD=wordpress
WORDPRESS_DB_NAME=wordpress
WORKPRESS_IMAGE=wordpress:5.5.1

Tiếp tục, mình sẽ viết một shell script để provision docker-compose này:

#!/bin/bash
echo "====================================="
echo "# Start WordPress - MySQL container #"
echo "====================================="

WORK_DIR=`dirname $(readlink -f $0)`

declare -a volumes
volumes=(wp_data db_data db_config)

is_docker_installed() {
    sudo docker ps > /dev/null 2>&1
}

is_docker_compose_installed() {
    sudo docker-compose version > /dev/null 2>&1
}

is_volume_exists() {
    sudo docker volume inspect $1 > /dev/null 2>&1
}

is_docker_installed
if [[ $? -ne 0 ]]; then
    echo "Can not run docker command"
    echo "Skipped deploy process..."
    exit 0
fi
is_docker_compose_installed
if [[ $? -ne 0 ]]; then
    echo "Can not run docker-compose command"
    echo "Skipped deploy process..."
    exit 0
fi

for volume in "${volumes[@]}"; do 
    is_volume_exists $volume
    if [[ $? -ne 0 ]]; then
        sudo docker volume create --name=$volume > /dev/null 2>&1
        echo "Created $volume volume"
    fi
done
cd $WORK_DIR/..
sudo docker-compose up -d
cd - > /dev/null 2>&1

Khi run script này, coi như là bạn đã deploy thành công và có thể bay vô test được rồi 😉

Mirate sang một VPS khác

Đây là một vấn để nan giải cho những kẻ ít tiền như mình. Nên tư tưởng trong đâu mình lúc nào cũng phải mirate qua bên khác khi bên hiện tại hết thời gian trial 🙂

Mình có một shell script để backup các container data hiện tại (đối với WordPress sẽ backup htdocs directory, còn MySQL sẽ backup lại config và data directory – MySQL mình không backup bằng cách dump db mà backup nguyên cục data luôn cho khỏe, tuy nhiên bạn phải nhớ các credentials để có thể kết nối giữa WordPress và MySQL nhé, tốt nhất là sử dụng chung file .env như trên). Đây là script backup:

#!/bin/bash
echo "==============================================="
echo "# Backup WordPress - MySQL config & data      #"
echo "# Backup tar files for all data volume        #"
echo "# Usage:                                      #"
echo "# ./backup.sh -o <output_directory>           #"
echo "# All tar files will be created in output dir #"
echo "==============================================="

RUNNING_DIR=$PWD
volumes=(wp_data db_data db_config)

while getopts v:o: flag
do
    case "${flag}" in
        o) output=${OPTARG};;
    esac
done

is_docker_installed() {
    docker ps > /dev/null 2>&1
}
is_volume_exists() {
    docker volume inspect $1 > /dev/null 2>&1
}


is_docker_installed
if [[ $? -ne 0 ]]; then
    echo "Can not run docker command"
    echo "Skipped backup process..."
    exit 0
fi

for volume in "${volumes[@]}"; do 
    is_volume_exists $volume
    if [[ $? -ne 0 ]]; then
        echo "${volume} volume is not exists"
        echo "Skipped backup process..."
        exit 0
    fi
    CID=$(docker run -d -v ${volume}:/${volume} busybox true)
    if [[ $output == "" ]]; then
        output="./"
    fi
    mkdir -p $output
    cd /tmp
    rm -f ${volume}.tar
    docker cp $CID:/${volume} ./
    cd $volume
    tar cvf ../${volume}.tar ./ > /dev/null 2>&1
    echo "Archived volume $volume"
    rm -rf ${volume}

    cd $RUNNING_DIR > /dev/null 2>&1
    cp /tmp/${volume}.tar $output
    docker rm $CID > /dev/null 2>&1
done

Khi bạn chạy xong script, sẽ có 3 file tar được tạo ra tương ứng với 3 volumes của docker-compose này.

Khi bạn cần restore thì chỉ cần chạy script này và trỏ tới thư mục chứa 3 file tar là được:

#!/bin/bash
echo "============================================================"
echo "# Restore wordpress - mysql volume                         #"
echo "# All tar backup files should be located on same directory #"
echo "# Should deploy container first                            #"
echo "# Usage:                                                   #"
echo "# ./restore.sh -i <input_directory>                        #"
echo "============================================================"

WORK_DIR=`dirname $(readlink -f $0)`
RUNNING_DIR=$PWD
declare -a volumes
volumes=(wp_data db_data db_config)

while getopts i: flag
do
    case "${flag}" in
        i) input=${OPTARG};;
    esac
done

is_docker_installed() {
    docker ps > /dev/null 2>&1
}

is_docker_compose_installed() {
    docker-compose version > /dev/null 2>&1
}

is_volume_exists() {
    docker volume inspect $1 > /dev/null 2>&1
}

is_docker_installed
if [[ $? -ne 0 ]]; then
    echo "Can not run docker command"
    echo "Skipped backup process..."
    exit 0
fi
if [[ ! -d ${input} ]]; then
    echo "Input directory does not exists - Skipped..."
    exit 0
fi
     
cd $input
for volume in "${volumes[@]}"; do 
    is_volume_exists $volume
    if [[ $? -ne 0 ]]; then
        echo "${volume} volume is not exists"
        echo "Skipped restore process..."
        exit 0
    fi
    
    if [[ -f ${volume}.tar ]]; then
        mkdir $volume > /dev/null 2>&1
        tar xvf ${volume}.tar -C ./${volume} > /dev/null 2>&1
        CID=$(docker run -d -v ${volume}:/${volume} busybox true)
        docker cp ./${volume} ${CID}:/
        rm -rf ./${volume}
        docker rm $CID > /dev/null 2>&1
        echo "Restored ${volume}"
    else
        echo "${volume}.tar does not exists - Skipped..."
    fi
done
cd $WORK_DIR/..
docker-compose down
docker-compose up -d
cd $RUNNING_DIR

Xóa WordPress hiện tại

Đôi lúc buồn đời quá, muốn xóa hết tất cả container thì sao nhỉ? Đã có destroy script, cái này khuyến khích chạy khi container test thử script nha, bạn mà lỡ may chạy script này khi WordPress đang prod thì xác định ăn cám 😛

#!/bin/bash
echo "======================================="
echo "# Destroy wordpress - mysql container #"
echo "======================================="
 
while true; do
    read -p "Do you want to destroy all wordpress container? (y/N) " yn
    case $yn in
        [Yy]* ) break;;
        [Nn]* ) exit;;
        *) exit;;
    esac
done

WORK_DIR=`dirname $(readlink -f $0)`

declare -a volumes
volumes=(wp_data db_data db_config)

is_docker_installed() {
    docker ps > /dev/null 2>&1
}

is_docker_compose_installed() {
    docker-compose version > /dev/null 2>&1
}

is_volume_exists() {
    docker volume inspect $1 > /dev/null 2>&1
}

is_docker_installed
if [[ $? -ne 0 ]]; then
    echo "Can not run docker command"
    echo "Skipped destroy process..."
    exit 0
fi
is_docker_compose_installed
if [[ $? -ne 0 ]]; then
    echo "Can not run docker-compose command"
    echo "Skipped destroy process..."
    exit 0
fi

cd $WORK_DIR/..
docker-compose down
cd $RUNNING_DIR

for volume in "${volumes[@]}"; do 
    is_volume_exists $volume
    if [[ $? -eq 0 ]]; then
        docker volume rm $volume > /dev/null 2>&1
        echo "Removed $volume volume"
    fi
done

Lời kết

Bài viết này chỉ là một tips nhỏ để bạn triển khai WordPress một cách hiệu quả hơn, có thể dễ dàng viết thêm vài script để tự động triển khai hoặc backup dữ liệu sang một chỗ khác để đảm bảo dữ liệu của bạn luôn được toàn vẹn.

Bạn có thể tham khảo thêm ở Github Repository

Chúc các bạn một ngày làm việc tốt lành


4.8 4 votes
Article Rating
guest
3 Comments
Inline Feedbacks
View all comments
Vô Danh
Vô Danh
10 months ago

Rất hay và bổ ích, cảm ơn admin

Lucy
Lucy
10 months ago

Cám ơn bạn đã chia sẻ