ติดตั้งและใช้ Docker
ในบทความ ออกแบบฐานข้อมูล Simple bank เราได้เรียนรู้วิธีการออกแบบฐานข้อมูล schema ด้วย dbdiagram.io
ในบทความนี้เราจะมาเรียนรู้วิธีติดตั้ง Docker Desktop บนเครื่อง local จากนั้นดาวน์โหลดและเริ่มต้นคอนเทนเนอร์ PostgreSQL
Docker คือ engine ตัวหนึ่งที่มีการทำงานในลักษณะจำลองสภาพแวดล้อมขึ้นมาบนเครื่อง server เพื่อใช้ในการ run service ที่ต้องการ มีการทำงานคล้ายคลึงกับ Virtual Machine เช่น VMWare, VirtualBox, XEN, KVM
นอกจากนี้เรายังจะได้เรียนรู้วิธีตั้งค่าและใช้ TablePlus เพื่อเชื่อมต่อและโต้ตอบกับ Postgres และใช้เพื่อเรียกใช้สคริปต์ SQL ที่เราสร้างขึ้นในครั้งก่อนเพื่อสร้างสคีมาฐานข้อมูลของ Simple Bank
ติดตั้ง Docker Desktop
เริ่มต้นด้วย ติดตั้ง PowerShell แล้ว ติดตั้ง docker ตามบทความนี้
Pull Postgres image
ในบทความนี้ เราจะใช้ PostgreSQL เป็นกลไกจัดการฐานข้อมูลสำหรับแอปของเรา ไปที่ Docker Hub เพื่อค้นหา image
ค้นหา Postgres มีหลายผลลัพธ์ แต่เราจะใช้อันแรกเพราะเป็นอิมเมจ Postgres อย่างเป็นทางการ
ดังที่คุณเห็นที่นี่ เราสามารถเรียกใช้ docker pull postgres เพื่อรับภาพนี้ การดำเนินการนี้จะดึง image ที่มีแท็กล่าสุด ในกรณีนี้คือเวอร์ชัน 12
มีรุ่นอื่น ๆ อีกมากมายที่มีแท็กต่างกันเช่นกัน เรามักใช้ภาพอัลไพน์ เนื่องจากมีขนาดเล็กมาก ด้วยการกระจายลินุกซ์แบบอัลไพน์น้ำหนักเบา
มาเปิดเทอร์มินัล PowerShell แล้วเรียกใช้คำสั่ง:
docker pull postgres:12-alpine
Docker environment variable
เรายังปรับแต่งคอนเทนเนอร์ได้ด้วยการเปลี่ยนตัวแปรสภาพแวดล้อมบางส่วน
ตัวอย่างเช่น ด้วยตัวแปร POSTGRES_USER เราสามารถตั้งค่าชื่อผู้ใช้ของ superuser เพื่อเข้าสู่ระบบ Postgres หากไม่ได้ระบุไว้ ชื่อผู้ใช้เริ่มต้น: postgres จะถูกใช้
ในทำนองเดียวกัน ตัวแปร POSTGRES_DB ช่วยให้เราสามารถตั้งชื่อฐานข้อมูลเริ่มต้น ซึ่งจะถูกสร้างขึ้นเมื่อคอนเทนเนอร์เริ่มทำงาน มิฉะนั้น ชื่อฐานข้อมูลดีฟอลต์จะเหมือนกับ POSTGRES_USER
เอาล่ะ เรามาเรียกใช้คำสั่งนี้ในเทอร์มินัลกัน:
docker run --name postgres12 -e POSTGRES_USER=root -e POSTGRES_PASSWORD=secret -d postgres:12-alpine
- ที่นี่ใช้ชื่อ image คือ postgres:12-alpine เพราะเราต้องการเรียกใช้ Postgres เวอร์ชันเฉพาะนี้
- สำหรับ password ใช้ secret
- จากนั้นตั้งชื่อ superuser เป็น root ด้วยตัวแปรสภาพแวดล้อม POSTGRES_USER
- ใช้ postgres12 เป็นชื่อของคอนเทนเนอร์
สุดท้าย อาร์กิวเมนต์ที่สำคัญอย่างหนึ่งที่เราต้องเพิ่มให้กับคำสั่งนี้คือการทำ port mapping
Docker port mapping
นั่นหมายความว่าอย่างไร?
โดยทั่วไป คอนเทนเนอร์ docker จะทำงานในเครือข่ายเสมือนที่แยกจากกัน ซึ่งแตกต่างจากเครือข่ายโฮสต์ที่เราใช้งานอยู่
ดังนั้นเราจึงไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์ Postgres ที่ทำงานบนพอร์ต 5432 ของเครือข่ายคอนเทนเนอร์ได้ เว้นแต่เราจะบอกให้นักเทียบท่าสร้าง “bridge” ประเภทใดประเภทหนึ่งระหว่างเครือข่าย localhost ของเรากับเครือข่ายของคอนเทนเนอร์
เราทำโดยใช้แฟล็ก -p จากนั้นระบุพอร์ตของเครือข่ายโฮสต์ ตามด้วยโคลอน จากนั้นจึงระบุพอร์ตที่เกี่ยวข้องของคอนเทนเนอร์ พวกเขาไม่จำเป็นต้องเหมือนกัน แต่ฉันมักใช้พอร์ตเดียวกันเพื่อให้จำได้ง่ายขึ้น
docker run --name postgres12 -e POSTGRES_USER=root -e POSTGRES_PASSWORD=secret -p 5432:5432 -d postgres:12-alpine
ตอนนี้เมื่อเรากด Enter Docker จะเริ่มคอนเทนเนอร์ Postgres และส่งคืน ID ที่ไม่ซ้ำกันแบบยาว เราสามารถแสดงรายการคอนเทนเนอร์ที่รันอยู่ทั้งหมดด้วยคำสั่ง
docker ps
- ดังที่คุณเห็นที่นี่ ID คอนเทนเนอร์นี้เป็นคำนำหน้าสั้น ๆ ของคำนำหน้าแบบยาวที่ docker desktop ส่งคืนในคำสั่งก่อนหน้า
- ชื่อภาพคือ postgres พร้อมแท็ก 12-alpine ถ้าเรารัน docker images เราจะเห็นว่ามันเป็นอิมเมจเดียวกันกับที่เราเคยดึงมาก่อนด้วยคำสั่ง docker pull
- มีข้อมูลเพิ่มเติมหลายอย่าง เช่น เวลาที่สร้างของคอนเทนเนอร์ หรือสถานะของคอนเทนเนอร์
- และการแมปพอร์ตอย่างที่เราคาดไว้ก็คือการแมปพอร์ต 5432 บน localhost กับพอร์ตเดียวกันในคอนเทนเนอร์
- และสุดท้ายคือชื่อคอนเทนเนอร์ ซึ่งก็คือ postgres12 ตามที่เราตั้งค่าไว้ในคำสั่ง docker run
Access Postgres console
ตกลง ตอนนี้เซิร์ฟเวอร์ Postgres พร้อมแล้ว มาลองเชื่อมต่อและเข้าถึงคอนโซลของเซิร์ฟเวอร์กัน
เราสามารถทำได้ด้วยคำสั่ง docker exec ช่วยให้เราสามารถเรียกใช้คำสั่งเฉพาะได้ 1 คำสั่งภายในคอนเทนเนอร์ที่กำลังทำงานอยู่
docker exec -it postgres12 psql -U root
- เราใช้แฟล็ก -it เพื่อบอกให้นักเทียบท่ารันคำสั่งเป็นเซสชัน TTY แบบโต้ตอบ
- จากนั้นเราระบุชื่อคอนเทนเนอร์ ซึ่งก็คือ postgres12
- และสุดท้ายคือคำสั่งที่เราต้องการเรียกใช้ภายใน postgres12 ในกรณีนี้ เราต้องการเรียกใช้คำสั่ง psql เพื่อเข้าถึงคอนโซล Postgres และเราใช้แฟล็ก -U ที่นี่เพื่อบอก psql ว่าเราต้องการเชื่อมต่อกับผู้ใช้ root
และตอนนี้เราอยู่ในคอนโซล Postgres แล้ว
สิ่งหนึ่งที่คุณอาจสังเกตเห็นที่นี่คือ Postgres ไม่ขอรหัสผ่าน แม้ว่าเราจะตั้งค่าไว้เมื่อเรียกใช้คอนเทนเนอร์ เป็นเพราะโดยค่าเริ่มต้น คอนเทนเนอร์ Postgres จะตั้งค่าการพิสูจน์ตัวตนที่เชื่อถือได้ในเครื่อง ดังนั้นจึงไม่จำเป็นต้องใช้รหัสผ่านเมื่อเชื่อมต่อจาก localhost (ภายในคอนเทนเนอร์)
เราสามารถลองใช้แบบสอบถามง่ายๆ เช่น
select now()
เพื่อรับเวลาปัจจุบัน และออกจากคอนโซลโดย
\q
View container logs
อีกสิ่งหนึ่ง ที่นี่คือการแสดงบันทึกของคอนเทนเนอร์
เราใช้คำสั่ง docker logs ตามด้วยชื่อคอนเทนเนอร์ คุณสามารถใช้ ID เฉพาะของคอนเทนเนอร์ได้เช่นกัน
docker logs postgres12
ด้วยวิธีนี้ เราสามารถตรวจสอบสิ่งที่เกิดขึ้นภายในคอนเทนเนอร์ของแอปได้อย่างง่ายดาย
เอาล่ะ ตอนนี้คุณรู้วิธีใช้คำสั่งนัก docker พื้นฐานเพื่อโต้ตอบกับคอนเทนเนอร์ Postgres และเข้าถึงคอนโซลเพื่อเรียกใช้คำสั่ง SQL
ติดตั้ง Table Plus
แสดงวิธีอื่นที่ง่ายกว่าในการจัดการและเล่นกับฐานข้อมูลโดยใช้ Table Plus
Table Plus เป็นเครื่องมือ GUI ที่สามารถพูดคุยกับกลไกฐานข้อมูลประเภทต่างๆ เช่น PostgreSQL, MySQL, Mongo, Redis เป็นต้น ใช้งานง่ายมากและจะช่วยให้เราพัฒนาได้เร็วขึ้นมาก ไปที่ tableplus.com เพื่อดาวน์โหลด
Create a new connection
ตอนนี้เรามาเปิดแอปกัน ยังไม่มีการเชื่อมต่อ db มาสร้างใหม่
มีตัวเลือกกลไกฐานข้อมูลมากมาย แต่ในกรณีของเรา เราใช้ PostgreSQL
- ตอนนี้เราป้อนชื่อของการเชื่อมต่อ โดยจะเรียกมันว่า postgres12
- โฮสต์คือ localhost (หรือ 127.0.0.1) และพอร์ตคือ 5432 โดยค่าเริ่มต้น
- ชื่อผู้ใช้คือ root และรหัสผ่านเป็น secret เนื่องจากเรากำหนดค่าเมื่อรันคอนเทนเนอร์ postgres
- ชื่อฐานข้อมูลเริ่มต้นคือ root เช่นเดียวกับชื่อผู้ใช้ เนื่องจากเราไม่ได้กำหนดค่าไว้อย่างชัดเจนเมื่อเริ่มต้นคอนเทนเนอร์
มาคลิก Connect ทดสอบเพื่อทดสอบการเชื่อมต่อกัน
ตอนนี้เราสามารถคลิก เชื่อมต่อ เพื่อเชื่อมต่อกับเซิร์ฟเวอร์ฐานข้อมูล
ขณะนี้ทุกอย่างว่างเปล่าเนื่องจากเรายังไม่ได้สร้างสคีมา แต่เรายังคงสามารถเรียกใช้คิวรีบางรายการได้โดยคลิกที่ไอคอน SQL
แล้วลองเขียนคำสั่ง
select now();
จากนั้นคลิกปุ่ม Run current ผลลัพธ์จะปรากฏ วันที่และ เวลา ในส่วนด้านล่าง
Create Simple Bank schema
ตอนนี้ มาเปิดไฟล์ Simple_bank.sql ที่เราได้สร้างขึ้นในการสร้างจากบทความ ออกแบบฐานข้อมูล Simple bank จากนั้นเลือกคลุมข้อมูลทั้งหมดในไฟล์นี้ แล้วกด Run current เพื่อเรียกใช้
ตอนนี้เมื่อเรากดปุ่ม refresh เพื่อรีเฟรช จะเห็นตาราง 3 ตารางที่แสดงทางด้านซ้าย คือ: accounts, entries และ transfers
เราสามารถคลิกที่ชื่อเพื่อดูข้อมูลหรือเลือกแท็บ Structure เพื่อดูโครงสร้างสคีมา
มีข้อมูลที่เป็นประโยชน์มากมาย เช่น name, data type, default value, foreign key, is nullable หรือไม่
สมมุติว่าคอลัมน์ Foreign Key บางคอลัมน์จะเป็น nullable ซึ่งไม่ใช่สิ่งที่เราต้องการจริงๆ เพราะทุกรายการหรือการโอนจะต้องเชื่อมโยงกับบัญชีของพวกเขา
ไปที่ dbdiagram.io เพื่อแก้ไขปัญหานี้
Fix schema definition
โดยจะเพิ่มข้อ not null ที่ไม่เป็นค่าว่างลงในคอลัมน์ account_id ของตารางรายการ และคอลัมน์ from_account_id และ to_account_id ของตาราง transfers จากนั้นส่งออกไปยัง PostgreSQL
Table accounts as A {
id bigserial [pk]
owner varchar [not null]
balance bigint [not null]
currency varchar [not null]
created_at timestamptz [not null, default: `now()`]
Indexes {
owner
}
}
Table entries {
id bigserial [pk]
account_id bigint [ref: > A.id, not null]
amount bigint [not null, note: 'can be negative or positive']
created_at timestamptz [not null, default: `now()`]
Indexes {
account_id
}
}
Table transfers {
id bigserial [pk]
from_account_id bigint [ref: > A.id, not null]
to_account_id bigint [ref: > A.id, not null]
amount bigint [not null, note: 'must be positive']
created_at timestamptz [not null, default: `now()`]
Indexes {
from_account_id
to_account_id
(from_account_id, to_account_id)
}
}
ตอนนี้เรามาลบไฟล์เก่า ด้วยการเปิดด้วย Table Plus แล้วเลือกทั้งหมด 3 ตารางนี้ คลิกขวาและเลือก Delete…
เลือก Cascade เพื่อให้แน่ใจว่าข้อมูลอ้างอิงทั้งหมดจะถูกลบออก จากนั้นคลิก Ok
ตอนนี้ตารางยังคงอยู่ แต่มีเครื่องหมายเป็นสีแดง ให้กด Ctrl + S เพื่อบันทึกสถานะนี้ แล้วคำสั่ง DELETE TABLE จะถูกดำเนินการ และตารางทั้งหมดจะหายไป
ตกลง ตอนนี้ ให้เลือกคลุมข้อมูลทั้งหมดในไฟล์ Simple_bank.sql ใหม่นี้
CREATE TABLE "accounts" (
"id" bigserial PRIMARY KEY,
"owner" varchar NOT NULL,
"balance" bigint NOT NULL,
"currency" varchar NOT NULL,
"created_at" timestamptz NOT NULL DEFAULT (now())
);
CREATE TABLE "entries" (
"id" bigserial PRIMARY KEY,
"account_id" bigint NOT NULL,
"amount" bigint NOT NULL,
"created_at" timestamptz NOT NULL DEFAULT (now())
);
CREATE TABLE "transfers" (
"id" bigserial PRIMARY KEY,
"from_account_id" bigint NOT NULL,
"to_account_id" bigint NOT NULL,
"amount" bigint NOT NULL,
"created_at" timestamptz NOT NULL DEFAULT (now())
);
ALTER TABLE "entries" ADD FOREIGN KEY ("account_id") REFERENCES "accounts" ("id");
ALTER TABLE "transfers" ADD FOREIGN KEY ("from_account_id") REFERENCES "accounts" ("id");
ALTER TABLE "transfers" ADD FOREIGN KEY ("to_account_id") REFERENCES "accounts" ("id");
CREATE INDEX ON "accounts" ("owner");
CREATE INDEX ON "entries" ("account_id");
CREATE INDEX ON "transfers" ("from_account_id");
CREATE INDEX ON "transfers" ("to_account_id");
CREATE INDEX ON "transfers" ("from_account_id", "to_account_id");
COMMENT ON COLUMN "entries"."amount" IS 'can be negative or positive';
COMMENT ON COLUMN "transfers"."amount" IS 'must be positive';
เมื่อเรียกใช้และรีเฟรชแล้ว 3 ตารางจะปรากฏขึ้นอีกครั้ง แต่คราวนี้ ทุกคอลัมน์จะไม่เป็น nullable นั่นคือสิ่งที่เราต้องการ
และเรายังสามารถดูความคิดเห็นสำหรับคอลัมน์จำนวนที่เราได้เขียนไว้ในสคริปต์คำจำกัดความของสคีมาได้!
credit : https://dev.to/techschoolguru/