ในการทำระบบ CI/CD ให้กับแอพพลิเคชั่นของภาษาที่ต้องมีการติดตั้ง Dependencies ต่างๆ เช่น Nodejs (node_module) หรือ PHP (vender) เป็นต้น ส่วนใหญ่ผมจะแยกเป็น 2 Job คือ job สำหรับติดตั้ง dependencies และ job ที่จะนำ dependencies นั้นไปใช้ เช่น
stages:
- build
- release
#
# Install node_module
#
npm:
stage: build
image: node:10-alpine
script:
- '[ -f package-lock.json ] && rm package-lock.json'
- npm i
cache:
key: npm-cache
paths:
- node_modules
#
# Create docker image
#
docker-image:
stage: release
image: docker:latest
services:
- docker:18-dind
cache:
key: npm-cache
paths:
- node_modules
policy: pull
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $CI_REGISTRY_IMAGE:master .
- docker push $CI_REGISTRY_IMAGE:master
จากโค็ดด้านบน
node_modules
แล้วจากนั้นก็ทำการ upload เก็บไว้โดยใช้เป็นชื่อ npm-cachenode_modules
อีกครั้ง แล้วผมก็ทำการ build เป็น docker image เก็บไว้ที่ registry ของ gitlabเมื่อมีการเรียก pipeline นี้อีกครั้ง
node_modules
แล้วค่อยติดตั้ง npm i
อีกครั้ง ซึ่งการติดตั้งครั้งนี้จะเร็วขึ้นเพราะเรามี node_modules
ไว้แล้ว เมื่อจบก็จะทำการ upload เก็บไว้โดยใช้เป็นชื่อ npm-cache อีกครั้งnode_modules
อีกครั้ง แล้วก็ทำงานตาม script
ไปเรื่อยๆการทำ caching แบบนี้จะทำให้ pipeline เราทำงานเร็วขึ้นมา เพราะไม่จำเป็นต้องติดตั้ง node_modules
ทุกครั้ง
แต่เดียวก่อน!!! จากที่ผมใช้งานในบ้างครั้ง สมมติใน package.json
เรามี dependencies 2 ตัว pipeline เราก็ทำงานปกติไปตาม Step คือ
node_modules
คราวนี้เรามีการเพิ่ม dependencies เป็น 4 ตัว pipeline ในขั้นตอน npm i
ก็จะติดตั้งเฉพาะ dependencies ที่เพิ่มเข้ามา แล้วอัพโหลด node_modules
เก็บไว้เหมือนเดิม
ปัญหามันอยู่ช่วงนี้ กล่าวคือ job ต่อมามันดันไปโหลด node_modules
ของเก่าที่มี dependencies 2 ตัว มาใช้ แล้วพอเราเอาแอพพลิเคชั่นไปใช้งานจริงขึ้น Server ก็จะเจอ error ว่า dependencies ไม่ครบทันที
ซึ่งการเรียก cache ไฟล์ผิดนี้เกิดขึ้นบ่อยมาก ถ้ามันเกิดแบบนี้ผมก็จะต้องเรียก pipeline ตัวนี้ซ้ำๆ สักสองถึงสามรอบถึงจะโอเค
ผมจะใช้ artifacts มาช่วยในการเก็บไฟล์ dependencies ต่างๆ แล้วให้ Job ที่ต้องการไปเรียกใช้ เช่น
stages:
- build
- release
#
# Install node_module
#
npm:
stage: build
image: node:10-alpine
script:
- '[ -f package-lock.json ] && rm package-lock.json'
- npm i
cache:
key: npm-cache
paths:
- node_modules
artifacts:
paths:
- node_modules
expire_in: 1 days
when: always
#
# Create docker image
#
docker-image:
stage: release
image: docker:latest
services:
- docker:18-dind
dependencies:
- npm
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $CI_REGISTRY_IMAGE:master .
- docker push $CI_REGISTRY_IMAGE:master
ใน npm job ผมจะเพิ่ม artifacts เข้ามาเก็บ node_modules
ไว้ด้วย และก็ให้มัน cache เก็บไว้แบบเดิม
...
...
artifacts:
paths:
- node_modules
expire_in: 1 days
when: always
...
...
ต่อมา docker-image job จากแต่ก่อนจะโหลด cache มาใช้ คราวนี้ก็ให้โหลด artifacts มาใช้เลย
...
...
dependencies:
- npm
...
...
เพียงเท่านี้ก็จะจบปัญหาเรื่องการนำ dependencies มาไม่ครบแล้ว ส่วนใครมีวิธีอื่นที่ดีกว่านี้ก็แนะนำมาได้นะครับ