การตั้งค่า dockerfile และ docker-compose เพื่อรัน Node.js และ MongoDB บน Docker Container
ในบทความนี้ จะบันทึกวิธีการตั้งค่า dockerfile และ docker-compose เพื่อทดสอบและฝึกใช้งาน Docker และต่อยอดเป็น Microservices ในอนาคต ซึ่งผมเห็นว่า มีความน่าสนใจที่จะเอามาแบ่งปันประสบการณ์ตรงนี้ให้ทุกคนได้อ่านกันครับ
ในกรณีนี้ เราจะไม่ใช้ Node.js เป็น Runtime บนเครื่องของตัวเองเลย รวมถึง MongoDB ด้วย ทุกอย่างจะทำงานผ่าน Docker เท่านั้น จุดประสงค์ต้องการทดสอบการรันทุก Server โดยใช้ Docker Container
ตั้งค่าโปรเจ็กต์
ในโปรเจ็กต์ตัวอย่าง เรามีการสร้าง APIs เพื่อใช้งานเกี่ยวกับ ระบบจอดรถ ขอตั้งชื่อโปรเจ็กต์ว่า parking-lot-backend-app
ละกันนะฮะ
ภายในโปรเจ็กต์ มีการตั้งค่าภายในไฟล์ .env
เกี่ยวกับ MongoDB ดังนี้
DB_HOST=mongo
DB_PORT=27017
DB_NAME=<DB_NAME>
DB_USER=<DB_USERNAME>
DB_PASS=<DB_PASSWORD>
ต่อมา เริ่มสร้าง dockerfile
กันก่อนดีกว่า
FROM node:12
# FROM เอาไว้เลือก Base Image จาก Docker Hub ที่ต้องการใช้เป็นสภาพแวดล้อม
LABEL maintainer="admin"
LABEL description="This dockerfile for install the parking-lot-backend."
WORKDIR /app
# WORKDIR คิือการกำหนด directory ของการทำงาน
# เพื่อให้คำสั่งอื่นๆของ Docker ไปทำงานที่นั่น ซึ่งในที่นี้เป็น /app
COPY package.json ./
# คัดลอก package.json ไปใส่ที่ ./
COPY package-lock.json ./
# คัดลอก package-lock.json ไปใส่ที่ ./
RUN npm install
# ในที่นี้ คือ จาก ./ ไปหา ./
COPY ./ ./
# COPY คือคำสั่งที่คัดลอกโค้ดจาก directory ต้นทาง ไปหา ปลายทาง
# ในที่นี้ คือ จาก ./ ไปหา ./
ENV NODE_ENV production
CMD ["npm", "run", "dev"]
# CMD คีอ การใส่คำสั่งเพื่อรันโปรแกรม จากตัวอย่างคือ คำสั่ง "npm run dev"
ลักษณะการเขียน Dockerfile จะเป็นการเขียนเพื่อเรียงลำดับการทำงานแบบบนลงล่าง รายละเอียดเพิ่มเติมศึกษาได้ที่นี่
สร้าง docker-compose.yml
ขึ้นมา โดยมีรายละเอียดดังนี้
version: '3'
services:
app:
container_name: parking-lot
restart: always
build: .
ports:
- '80:3000'
external_links:
- mongo
mongo:
container_name: mongo
image: mongo
ports:
- '27017:27017'
จากในไฟล์ Docker Compose นี้ มีการกำหนดค่าต่างๆดังนี้
- version
ของ Compose file format
- services
คือ การประกาศ service ที่จะรันทั้งหมด
- container-name
คือ การกำหนดชื่อ container ของแต่ละ service
- image
คือชื่อของ Docker Image ที่จะใช้
- ports
คือการกำหนด port โดยกำหนดแบบ <external_of_container>:<internal_of_container>
- external_links
คือการกำหนด ว่า app จะทำงานร่วมกันกับ container ชื่ออะไร ถ้า container นั้นอยู่ใน Compose เดียวกัน คำสั่งนี้จะถูก ignore ไป
ในกรณีนี้ เราจะมี Service อยู่ 2 ตัว คือ parking-lot
และ mongo
ซึ่งจะเป็น server ให้กับ MongoDB ทำหน้าที่เป็นฐานข้อมูลของ app
Start Container
มาเช็ค Container ที่มีอยู่ในเครื่องก่อนทำการสร้าง ด้วย docker-compose
docker ps -a
ดูว่าไม่มี Container
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
จากนั้น เราทำการสร้าง Container โดยใช้คำสั่งนี้ที่ directory path ของโปรเจ็กต์
docker-compose up
เราจะได้ Result ออกมาเป็นแบบนี้
[+] Running 2/2
⠿ Container mongo Created 0.1s
⠿ Container parking-lot Created 0.1s
Attaching to mongo, parking-lot
parking-lot |
parking-lot | > [email protected] dev /app
parking-lot | > nodemon ./bin/www
parking-lot |
parking-lot | [nodemon] 2.0.21
parking-lot | [nodemon] to restart at any time, enter `rs`
parking-lot | [nodemon] watching path(s): *.*
parking-lot | [nodemon] watching extensions: js,mjs,json
parking-lot | [nodemon] starting `node ./bin/www`
mongo | {"t":{"$date":"2023-04-09T10:07:55.820+00:00"},"s":"I", "c":"CONTROL", "id":23285, "ctx":"-","msg":"Automatically disabling TLS 1.0, to force-enable TLS 1.0 specify --sslDisabledProtocols 'none'"}
mongo | {"t":{"$date":"2023-04-09T10:07:55.821+00:00"},"s":"I", "c":"NETWORK", "id":4915701, "ctx":"-","msg":"Initialized wire specification","attr":{"spec":{"incomingExternalClient":{"minWireVersion":0,"maxWireVersion":17},"incomingInternalClient":{"minWireVersion":0,"maxWireVersion":17},"outgoing":{"minWireVersion":6,"maxWireVersion":17},"isInternalClient":true}}}
เราจะเห็นว่า Container ของโปรเจ็กต์และของ mongo image ทำงานได้แล้วเรียบร้อย
ลองเช็ค Container อีกรอบ
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
be6b3a88e153 parking-lot-backend-app "docker-entrypoint.s…" 20 seconds ago Up 19 seconds 0.0.0.0:80->3000/tcp parking-lot
244faa10158d mongo "docker-entrypoint.s…" 20 seconds ago Up 19 seconds 0.0.0.0:27017->27017/tcp mongo
เราจะเห็นว่า ชื่อ Container ของโปรเจ็กต์จะมีชื่อตามที่เราตั้งใน docker-compose ไฟล์ ส่วน Image จะเหมือนกับชื่อ Directory
หลังจากนี้ เราสามารถรันโปรเจ็กต์ได้แล้ว และข้อมูลที่สร้างขึ้นมาก็สามารถเก็บไว้ที่ Container ของ mongo
การ Stop Container และ Start Container อีกครั้ง
เราสามารถหยุดการทำงานของ Container ทั้งสองได้โดยการกด control + c ที่หน้า Command Line ที่เรา Start docker-compose ไว้ก่อนหน้าได้
เมื่อกลับมาเช็ค ด้วย docker ps
จะเห็นว่าไม่มี Container ที่ทำงานแล้ว
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ซึ่ง Container ได้ถูกหยุดการทำงานไว้เท่านั้น แต่เราสามารถ Start Container ขึ้นมาได้อีกครั้ง ด้วยคำสั่ง
docker container start parking-lot mongo
จะเห็นชื่อ Container แสดงขึ้นมา ถือว่ากลับมาทำงานอีกครั้งเรียบร้อย
parking-lot
mongo
หรือว่าจะสั่งการรัน Container ด้วยวิธี docker-compose up
ที่ Directory Path ก็ได้เช่นเดียวกัน
สรุป
นี่เป็นเพียงการเริ่มต้นใช้งาน Docker สำหรับเป็นประตูบานแรก เพื่อเข้าสู่โลกของ Microservices เท่านั้น ผมบันทึกวิธีการทำงานบางส่วนเอาไว้ เพื่อทบทวนความจำตัวเอง และเผื่อว่าจะมีประโยชน์ให้กับผู้ที่เป็นมือใหม่เหมือนกันได้เห็นตัวอย่างเพื่อเอาไปใช้กับงานของตัวเอง แล้วพบกันใหม่บทความหน้าครับ
อ้างอิง
ช่วงขายของ
ตอนนี้เรามีบริการรับทำเว็บไซต์เพื่อจุดประสงค์ต่างๆ เช่น
- ร้านค้าออนไลน์
- โปรโมทบริษัท
- เว็บบล็อกสำหรับเขียนบทความ
- หน้าขายของแบบหน้าเดียว (Single Page)
และอื่นๆ โดยใช้ Wordpress เป็นโครงสร้างหลังบ้านและหน้าบ้าน ทำให้ดูแลรักษาง่ายในระยะยาว
คุณไม่ต้องมีแบบมาก่อน ไม่เป็นไร เรามีหน้าเว็บตัวอย่างมาให้คุณเลือกหลายสิบแบบ ราคาคุ้มค่า และส่งมอบงานไว สามารถเข้ามาดูรายละเอียด และสอบถาม-พูดคุยได้ที่เว็บไซต์ของ OneFastWeb ได้เลยครับ ขอบคุณครับ