MySQL + Docker เขียน + Nodejs/Python— คำแนะนำทีละขั้นตอน

Nov 28 2022
MySQL เป็นหนึ่งในฐานข้อมูลเชิงสัมพันธ์ที่ได้รับความนิยมสูงสุดตลอดกาล การใช้ MySQL กับ Docker และ docker-compose ทำให้ง่ายและรวดเร็วในการทดสอบการเปลี่ยนแปลงในแอปพลิเคชันใดๆ โดยใช้ MySQL เป็นฐานข้อมูล

MySQL เป็นหนึ่งใน ฐานข้อมูลเชิงสัมพันธ์ที่ได้รับความ นิยมสูงสุดตลอดกาล การใช้ MySQL กับ Docker และ docker-compose ทำให้ง่ายและรวดเร็วในการทดสอบการเปลี่ยนแปลงในแอปพลิเคชันใดๆ โดยใช้ MySQL เป็นฐานข้อมูล ในบทช่วยสอนนี้ เราจะให้รายละเอียดวิธีใช้ MySQL กับ Docker และ docker-compose ทีละขั้นตอน ทำให้เข้าใจได้ง่าย

รหัส TLDR ที่นี่ มากลิ้งกัน!

เหตุใดจึงต้องใช้ MySQL กับ Docker เพื่อการพัฒนาในพื้นที่

มีเหตุผลที่ดีหลายประการในการใช้ฐานข้อมูลใด ๆ รวมถึง MySQL พร้อม Docker สำหรับการพัฒนาในพื้นที่ เหตุผลบางประการมีดังนี้:

  1. การใช้ MySQL เวอร์ชันใดก็ได้ เช่น 5.6, 5.7 หรือ 8 ตามโครงการหรือเหตุผลอื่นๆ นั้นง่ายมาก
  2. โดยปกติแล้วกับนักเทียบท่า ถ้ามันทำงานบนเครื่องของคุณ มันจะทำงานบนเครื่องของวิศวกรซอฟต์แวร์รายอื่น ในสภาพแวดล้อมที่กำลังจัดเตรียม และในการผลิตด้วยเช่นกัน เนื่องจากมีความเข้ากันได้บางอย่าง
  3. สมาชิกในทีมใหม่สามารถทำงานได้อย่างมีประสิทธิภาพภายในไม่กี่ชั่วโมง ไม่ใช่วันๆ เนื่องจากนักเทียบท่าและเครื่องมืออื่นๆ ได้รับการตั้งค่าอย่างมีประสิทธิภาพ

ข้อกำหนดเบื้องต้น

ก่อนที่เราจะจัดการกับโค้ดและคำสั่ง CLI บางคำสั่ง ด้านล่างนี้เป็นสิ่งที่ควรทำก่อน:

  1. ความรู้พื้นฐานของ Docker และคำสั่งที่เกี่ยวข้อง เช่น docker build, run, execute ฯลฯ จะเป็นประโยชน์สำหรับคำแนะนำนี้
  2. ข้อมูลใด ๆ ก่อนหน้านี้เกี่ยวกับ Docker-compose จะมีประโยชน์มาก
  3. ความเข้าใจทั่วไปเกี่ยวกับวิธีการทำงานของฐานข้อมูลเชิงสัมพันธ์ โดยเฉพาะ MySQL จะพิจารณาเป็นพิเศษ

รัน MySQL ด้วย Docker

สำหรับคู่มือเริ่มต้นนี้ เราจะใช้อิมเมจ MySQL Docker อย่างเป็นทางการจากDockerHub อิมเมจ MySQL Docker อย่างเป็นทางการไม่มีเวอร์ชัน Alpine Linux แต่เวอร์ชัน Debian ยังมีขนาด 147 MB ​​ซึ่งไม่ใหญ่เกินไปสำหรับอิมเมจนักเทียบท่า

หากต้องการเรียกใช้คอนเทนเนอร์ MySQL 8.0 โดยใช้อิมเมจอย่างเป็นทางการ ให้เรียกใช้คำสั่งต่อไปนี้:

mkdir /tmp/mysql-data
docker run --name basic-mysql --rm -v /tmp/mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=ANSKk08aPEDbFjDO -e MYSQL_DATABASE=testing -p 3306:3306 -it mysql:8.0

  • --nameเพื่อตั้งชื่อคอนเทนเนอร์basic-mysql
  • --rmเพื่อนำคอนเทนเนอร์ออกเมื่อหยุดทำงาน
  • -v /tmp/mysql-data:/var/lib/mysqlถูกเพิ่มเพื่อเก็บข้อมูลเมื่อคอนเทนเนอร์รีสตาร์ท มันจะหายไปเมื่อเครื่องโฮสต์รีสตาร์ทตามที่เป็นอยู่/tmp
  • -e MYSQL_ROOT_PASSWORD=ANSKk08aPEDbFjDO -e MYSQL_DATABASE=testingสำหรับตั้งรหัสผ่านของผู้ใช้ root และเริ่มต้นฐานข้อมูลชื่อtesting
  • -p 3306:3306แมปพอร์ตโฮสต์ 3306 กับพอร์ตคอนเทนเนอร์ 3306 พอร์ต 3306 เป็นพอร์ตเริ่มต้นของ MySQL
  • -it mysql:8.0- -มันจะแสดงบันทึกทั้งหมดและเรากำลังใช้อิมเมจ MySQL เวอร์ชัน 8.0 อย่างเป็นทางการซึ่งจะเรียกใช้รสชาติของ Debian

2022-10-27 06:11:09+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.31-1.el8 started.
2022-10-27 06:11:10+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2022-10-27 06:11:10+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.31-1.el8 started.
2022-10-27 06:11:11+00:00 [Note] [Entrypoint]: Initializing database files
2022-10-27T06:11:11.957280Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
2022-10-27T06:11:11.957392Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.0.31) initializing of server in progress as process 80
2022-10-27T06:11:11.987130Z 0 [Warning] [MY-010159] [Server] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
2022-10-27T06:11:12.013548Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2022-10-27T06:11:16.919522Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2022-10-27T06:11:20.772591Z 6 [Warning] [MY-010453] [Server] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.
2022-10-27 06:11:27+00:00 [Note] [Entrypoint]: Database files initialized
2022-10-27 06:11:27+00:00 [Note] [Entrypoint]: Starting temporary server
mysqld will log errors to /var/lib/mysql/729f35877b11.err
mysqld is running as pid 133
2022-10-27 06:11:40+00:00 [Note] [Entrypoint]: Temporary server started.
'/var/lib/mysql/mysql.sock' -> '/var/run/mysqld/mysqld.sock'
Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/leapseconds' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/tzdata.zi' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.
2022-10-27 06:11:44+00:00 [Note] [Entrypoint]: Creating database testing
2022-10-27 06:11:44+00:00 [Note] [Entrypoint]: Stopping temporary server
2022-10-27 06:11:48+00:00 [Note] [Entrypoint]: Temporary server stopped
2022-10-27 06:11:48+00:00 [Note] [Entrypoint]: MySQL init process done. Ready for start up.
2022-10-27T06:11:48.661152Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
2022-10-27T06:11:48.670274Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.31) starting as process 1
2022-10-27T06:11:48.683339Z 0 [Warning] [MY-010159] [Server] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
2022-10-27T06:11:48.700826Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2022-10-27T06:11:51.317151Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2022-10-27T06:11:52.336910Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2022-10-27T06:11:52.336965Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
2022-10-27T06:11:52.352191Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
2022-10-27T06:11:52.548249Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock
2022-10-27T06:11:52.548394Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.31'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server - GPL.

docker exec -it basic-mysql /bin/bash
#once inside the container 
mysql -u root -p
#put/paste the password, ANSKk08aPEDbFjDO, and once inside MySQL CLI run
show databases;

เราสามารถหยุดภาชนะได้ด้วยdocker stop basic-mysql

แม้ว่านั่นจะไม่ยากเกินไป แต่ฉันก็ไม่คิดว่ามันง่ายอีกทั้งพารามิเตอร์ของคำสั่งก็จำได้ไม่ยาก อีกแง่มุมหนึ่งคือเราเรียกใช้ MySQL แบบแยกจากกัน ไม่มีการเชื่อมโยงระหว่างแอปพลิเคชัน Quotes API Node.js และคอนเทนเนอร์ MySQL นี่คือสิ่งที่ลักษณะการประกาศของการเขียนนักเทียบท่ามีประโยชน์มากดังที่เราจะเห็นในหัวข้อถัดไป

รัน MySQL ด้วย docker-compose

เพิ่มสคริปต์การฉีดเริ่มต้น

mkdir basic-mysql && touch ./basic-mysql/init.sql

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';
USE testing;
DROP TABLE IF EXISTS `order`;
DROP TABLE IF EXISTS users;
DROP TABLE IF EXISTS coffee;
/*NEVER store passwords in clear text as it's done here!!!*/
CREATE TABLE users (
 id SERIAL PRIMARY KEY,
 name TEXT NOT NULL,
 email TEXT NOT NULL,
 password TEXT NOT NULL,
 role ENUM('admin', 'consumer')
);
INSERT INTO
 users (name, email, password, role)
VALUES
 ('test', '[email protected]', 'test', 'consumer'),
 ('admin', '[email protected]', 'admin', 'admin');
CREATE TABLE coffee (
 id SERIAL PRIMARY KEY,
 blend_name char(64),
 origin char(64),
 variety char(64),
 notes char(64),
 intensifier char(64),
 price float
);
INSERT INTO
 coffee (
  blend_name,
  origin,
  variety,
  notes,
  intensifier,
  price
 )
VALUES
 (
  'Good-morning Symphony',
  'Dipilto, Nicaragua',
  'Kona',
  'crisp, coating, concord grape, fresh wood, maple syrup',
  'astringent',
  23.7
 ),
 (
  'KrebStar Mug',
  'Central Valley, Costa Rica',
  'Yellow Bourbon',
  'mild, tea-like, pineapple, barley, musty',
  'delicate',
  40.0
 );
CREATE TABLE `order` (
 id SERIAL PRIMARY KEY,
 coffeeId BIGINT UNSIGNED NOT NULL,
 userId BIGINT UNSIGNED NOT NULL,
 quantity INT NOT NULL,
 createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
 updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 CONSTRAINT fk_coffeeId FOREIGN KEY (coffeeId) REFERENCES coffee(id) ON DELETE CASCADE ON UPDATE CASCADE,
 CONSTRAINT fk_userId FOREIGN KEY (userId) REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE
);
-- insert data into order table
INSERT INTO
 `order` (coffeeId, userId, quantity)
VALUES
 (1, 1, 2),
 (2, 2, 1);

version: '3.8'
services:
  basic-mysql:
    container_name: basic-mysql
    image: mysql:8.0
    cap_add:
      - SYS_NICE
    restart: always
    environment:
      - MYSQL_DATABASE=testing
      - MYSQL_ROOT_PASSWORD=ANSKk08aPEDbFjDO
    ports:
      - '3306:3306'
      - '33060:33060'
    command: --init-file /docker-entrypoint-initdb.d/init.sql
    volumes:
      - basic-mysql:/var/lib/mysql
      - ./basic-mysql/init.sql:/docker-entrypoint-initdb.d/init.sql
volumes:
  basic-mysql:
    driver: local

  1. ใช้ไฟล์ docker-compose เวอร์ชัน 3.8ซึ่งเป็นหนึ่งในไฟล์ล่าสุด
  2. ดังนั้นเราจึงกำหนดdbให้เป็นบริการ แต่ละบริการจะเทียบเท่ากับคำสั่งเรียกใช้นักเทียบท่าใหม่
  3. ต่อจากนั้น เราชี้ให้นักเทียบท่าเขียนเพื่อใช้อิมเมจ MySQL 8.0 อย่างเป็นทางการสำหรับบริการฐานข้อมูลนี้
  4. ชุดcap_addที่จะSYS_NICE ระงับข้อความแสดงข้อผิดพลาดที่ไม่มีประโยชน์
  5. ขั้นต่อไป เราจะขอให้นักเทียบท่าที่เขียนใหม่รีสตาร์ทคอนเทนเนอร์นี้เสมอหากล้มเหลว
  6. หลังจากนั้น เราเพิ่มตัวแปรสภาพแวดล้อม 2 ตัวสำหรับฐานข้อมูล MySQL และรหัสผ่านของผู้ใช้รูท ตามความต้องการ เราสามารถเพิ่มผู้ใช้รายอื่นเพื่อให้สิทธิ์กับ env vars อื่นน้อยลง
  7. จากนั้น เราแมปพอร์ตโฮสต์3306กับพอร์ตคอนเทนเนอร์3306เนื่องจากเซิร์ฟเวอร์ MySQL กำลังทำงานบนพอร์ต3306คอนเทนเนอร์ พอร์ตโฮสต์อาจเปลี่ยนแปลงได้ขึ้นอยู่กับความต้องการ
  8. จากนั้น เรารันสคริปต์การ seed เพื่อใส่ข้อมูลเริ่มต้นลงในฐานข้อมูล mysql ของเราtesting
  9. จากนั้นเราเพิ่ม 2 วอลุ่ม วอลุ่มแรกคือวอลุ่ม DB ที่แมปกับวอลุ่มด้านbasic-mysqlล่าง ซึ่งโดยทั่วไปจะบอกนักเทียบท่าและนักเทียบท่าที่เขียนเพื่อจัดการโวลุ่มให้เรา ต่อไป เราเพิ่มinit.sqlสคริปต์ที่จะเริ่มต้น ฐานข้อมูล ของเราtestingด้วยไฟล์ SQL ที่กำหนด

docker-compose up

[+] Running 1/1
 ⠿ Container basic-mysql  Created                                                          0.2s
Attaching to basic-mysql
basic-mysql  | 2022-10-27 09:38:51+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.31-1.el8 started.
basic-mysql  | 2022-10-27 09:38:51+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
basic-mysql  | 2022-10-27 09:38:51+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.31-1.el8 started.
basic-mysql  | '/var/lib/mysql/mysql.sock' -> '/var/run/mysqld/mysqld.sock'
basic-mysql  | 2022-10-27T09:38:52.620935Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
basic-mysql  | 2022-10-27T09:38:52.628931Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.31) starting as process 1
basic-mysql  | 2022-10-27T09:38:52.649308Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
basic-mysql  | 2022-10-27T09:38:53.380032Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
basic-mysql  | 2022-10-27T09:38:53.698374Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
basic-mysql  | 2022-10-27T09:38:53.698422Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
basic-mysql  | 2022-10-27T09:38:53.705214Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
basic-mysql  | 2022-10-27T09:38:53.904655Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.31'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server - GPL.
basic-mysql  | 2022-10-27T09:38:53.904741Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock

การเชื่อมต่อกับฐานข้อมูลผ่าน UI เช่นMySQL Workbench และตรวจสอบว่าตารางของเราได้รับการ seed อย่างถูกต้อง

ทดสอบการเชื่อมต่อผ่านสคริปต์ python

ตรวจสอบให้แน่ใจว่ามีการติดตั้งการพึ่งพา วิ่งpip install pymysqlหรือpip3 install pymysql

# main.py
import pymysql.cursors
# Connect to the database
connection = pymysql.connect(
    host='localhost',
    user='root',
    password='ANSKk08aPEDbFjDO',
    database='testing',
    cursorclass=pymysql.cursors.DictCursor
)
with connection:
    with connection.cursor() as cursor:
        # Read a single record
        sql = "SELECT * FROM `users`"
        cursor.execute(sql)
        result = cursor.fetchall()
        print(result)

การทดสอบการเชื่อมต่อผ่านโหนดสคริปต์

ตรวจสอบให้แน่ใจว่ามีการติดตั้งการพึ่งพา วิ่งnpm i mysql

// main.js
const mysql = require('mysql');
const con = mysql.createConnection({
  host: "localhost",
  user: "root",
  password: "ANSKk08aPEDbFjDO",
  database: "testing"
});
con.connect(function(err) {
  if (err) throw err;
  console.log("Connected!");
con.query("SELECT * FROM `users`", function (err, result, fields){
    if (err) throw err;
    console.log(result);
  });
});

เรียกร้องให้ดำเนินการ

หากคุณเห็นว่าคู่มือนี้มีประโยชน์ โปรดปรบมือและติดตามฉันได้ตามสบาย เข้าร่วมสื่อผ่านลิงก์นี้เพื่อเข้าถึงบทความพรีเมียมทั้งหมดจากฉันและนักเขียนที่ยอดเยี่ยมคนอื่นๆ ที่นี่บนสื่อ

เพิ่มระดับการเข้ารหัส

ขอบคุณที่เป็นส่วนหนึ่งของชุมชนของเรา! ก่อนที่คุณจะไป:

  • ปรบมือให้กับเรื่องราวและติดตามผู้เขียน
  • ดูเนื้อหาเพิ่มเติมในสิ่งพิมพ์ Level Up Coding
  • ติดตามเรา: Twitter | LinkedIn | จดหมายข่าว