Deploying WordPress – Part I: Version Controlling WordPress with Git

Deploying WordPress – Part I: Version Controlling WordPress with Git

ตอนนี้มีโครงการจะทำบล็อกโดยใช้ WordPress สำหรับขั้นตอนในการทำถ้าเป็นเมื่อก่อนก็ติดตั้งระบบปฏิบัติการ ฐานข้อมูล และเว็บเซิร์ฟเวอร์เสร็จก็ดาวน์โหลด WordPress มาติดตั้ง  คลิกเมาส์ไม่กี่ครั้งก็ได้บล็อกมาใช้งานแล้ว และส่วนใหญ่สิ่งที่ทำหลังจากติดตั้งก็คือดาวน์โหลดธีม รวมถึงปลักอินที่ต้องการ ถ้าหากต้องมีการแก้ไขอะไรก็ทำในเซิร์ฟเวอร์นั่นล่ะ

ลองไปไล่อ่านดูว่าคนอื่นเค้ามีขบวนการจัดการและพัฒนาบล็อกอย่างไรก็พบว่า ส่วนใหญ่ใช้ version control system อย่าง Git เข้ามาช่วยในการจัดการซอร์ซโค้ดของปลักอินและเทมเพลต นอกจากนั้นเห็นหลายคนยังใช้เครื่องมือหลายๆตัวมาช่วยในขบวนการ deploy WordPress อีกด้วย Git มาจัดการ WordPress โดยเน้นที่การจัดการซอร์ซโค้ดของปลักอินและเทมเพลต ส่วนซอร์ซโค้ดหลักของ WordPress จะไม่ถูกแก้ไข การใช้ version control system เข้ามาจัดการซอร์ซโค้ดมีประโยชน์หลายอย่าง เช่น

  • สามารถแก้ไขซอร์ซโค้ดของโครงการร่วมกันกับทีมพัฒนาหลายๆคนได้ การทำงานร่วมกันหลายคนบนซอร์ซโค้ดเดียวกันจำเป็นต้องมี workflow โดยสามารถลองศึกษาได้จากบทความ Simple Git workflow is simple
  • ง่ายต่อการอ้างอิงเวอร์ชันต่างๆของซอร์ซโค้ด เนื่องจากมีที่เก็บซอร์ซโค้ดที่ตกลงกันอย่างเป็นทางการภายในทีมพัฒนา
  • เป็นการสำรองข้อมูลของซอร์ซโค้ดไปในตัว
  • สามารถติดตามประวัติของการเปลี่ยนแปลง รวมถึงสามารถกู้คืนซอร์ซโค้ดได้ในกรณีเกิดความผิดพลาดที่ไม่คาดคิด

เอาล่ะมาเริ่มกันเลย

โครงสร้างพื้นฐานของ Git repository

เราจะเริ่มจากการสร้างโครงสร้างพื้นฐานของ Git repository กันก่อน สมมติว่าเราจะเก็บซอร์ซโค้ดของ WordPress ไว้ในไดเรกทอรี mysite และเราจะสร้าง git repository เปล่าๆไว้ในนั้น

$ mkdir mysite && cd mysite
$ git init
$ touch README.md
$ git add README.md
$ git commit -m "Initial commit."

จากนั้นสร้าง submodule สำหรับ WordPress

$ git submodule add git://github.com/WordPress/wordpress.git
$ git commit -m "Add wordpress submodule."
$ cd wordpress
$ git checkout 3.8.1
$ cd ..
$ git commit -am "Checkout latest wordpress version"

เราสามารถใช้คำสั้ง git tag เพื่อดูว่าเวอร์ชันล่าสุดของ WordPress คือเวอร์ชันอะไร โดยในที่นี้คือเวอร์ชัน 3.8.1

คัดลอกไดเรกทอรี wp-content และไฟล์ที่สำคัญออกมานอก wordpress

ในขั้นต่อไปเราจะทำการคัดลอกไดเรกทอรี “wp-content” ออกมาจากไดเรกทอรี wordpress ซึ่งจะอยู่ใน root ของ git repository

$ cp wordpress/wp-config-sample.php wp-config.php
$ cp wordpress/index.php .
$ cp -R wordpress/wp-content .
$ git add .
$ git commit -m "Moving config and content outside the submodule"

แก้ไขไฟล์ index.php และ wp-config.php เพื่อให้สามารถทำงานนอกไดเรกทอรี wordpress ได้

แก้ไขไฟล์ index.php

require( dirname( __FILE__ ) . '/wp-blog-header.php' );

เป็น

require( dirname( __FILE__ ) . '/wordpress/wp-blog-header.php' );

จากนั้นแก้ไขไฟล์ wp-config.php จากเดิม

// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', 'database_name_here');

/** MySQL database username */
define('DB_USER', 'username_here');

/** MySQL database password */
define('DB_PASSWORD', 'password_here');

/** MySQL hostname */
define('DB_HOST', 'localhost');

/** Database Charset to use in creating database tables. */
define('DB_CHARSET', 'utf8');

/** The Database Collate type. Don't change this if in doubt. */
define('DB_COLLATE', '');

เป็น

if ( file_exists( dirname( __FILE__ ) . '/wp-config-production.php' ) ) {
  include( dirname( __FILE__ ) . '/wp-config-production.php' );
} else {
  define( 'WP_LOCAL_DEV', true ); // We'll talk about this later

  // ** MySQL settings - You can get this info from your web host ** //
  /** The name of the database for WordPress */
  define('DB_NAME', 'database_name_here');

  /** MySQL database username */
  define('DB_USER', 'username_here');

  /** MySQL database password */
  define('DB_PASSWORD', 'password_here');

  /** MySQL hostname */
  define('DB_HOST', 'localhost');

  /** Database Charset to use in creating database tables. */
  define('DB_CHARSET', 'utf8');

  /** The Database Collate type. Don't change this if in doubt. */
  define('DB_COLLATE', '');
}

/* defined after managed by git */
define('WP_SITEURL', 'http://' . $_SERVER['SERVER_NAME'] . '/wordpress');
define('WP_HOME',    'http://' . $_SERVER['SERVER_NAME']);
define('WP_CONTENT_DIR', $_SERVER['DOCUMENT_ROOT'] . '/wp-content');
define('WP_CONTENT_URL', 'http://' . $_SERVER['SERVER_NAME'] . '/wp-content');

ซอร์ซโค้ดด้านบนสามารถใช้ได้ทั้งบนเครื่องที่ใช้ในการพัฒนาและ เซิร์ฟเวอร์ production ถ้าหากนำซอร์ซโค้ดนี้มาใช้ในเครื่องสำหรับพัฒนาก็ไม่จำเป็นต้องใส่ไฟล์ wp-config-production.php เข้ามา และสามารถแก้ไข username password และ host ของฐานข้อมูลในไฟล์ wp-config.php ได้เลย แต่ถ้าหากใช้ในเซิร์ฟเวอร์ production ก็ต้องใส่ไฟล์ wp-config-production.php เข้าไปด้วย WordPress จะใช้ค่า username password และ host ของฐานข้อมูล จากไฟล์ wp-config-production.php แทน

เมื่อแก้ไขไฟล์ wp-config.php เสร็จแล้ว จากนั้นเพิ่มไฟล์ทั้งหมดเข้าไปใน repository และ commit การเปลี่ยนแปลง

$ git add .
$ git commit -m "define correct paths in config files"

ซอร์ซโค้ดด้านล่างเป็นตัวอย่างของไฟล์ wp-config-production.php ซึ่งจะไม่ถูกเก็บไข้าไปใน repository การสร้างไฟล์นี้อาจจะทำโดยเก็บไว้ในที่ปลอดภัย และคัดลอกเข้าไปในเซิร์ฟเวอร์ production หลังจาก deploy หรือสร้างขึ้นอัตโนมัติขณะทำการ deploy WordPress ก็ได้ ซึ่งจะได้กล่าวถึงในตอนต่อไป

<?php
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', 'wordpress');

/** MySQL database username */
define('DB_USER', 'root');

/** MySQL database password */
define('DB_PASSWORD', 'root');

/** MySQL hostname */
define('DB_HOST', 'localhost');

/** Database Charset to use in creating database tables. */
define('DB_CHARSET', 'utf8');

/** The Database Collate type. Don't change this if in doubt. */
define('DB_COLLATE', '');
?>

กำหนดว่าจะเก็บหรือไม่เก็บไฟล์อะไรบ้างใน repository โดยใช้ gitignore

ในเครื่องที่ใช้สำหรับพัฒนา บางครั้งจะเกิดไฟล์ที่เกิดจากการทดสอบ ซึ่งอยู่ใน local repository ยกตัวอย่างเช่น ไดเรกทอรีสำหรับเก็บรูปภาพที่อัพโหลด ไฟล์พวกนี้เราไม่ต้องการที่จะเก็บเข้าใน repository ด้วย เราสามารถใช้ gitignore เพื่อสร้างกฏว่าจะเก็บหรือไม่เก็บไฟล์อะไรบ้างใน repository ได้ โดยกฏจะเก็บอยู่ในไฟล์ .gitignore ภายใต้ root ของ repository ซึ่งในที่นี้คือ mysite/.gitignore ยกตัวอย่างเช่น

# Ignore everything in the root except the "wp-content" directory, file ".gitignore", "README.md", "index.php" and "wp-config.php".
/*
!.gitignore
!README.md
!index.php
!wp-config.php
!wp-content/

# Ignore everything in the "wp-content" directory, except the "plugins"
# and "themes" directories.
wp-content/*
!wp-content/plugins/
!wp-content/themes/

# Ignore everything in the "plugins" directory, except the plugins you
# specify (see the commented-out examples for hints on how to do this.)
wp-content/plugins/*
!wp-content/plugins/my-single-file-plugin.php
!wp-content/plugins/my-directory-plugin/

# Ignore everything in the "themes" directory, except the themes you
# specify (see the commented-out example for a hint on how to do this.)
wp-content/themes/*
!wp-content/themes/my-theme/

ความหมายของ gitignore ด้านบนคือ

ไม่เก็บทุกอย่างภายใต้ root ยกเว้นไดเรกทอรี “wp-content” และไฟล์ตามรายเชื่อต่อไปนี้ “.gitignore” “README.md” “index.php” และ “wp-config.php”

ไม่เก็บทุกอย่างภายใต้ไดเรกทอรี “wp-content” ยกเว้นไดเรกทอรี “plugins” และ “themes”

ไม่เก็บทุกอย่างภายใต้ไดเรกทอรี “plugins” ยกเว้นปลักอินที่เรากำหนด ซึ่งอาจเป็นปลักอินที่เราต้องการใช้ใน WordPress หรือปลักอินที่เรากำลังพัฒนา ซึ่งจากตัวอย่างคือไฟล์ “my-single-file-plugin.php” และไดเรกทอรี “my-directory-plugin”

ไม่เก็บทุกอย่างภายใต้ไดเรกทอรี “themes” ยกเว้นธีมที่เรากำหนด ซึ่งอาจจะเป็นธีมภายนอกที่เราใช้กับบล็อกหรือเป็นธีมที่เรากำลังพัฒนาก็ได้ ซึ่งจากตัวอย่างคือไดเรกทอรี “my-theme”

จากนั้นเพิ่งไฟล์ .gitignore เข้าไปใน repository

$ git add .gitignore
$ git commit -m "Add .gitignore file"

การเก็บซอร์ซโค้ดใน remote repository

จากนั้นทำการเก็บซอร์ซโค้ดใน remote repository ซึ่งจากตัวอย่างใช้บริการของ github โดยในขั้นแรกให้ทำการสร้าง repository ชื่อ mysite

Screen Shot 2557-03-19 at 11.23.32 AM

กลับมาที่หน้าจอของ local repository ทำการกำหนด remote repository โดยใช้คำสั่ง

$ git remote add origin https://github.com/<user>/mysite.git

<user> ในแต่ละคนจะไม่เหมือนกัน ทาง github จะบอก URL ของ repository ให้ดูหลังจากกดปุ่ม “Create repository”

จากนั้นทำการส่งซอร์ซโค้ดไปเก็บใน remote repository โดยใช้คำสั่ง

$ git push -u origin master

github จะถาม username และ password เมื่อใส่ค่าที่ถูกต้อง ซอร์ซโค้ดก็จะถูกส่งไปเก็บใน remote repository

Username for 'https://github.com': johndoe
Password for 'https://johndoe@github.com':
Counting objects: 339, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (327/327), done.
Writing objects: 100% (339/339), 3.13 MiB | 70.00 KiB/s, done.
Total 339 (delta 81), reused 0 (delta 0)
To https://github.com/johndoe/mysite.git
 * [new branch] master -> master
Branch master set up to track remote branch master from origin.

การอัพเดท WordPress

ถ้าหากในอนาคต  WordPress ออกเวอร์ชันใหม่ เช่นออกเวอร์ชัน 3.8.2 เราสามารถอัพเดท  WordPress โดยใช้คำสั่ง

$ cd wordpress
$ git fetch --tags
$ git checkout 3.8.2 # switch to the 3.8.2 branch
$ cd ..
$ git commit -m "Update WordPress to version 3.8.2"

การ Deploy WordPress ในเซิร์ฟเวอร์ production

การบวนการ deploy เป็นกระบวนการที่ทำได้หลายวิธี อยู่ที่ความต้องการ โดยแต่ละวิธีก็จะมีความซับซ้อนต่างกันด้วย ในบทความนี้จะใช้ git ในการ deploy ซอร์ซโค้ดไปที่ เซิร์ฟเวอร์ production แต่อย่างไรก็ตามวิธีนี้ยังมีข้อจำกัดในเรื่องของการจัดการฐานข้อมูล ถ้าหากการ deploy ของเราต้องเกี่ยวข้องกับฐานข้อมูล เช่นต้องสามารถ backup หรือ rollback ได้ ลำพังวิธีที่ใช้ git ในการ deploy จะยังไม่เพียงพอ แต่ถ้ามีการแก้ไขเฉพาะธีม หรือปลักอิน ที่ไม่ได้ไปยุ่งเกี่ยวกับฐานข้อมูลมาก วิธีนี้ถือว่าเป็นวิธีที่ใช้ได้ดีเลยทีเดียว

เราสามารถใช้เครื่องมืออื่นๆมาช่วยในการ deploy WordPress ให้มีประสิทธิภาพและความยืดหยุ่นมากขึ้นได้ ซึ่งจะได้กล่าวถึงในตอนต่อไป

การ deploy  นั้นเริ่มจากการติดตั้งระบบปฏิบัติการ ติดตั้ง PHP และ MySQL ซึ่งจะไม่ขอกล่าวถึงในที่นี้นะครับ เพราะจะทำให้บทความยาวเกินไป สมมติว่าเราติดตั้งทุกอย่างพร้อมใช้งานแล้ว ให้เข้าไปที่หน้ารอของ เซิร์ฟเวอร์ production

สมมติว่าเซิร์ฟเวอร์ production อยู่ที่ IP 192.168.1.2 เราสามารถเข้าไปในเซิร์ฟเวอร์โดยใช้โปรโตคอล ssh เมื่อเข้าไปแล้วให้สร้างไดเรกทอรีชื่อ repos/mysite จากนั้นสร้าง git repository เปล่าๆขึ้นมา

$ ssh user@192.168.1.2
$ mkdir -p repos/mysite && cd repos/mysite
$ git --bare init

จากนั้นสร้างไฟล์ post-receive ซึ่งอยู่ในไดเรกทอรี hooks อีกที

$ vim hooks/post-receive

สมมติว่า document root ของเว็บเซิร์ฟเวอร์ อยู่ที่ /var/www/localhost/htdocs ให้ใส่ข้อมูลในไฟล์ post-receive ตามด้านล่าง

#!/bin/sh
GIT_WORK_TREE=/var/www/localhost/htdocs git checkout -f

กำหนดสิทธิ์ให้ไฟล์ post-receive สามารถถูก excute ได้ โดยใช้คำสั่ง

$ sudo chmod +x hooks/post-update

อย่าลืมว่าต้องทำให้ user ของเราต้องมีสิทธิ์เขียนไดเรกทอรี /var/www/localhost/htdocs ได้ โดยใช้คำสั่ง 

$sudo chown -R user /var/www/localhost

กลับไปที่เครื่องที่ใช้พัฒนา ใน repository ซึ่งอยู่ในไดเรกทอรี mysite ของเรา ให้ทำการสร้าง alias ของ remote repository ชื่อ production ขึ้นมาโดยชี้ไปที่ remote repository บนเซิร์ฟเวอร์ production

$ git remote add production ssh://user@192.168.1.2/~/repos/mysite

ทำการ push master branch เข้าไปในเซิร์ฟเวอร์ production ด้วยคำสั่ง

$ git push production +master:refs/heads/master

ถ้าหากมีการเปลี่ยนแปลงซอร์ซโค้ด และต้องการ push ไปที่เซิร์ฟเวอร์ production ก็สามารถทำได้โดยใช้คำสั่ง

$ git push production

ถ้าทำทุกอย่างถูกต้องเราจะเห็นซอร์ซโค้ดถูกคัดลอกเข้าไปอยู่ใน document root ของเว็บเซิร์ฟเวอร์

$ ls -l /var/www/localhost/htdocs/
total 20
-rw-rw-r-- 1 nontster nontster 24 Mar 19 15:47 README.md
-rw-rw-r-- 1 nontster nontster 428 Mar 19 15:38 index.php
drwxrwxr-x 2 nontster nontster 4096 Mar 19 15:38 wordpress
-rw-rw-r-- 1 nontster nontster 3618 Mar 19 15:47 wp-config.php
drwxrwxr-x 4 nontster nontster 4096 Mar 19 15:38 wp-content

เราต้องทำการคัดลอกไฟล์ wp-config-production.php เข้าไปใน document root ของเว็บเซิร์ฟเวอร์ ซึ่งในที่นี้คือไดเรกทอรี /var/www/localhost/htdocs เสียก่อน และสำหรับการใช้งาน WordPress ครั้งแรกจะต้องทำการติดตั้ง WordPress โดยผู้ใช้จะถูก redirect ไปที่หน้า install WordPress เพื่อใส่ข้อมุลที่จำเป็น ก่อนที่ WordPress จะพร้อมใช้งาน

ในตอนหน้าจะลองมาปรับปรุงขบวนการ deploy WordPress ให้มีประสิทธิภาพมากขึ้นโดยการใช้ Capistrano และ WP CLI

2 คิดบน “Deploying WordPress – Part I: Version Controlling WordPress with Git

  1. Pingback: Deploying WordPress – Part 2: Deploying WordPress with Capistrano | WHO, WHAT, WHERE, WHEN, WHY, HOW ?

ใส่ความเห็น

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / เปลี่ยนแปลง )

Twitter picture

You are commenting using your Twitter account. Log Out / เปลี่ยนแปลง )

Facebook photo

You are commenting using your Facebook account. Log Out / เปลี่ยนแปลง )

Google+ photo

You are commenting using your Google+ account. Log Out / เปลี่ยนแปลง )

Connecting to %s