การสร้างห่วงโซ่ CI/CD และการทำงานอัตโนมัติด้วย Docker

ฉันเขียนเว็บไซต์แรกในช่วงปลายยุค 90 สมัยนั้นมันง่ายมากที่จะนำพวกมันไปใช้งาน มีเซิร์ฟเวอร์ Apache บนโฮสติ้งที่ใช้ร่วมกันบางแห่ง คุณสามารถเข้าสู่เซิร์ฟเวอร์นี้ผ่านทาง FTP ได้โดยการเขียนข้อความประมาณนี้ ftp://ftp.example.com. จากนั้นคุณจะต้องป้อนชื่อและรหัสผ่านของคุณและอัปโหลดไฟล์ไปยังเซิร์ฟเวอร์ มีหลายยุคสมัย ทุกอย่างง่ายกว่าตอนนี้

การสร้างห่วงโซ่ CI/CD และการทำงานอัตโนมัติด้วย Docker

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

สำหรับโปรเจ็กต์ส่วนตัวของฉัน ฉันมีการกำหนดค่าพิเศษ และฉันรู้ว่าฉันต้องการความสามารถในการปรับใช้ไซต์ในการผลิตโดยดำเนินการเพียงครั้งเดียว นั่นคือการเขียนโค้ดไปยังสาขา master บน GitHub นอกจากนี้ ฉันรู้ด้วยว่าเพื่อให้มั่นใจในการทำงานของเว็บแอปพลิเคชันขนาดเล็กของฉัน ฉันไม่ต้องการจัดการคลัสเตอร์ Kubernetes ขนาดใหญ่ หรือใช้เทคโนโลยี Docker Swarm หรือดูแลฟลีตเซิร์ฟเวอร์ด้วยพ็อด เอเจนต์ และอื่นๆ ทุกประเภท ความซับซ้อน เพื่อให้บรรลุเป้าหมายในการทำให้งานง่ายที่สุดเท่าที่จะเป็นไปได้ ฉันจำเป็นต้องทำความคุ้นเคยกับ CI/CD

หากคุณมีโปรเจ็กต์ขนาดเล็ก (ในกรณีนี้คือโปรเจ็กต์ Node.js) และคุณต้องการทราบวิธีปรับใช้โปรเจ็กต์นี้โดยอัตโนมัติ ขณะเดียวกันก็ตรวจสอบให้แน่ใจว่าสิ่งที่เก็บไว้ใน Repository ตรงกับสิ่งที่ใช้งานได้จริงทุกประการ ฉัน คิดว่าคุณอาจสนใจบทความนี้

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

ผู้อ่านบทความนี้คาดว่าจะมีความเข้าใจพื้นฐานเกี่ยวกับบรรทัดคำสั่งและการเขียนสคริปต์ Bash นอกจากนี้เขาจะต้องมีบัญชี Travis CI и ศูนย์กลางนักเทียบท่า.

วัตถุประสงค์

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

นี่คือขั้นตอนการทำงานของฉันในที่สุด

สำหรับโค้ดที่โพสต์ไปยังสาขาพื้นที่เก็บข้อมูลใด ๆ ยกเว้น masterจะดำเนินการต่อไปนี้:

  • โครงการที่สร้างบน Travis CI เริ่มต้นขึ้น
  • มีการดำเนินการทดสอบทุกหน่วย การบูรณาการ และแบบ end-to-end

เฉพาะโค้ดที่เข้าเท่านั้น masterจะดำเนินการดังต่อไปนี้:

  • ทุกอย่างที่กล่าวมาข้างต้น แถม...
  • การสร้างอิมเมจ Docker ตามโค้ด การตั้งค่า และสภาพแวดล้อมปัจจุบัน
  • การปรับใช้อิมเมจไปยัง Docker Hub
  • การเชื่อมต่อกับเซิร์ฟเวอร์ที่ใช้งานจริง
  • การอัพโหลดรูปภาพจาก Docker Hub ไปยังเซิร์ฟเวอร์
  • การหยุดคอนเทนเนอร์ปัจจุบันและการเริ่มต้นคอนเทนเนอร์ใหม่ตามอิมเมจใหม่

หากคุณไม่รู้อะไรเลยเกี่ยวกับ Docker รูปภาพ และคอนเทนเนอร์ ไม่ต้องกังวล ฉันจะบอกคุณทั้งหมดเกี่ยวกับเรื่องนี้

CI/CD คืออะไร

ตัวย่อ CI/CD ย่อมาจาก “การบูรณาการอย่างต่อเนื่อง/การปรับใช้อย่างต่อเนื่อง”

▍บูรณาการอย่างต่อเนื่อง

การบูรณาการอย่างต่อเนื่องเป็นกระบวนการที่นักพัฒนาทำข้อตกลงกับแหล่งเก็บข้อมูลซอร์สโค้ดหลักของโครงการ (โดยปกติจะเป็นสาขา master). ในขณะเดียวกันก็รับประกันคุณภาพของโค้ดผ่านการทดสอบอัตโนมัติ

▍ปรับใช้อย่างต่อเนื่อง

การปรับใช้อย่างต่อเนื่องคือการปรับใช้โค้ดโดยอัตโนมัติบ่อยครั้งในการผลิต ส่วนที่สองของตัวย่อ CI/CD บางครั้งสะกดว่า “การจัดส่งอย่างต่อเนื่อง” โดยพื้นฐานแล้วจะเหมือนกับ “การปรับใช้งานอย่างต่อเนื่อง” แต่ “การส่งมอบอย่างต่อเนื่อง” บ่งบอกถึงความจำเป็นในการยืนยันการเปลี่ยนแปลงด้วยตนเองก่อนเริ่มกระบวนการปรับใช้โครงการ

เริ่มต้นใช้งาน

แอพที่ผมเคยเรียนทั้งหมดนี้เรียกว่า จดบันทึก. นี่คือโครงการเว็บที่ฉันกำลังทำอยู่ ซึ่งออกแบบมาเพื่อจดบันทึก ตอนแรกผมลองทำ JamStack-โปรเจ็กต์ หรือเพียงแอปพลิเคชันส่วนหน้าที่ไม่มีเซิร์ฟเวอร์ เพื่อใช้ประโยชน์จากโฮสติ้งมาตรฐานและความสามารถในการปรับใช้โปรเจ็กต์ที่มีให้ netlify. เมื่อความซับซ้อนของแอปพลิเคชันเพิ่มขึ้น ฉันจำเป็นต้องสร้างส่วนของเซิร์ฟเวอร์ ซึ่งหมายความว่าฉันจะต้องกำหนดกลยุทธ์ของตัวเองสำหรับการบูรณาการแบบอัตโนมัติและการปรับใช้โปรเจ็กต์แบบอัตโนมัติ

ในกรณีของฉัน แอปพลิเคชันนี้เป็นเซิร์ฟเวอร์ Express ที่ทำงานในสภาพแวดล้อม Node.js ซึ่งให้บริการแอปพลิเคชัน React แบบหน้าเดียวและรองรับ API ฝั่งเซิร์ฟเวอร์ที่ปลอดภัย สถาปัตยกรรมนี้เป็นไปตามกลยุทธ์ที่สามารถพบได้ใน นี้ คู่มือการตรวจสอบสิทธิ์แบบเต็มสแต็ก

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

นักเทียบท่า

Docker เป็นเครื่องมือที่ช่วยให้แอปพลิเคชันต่างๆ กระจาย ปรับใช้ และรันในสภาพแวดล้อมเดียวกัน ด้วยเทคโนโลยีคอนเทนเนอร์ไลเซชันได้ แม้ว่าแพลตฟอร์ม Docker จะทำงานในสภาพแวดล้อมที่แตกต่างกันก็ตาม ก่อนอื่น ฉันต้องใช้เครื่องมือบรรทัดคำสั่ง (CLI) ของ Docker ก่อน คำแนะนำ คู่มือการติดตั้ง Docker ไม่สามารถเรียกได้ว่าชัดเจนและเข้าใจได้มากนัก แต่คุณสามารถเรียนรู้ได้ว่าในการเริ่มขั้นตอนการติดตั้งแรกคุณต้องดาวน์โหลด Docker Desktop (สำหรับ Mac หรือ Windows)

Docker Hub ก็ประมาณเดียวกับ GitHub สำหรับที่เก็บ git หรือรีจิสตรี NPM สำหรับแพ็คเกจ JavaScript นี่คือพื้นที่เก็บข้อมูลออนไลน์สำหรับอิมเมจ Docker นี่คือสิ่งที่ Docker Desktop เชื่อมต่ออยู่

ดังนั้น ในการเริ่มต้นใช้งาน Docker คุณต้องทำสองสิ่ง:

หลังจากนี้ คุณสามารถตรวจสอบว่า Docker CLI ทำงานหรือไม่โดยรันคำสั่งต่อไปนี้เพื่อตรวจสอบเวอร์ชันของ Docker:

docker -v

จากนั้น เข้าสู่ระบบ Docker Hub โดยป้อนชื่อผู้ใช้และรหัสผ่านของคุณเมื่อถูกถาม:

docker login

หากต้องการใช้ Docker คุณต้องเข้าใจแนวคิดของรูปภาพและคอนเทนเนอร์

▍รูปภาพ

รูปภาพเป็นเหมือนพิมพ์เขียวที่มีคำแนะนำในการประกอบคอนเทนเนอร์ นี่คือสแน็ปช็อตของระบบไฟล์และการตั้งค่าของแอปพลิเคชันที่ไม่เปลี่ยนรูป นักพัฒนาสามารถแชร์รูปภาพได้อย่างง่ายดาย

# Вывод сведений обо всех образах
docker images

คำสั่งนี้จะส่งออกตารางที่มีส่วนหัวต่อไปนี้:

REPOSITORY     TAG     IMAGE ID     CREATED     SIZE
---

ต่อไป เราจะดูตัวอย่างคำสั่งในรูปแบบเดียวกัน อันดับแรกคือคำสั่งพร้อมความคิดเห็น จากนั้นจึงตัวอย่างของสิ่งที่คำสั่งสามารถส่งออกได้

▍คอนเทนเนอร์

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

# Перечисление всех контейнеров
docker ps -a
CONTAINER ID     IMAGE     COMMAND     CREATED     STATUS     PORTS     NAMES
---

▍แท็ก

แท็กเป็นการบ่งชี้ถึงเวอร์ชันเฉพาะของรูปภาพ

▍การอ้างอิงคำสั่ง Docker อย่างรวดเร็ว

ต่อไปนี้เป็นภาพรวมของคำสั่ง Docker ที่ใช้กันทั่วไป

ทีม

สิ่งแวดล้อม

การกระทำ

นักเทียบท่า

ภาพ

การสร้างภาพจาก Dockerfile

แท็กนักเทียบท่า

ภาพ

การแท็กรูปภาพ

ภาพนักเทียบท่า

ภาพ

รายการภาพ

เรือเทียบท่า

ภาชนะ

ใช้งานคอนเทนเนอร์ตามรูปภาพ

นักเทียบท่า

ภาพ

การอัปโหลดภาพไปยังรีจิสทรี

นักเทียบท่าดึง

ภาพ

กำลังโหลดรูปภาพจากรีจิสทรี

นักเทียบท่า PS

ภาชนะ

รายการคอนเทนเนอร์

ระบบนักเทียบท่า prune

รูปภาพ/คอนเทนเนอร์

การนำคอนเทนเนอร์และรูปภาพที่ไม่ได้ใช้ออก

▍ไฟล์นักเทียบท่า

ฉันรู้วิธีเรียกใช้แอปพลิเคชันที่ใช้งานจริงในเครื่อง ฉันมีการกำหนดค่า Webpack ที่ออกแบบมาเพื่อสร้างแอปพลิเคชัน React สำเร็จรูป ต่อไป ฉันมีคำสั่งที่เริ่มต้นเซิร์ฟเวอร์ที่ใช้ Node.js บนพอร์ต 5000. ดูเหมือนว่านี้:

npm i         # установка зависимостей
npm run build # сборка React-приложения
npm run start # запуск Node-сервера

ควรสังเกตว่าฉันไม่มีตัวอย่างการใช้งานสำหรับเนื้อหานี้ แต่ที่นี่ สำหรับการทดลอง แอปพลิเคชัน Node ธรรมดาๆ ก็สามารถทำได้

หากต้องการใช้คอนเทนเนอร์ คุณจะต้องให้คำแนะนำแก่ Docker นี้จะกระทำผ่านไฟล์ที่เรียกว่า Dockerfileซึ่งอยู่ในไดเร็กทอรีรากของโปรเจ็กต์ ในตอนแรกไฟล์นี้ดูเหมือนจะเข้าใจยากทีเดียว

แต่สิ่งที่มีอยู่เพียงอธิบายด้วยคำสั่งพิเศษบางอย่างที่คล้ายกับการตั้งค่าสภาพแวดล้อมการทำงาน นี่คือคำสั่งบางส่วน:

  • จาก — คำสั่งนี้เริ่มต้นไฟล์ โดยจะระบุอิมเมจพื้นฐานที่ใช้สร้างคอนเทนเนอร์
  • คัดลอก — การคัดลอกไฟล์จากแหล่งในเครื่องไปยังคอนเทนเนอร์
  • เวิร์คไดร์ — การตั้งค่าไดเร็กทอรีการทำงานสำหรับคำสั่งต่อไปนี้
  • วิ่ง - เรียกใช้คำสั่ง
  • เปิดเผย — การตั้งค่าพอร์ต
  • จุดเริ่มต้น - บ่งชี้คำสั่งที่จะดำเนินการ

Dockerfile อาจมีลักษณะเช่นนี้:

# Загрузить базовый образ
FROM node:12-alpine

# Скопировать файлы из текущей директории в директорию app/
COPY . app/

# Использовать app/ в роли рабочей директории
WORKDIR app/

# Установить зависимости (команда npm ci похожа npm i, но используется для автоматизированных сборок)
RUN npm ci --only-production

# Собрать клиентское React-приложение для продакшна
RUN npm run build

# Прослушивать указанный порт
EXPOSE 5000

# Запустить Node-сервер
ENTRYPOINT npm run start

ขึ้นอยู่กับอิมเมจพื้นฐานที่คุณเลือก คุณอาจต้องติดตั้งการขึ้นต่อกันเพิ่มเติม ความจริงก็คืออิมเมจพื้นฐานบางส่วน (เช่น Node Alpine Linux) ถูกสร้างขึ้นโดยมีเป้าหมายเพื่อให้มีขนาดกะทัดรัดที่สุดเท่าที่จะเป็นไปได้ ด้วยเหตุนี้พวกเขาจึงอาจไม่มีโปรแกรมบางโปรแกรมที่คุณคาดหวัง

▍การสร้าง การแท็ก และการใช้งานคอนเทนเนอร์

การประกอบในพื้นที่และการเปิดตัวตู้คอนเทนเนอร์เกิดขึ้นหลังจากที่เรามี Dockerfileงานค่อนข้างง่าย ก่อนที่คุณจะพุชอิมเมจไปที่ Docker Hub คุณจะต้องทดสอบอิมเมจในเครื่องก่อน

▍การประกอบ

ก่อนอื่นคุณต้องรวบรวม ภาพโดยระบุชื่อและแท็ก (หากไม่ได้ระบุแท็ก ระบบจะกำหนดแท็กให้กับรูปภาพโดยอัตโนมัติ) latest).

# Сборка образа
docker build -t <image>:<tag> .

หลังจากรันคำสั่งนี้ คุณจะสามารถดู Docker สร้างอิมเมจได้

Sending build context to Docker daemon   2.88MB
Step 1/9 : FROM node:12-alpine
 ---> ...выполнение этапов сборки...
Successfully built 123456789123
Successfully tagged <image>:<tag>

การสร้างอาจใช้เวลาสองสามนาที - ทั้งหมดขึ้นอยู่กับจำนวนการขึ้นต่อกันที่คุณมี เมื่อสร้างเสร็จแล้ว คุณสามารถรันคำสั่งได้ docker images และดูคำอธิบายของภาพใหม่ของคุณ

REPOSITORY          TAG               IMAGE ID            CREATED              SIZE
<image>             latest            123456789123        About a minute ago   x.xxGB

▍เปิดตัว

สร้างภาพแล้ว ซึ่งหมายความว่าคุณสามารถเรียกใช้คอนเทนเนอร์ตามคอนเทนเนอร์ได้ เพราะผมต้องการเข้าถึงแอพพลิเคชั่นที่ทำงานอยู่ในคอนเทนเนอร์ได้ที่ localhost:5000, ฉัน , ทางด้านซ้ายของคู่ 5000:5000 ในคำสั่งถัดไปที่ติดตั้ง 5000. ทางด้านขวามือคือพอร์ตคอนเทนเนอร์

# Запуск с использованием локального порта 5000 и порта контейнера 5000
docker run -p 5000:5000 <image>:<tag>

เมื่อสร้างและรันคอนเทนเนอร์แล้ว คุณสามารถใช้คำสั่งได้ docker ps เพื่อดูข้อมูลเกี่ยวกับคอนเทนเนอร์นี้ (หรือคุณสามารถใช้คำสั่ง docker ps -aซึ่งแสดงข้อมูลเกี่ยวกับคอนเทนเนอร์ทั้งหมด ไม่ใช่แค่คอนเทนเนอร์ที่ทำงานอยู่)

CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS                      PORTS                    NAMES
987654321234        <image>             "/bin/sh -c 'npm run…"   6 seconds ago        Up 6 seconds                0.0.0.0:5000->5000/tcp   stoic_darwin

หากตอนนี้คุณไปถึงที่อยู่แล้ว localhost:5000 — คุณสามารถดูหน้าของแอปพลิเคชันที่ทำงานอยู่ซึ่งมีลักษณะเหมือนกับหน้าของแอปพลิเคชันที่ทำงานในสภาพแวดล้อมการใช้งานจริงทุกประการ

▍การแท็กและการเผยแพร่

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

ตอนนี้คุณสามารถสร้างอิมเมจด้วยชื่อใหม่และรันคำสั่ง docker push เพื่อส่งไปยังที่เก็บ Docker Hub

docker build -t <username>/<repository>:<tag> .
docker tag <username>/<repository>:<tag> <username>/<repository>:latest
docker push <username>/<repository>:<tag>

# На практике это может выглядеть, например, так:
docker build -t user/app:v1.0.0 .
docker tag user/app:v1.0.0 user/app:latest
docker push user/app:v1.0.0

หากทุกอย่างเป็นไปด้วยดี รูปภาพจะพร้อมใช้งานบน Docker Hub และสามารถอัปโหลดไปยังเซิร์ฟเวอร์หรือถ่ายโอนไปยังนักพัฒนารายอื่นได้อย่างง่ายดาย

ขั้นตอนถัดไป

ตอนนี้เราได้ตรวจสอบแล้วว่าแอปพลิเคชันในรูปแบบของคอนเทนเนอร์ Docker นั้นกำลังทำงานอยู่ในเครื่อง เราได้อัปโหลดคอนเทนเนอร์ไปยัง Docker Hub แล้ว ทั้งหมดนี้หมายความว่าเราได้ก้าวหน้าไปสู่เป้าหมายของเราเป็นอย่างดีแล้ว ตอนนี้เราต้องแก้คำถามอีกสองข้อ:

  • การตั้งค่าเครื่องมือ CI สำหรับการทดสอบและปรับใช้โค้ด
  • การตั้งค่าเซิร์ฟเวอร์ที่ใช้งานจริงเพื่อให้สามารถดาวน์โหลดและรันโค้ดของเราได้

ในกรณีของเราเราใช้ Travis CI. ในฐานะเซิร์ฟเวอร์ - ดิติกัลโอเชียน.

ควรสังเกตว่าคุณสามารถใช้บริการอื่นร่วมกันได้ที่นี่ ตัวอย่างเช่น แทนที่จะใช้ Travis CI คุณสามารถใช้ CircleCI หรือ Github Actions ได้ และแทนที่จะเป็น DigitalOcean - AWS หรือ Linode

เราตัดสินใจร่วมงานกับ Travis CI และฉันมีการกำหนดค่าบางอย่างในบริการนี้แล้ว ดังนั้นตอนนี้ผมจะพูดสั้น ๆ เกี่ยวกับวิธีการเตรียมตัวไปทำงาน

Travis CI

Travis CI เป็นเครื่องมือสำหรับการทดสอบและปรับใช้โค้ด ฉันไม่อยากพูดถึงความซับซ้อนของการจัดตั้ง Travis CI เนื่องจากแต่ละโครงการมีเอกลักษณ์เฉพาะตัว และสิ่งนี้จะไม่ก่อให้เกิดประโยชน์มากนัก แต่ฉันจะครอบคลุมพื้นฐานเพื่อช่วยคุณเริ่มต้นหากคุณตัดสินใจใช้ Travis CI ไม่ว่าคุณจะเลือก Travis CI, CircleCI, Jenkins หรืออย่างอื่น วิธีการกำหนดค่าที่คล้ายกันก็จะถูกนำมาใช้ทุกที่

หากต้องการเริ่มต้นใช้งาน Travis CI โปรดไปที่ เว็บไซต์โครงการ และสร้างบัญชี จากนั้นรวม Travis CI เข้ากับบัญชี GitHub ของคุณ เมื่อตั้งค่าระบบ คุณจะต้องระบุพื้นที่เก็บข้อมูลที่คุณต้องการให้ทำงานอัตโนมัติและเปิดใช้งานการเข้าถึง (ฉันใช้ GitHub แต่ฉันแน่ใจว่า Travis CI สามารถทำงานร่วมกับ BitBucket และ GitLab และบริการอื่นๆ ที่คล้ายกันได้)

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

▍วงจรชีวิตของงาน

ไฟล์การกำหนดค่า Travis CI ที่ถูกเรียก .travis.yml และจัดเก็บไว้ในไดเร็กทอรีรากของโปรเจ็กต์ รองรับแนวคิดของเหตุการณ์ วงจรชีวิต งาน เหตุการณ์เหล่านี้แสดงตามลำดับที่เกิดขึ้น:

  • apt addons
  • cache components
  • before_install
  • install
  • before_script
  • script
  • before_cache
  • after_success или after_failure
  • before_deploy
  • deploy
  • after_deploy
  • after_script

▍การทดสอบ

ในไฟล์การกำหนดค่า ฉันจะกำหนดค่าเซิร์ฟเวอร์ Travis CI ในเครื่อง ฉันเลือกภาษาของ Node 12 และบอกให้ระบบติดตั้งการขึ้นต่อกันที่จำเป็นสำหรับการใช้ Docker

ทุกสิ่งที่อยู่ในรายการ .travis.ymlจะถูกดำเนินการเมื่อมีการร้องขอการดึงทั้งหมดไปยังสาขาทั้งหมดของที่เก็บ เว้นแต่จะระบุไว้เป็นอย่างอื่น นี่เป็นฟีเจอร์ที่มีประโยชน์เพราะหมายความว่าเราสามารถทดสอบโค้ดทั้งหมดที่เข้ามาใน Repository ได้ สิ่งนี้จะช่วยให้คุณทราบว่าโค้ดพร้อมที่จะเขียนไปยังสาขาหรือไม่ masterและจะขัดขวางกระบวนการสร้างโครงการหรือไม่ ในการกำหนดค่าส่วนกลางนี้ ฉันติดตั้งทุกอย่างในเครื่อง รันเซิร์ฟเวอร์ Webpack dev ในเบื้องหลัง (นี่คือฟีเจอร์ของเวิร์กโฟลว์ของฉัน) และรันการทดสอบ

หากคุณต้องการให้พื้นที่เก็บข้อมูลของคุณแสดงป้ายที่บ่งบอกถึงความครอบคลุมของการทดสอบ ที่นี่ คุณสามารถดูคำแนะนำสั้นๆ เกี่ยวกับการใช้ Jest, Travis CI และ Coveralls เพื่อรวบรวมและแสดงข้อมูลนี้ได้

นี่คือเนื้อหาของไฟล์ .travis.yml:

# Установить язык
language: node_js

# Установить версию Node.js
node_js:
  - '12'

services:
  # Использовать командную строку Docker
  - docker

install:
  # Установить зависимости для тестов
  - npm ci

before_script:
  # Запустить сервер и клиент для тестов
  - npm run dev &

script:
  # Запустить тесты
  - npm run test

นี่คือจุดที่การดำเนินการที่ดำเนินการสำหรับสาขาทั้งหมดของที่เก็บและสำหรับการร้องขอการดึงสิ้นสุดลง

▍การติดตั้งใช้งาน

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

deploy:
  # Собрать Docker-контейнер и отправить его на Docker Hub
  provider: script
  script: bash deploy.sh
  on:
    branch: master

สคริปต์การปรับใช้แก้ปัญหาสองประการ:

  • สร้าง แท็ก และส่งรูปภาพไปยัง Docker Hub โดยใช้เครื่องมือ CI (ในกรณีของเราคือ Travis CI)
  • กำลังโหลดอิมเมจบนเซิร์ฟเวอร์ หยุดคอนเทนเนอร์เก่าและเริ่มต้นคอนเทนเนอร์ใหม่ (ในกรณีของเรา เซิร์ฟเวอร์ทำงานบนแพลตฟอร์ม DigitalOcean)

ขั้นแรก คุณต้องตั้งค่ากระบวนการอัตโนมัติสำหรับการสร้าง การแท็ก และการพุชรูปภาพไปที่ Docker Hub ทั้งหมดนี้คล้ายกับสิ่งที่เราทำด้วยตนเองมาก ยกเว้นว่าเราจำเป็นต้องมีกลยุทธ์ในการกำหนดแท็กที่ไม่ซ้ำให้กับรูปภาพและทำการเข้าสู่ระบบอัตโนมัติ ฉันมีปัญหากับรายละเอียดบางอย่างของสคริปต์การปรับใช้ เช่น กลยุทธ์การแท็ก การเข้าสู่ระบบ การเข้ารหัสคีย์ SSH การสร้างการเชื่อมต่อ SSH แต่โชคดีที่แฟนของฉันเก่งเรื่องการทุบตี เช่นเดียวกับเรื่องอื่นๆ อีกมากมาย เขาช่วยฉันเขียนสคริปต์นี้

ดังนั้นส่วนแรกของสคริปต์คือการอัปโหลดรูปภาพไปยัง Docker Hub มันค่อนข้างง่ายที่จะทำ รูปแบบการแท็กที่ฉันใช้เกี่ยวข้องกับการรวมแฮช git และแท็ก git เข้าด้วยกัน (หากมี) เพื่อให้แน่ใจว่าแท็กจะไม่ซ้ำกัน และทำให้ง่ายต่อการระบุแอสเซมบลีที่ใช้แท็กนั้น DOCKER_USERNAME и DOCKER_PASSWORD เป็นตัวแปรสภาพแวดล้อมผู้ใช้ที่สามารถตั้งค่าได้โดยใช้อินเทอร์เฟซ Travis CI Travis CI จะประมวลผลข้อมูลที่ละเอียดอ่อนโดยอัตโนมัติเพื่อไม่ให้ตกไปอยู่ในมือของผู้ไม่หวังดี

นี่คือส่วนแรกของสคริปต์ deploy.sh.

#!/bin/sh
set -e # Остановить скрипт при наличии ошибок

IMAGE="<username>/<repository>"                             # Образ Docker
GIT_VERSION=$(git describe --always --abbrev --tags --long) # Git-хэш и теги

# Сборка и тегирование образа
docker build -t ${IMAGE}:${GIT_VERSION} .
docker tag ${IMAGE}:${GIT_VERSION} ${IMAGE}:latest

# Вход в Docker Hub и выгрузка образа
echo "${DOCKER_PASSWORD}" | docker login -u "${DOCKER_USERNAME}" --password-stdin
docker push ${IMAGE}:${GIT_VERSION}

ส่วนที่สองของสคริปต์จะเป็นอย่างไรนั้นขึ้นอยู่กับโฮสต์ที่คุณใช้และวิธีการเชื่อมต่อกับโฮสต์นั้น ในกรณีของฉัน เนื่องจากฉันใช้ Digital Ocean ฉันจึงใช้คำสั่งเพื่อเชื่อมต่อกับเซิร์ฟเวอร์ หมอ. เมื่อทำงานกับ AWS ยูทิลิตี้นี้จะถูกนำมาใช้ awsและอื่น ๆ

การตั้งค่าเซิร์ฟเวอร์ไม่ใช่เรื่องยากเป็นพิเศษ ดังนั้นฉันจึงตั้งค่าหยดตามภาพพื้นฐาน ควรสังเกตว่าระบบที่ฉันเลือกต้องมีการติดตั้ง Docker ด้วยตนเองเพียงครั้งเดียวและการเปิดตัว Docker ด้วยตนเองเพียงครั้งเดียว ฉันใช้ Ubuntu 18.04 เพื่อติดตั้ง Docker ดังนั้นหากคุณใช้ Ubuntu เพื่อทำเช่นเดียวกัน คุณก็ทำตามได้ นี้ คำแนะนำง่ายๆ

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

  • เราจำเป็นต้องค้นหาคอนเทนเนอร์ที่กำลังทำงานอยู่และหยุดมัน
  • จากนั้นคุณจะต้องเปิดคอนเทนเนอร์ใหม่ในเบื้องหลัง
  • คุณจะต้องตั้งค่าพอร์ตภายในเครื่องของเซิร์ฟเวอร์เป็น 80 - สิ่งนี้จะช่วยให้คุณสามารถเข้าสู่เว็บไซต์ตามที่อยู่ดังกล่าว example.comโดยไม่ต้องระบุพอร์ตแทนที่จะใช้ที่อยู่เช่น example.com:5000.
  • สุดท้าย คุณต้องลบคอนเทนเนอร์และรูปภาพเก่าทั้งหมด

นี่คือความต่อเนื่องของสคริปต์

# Найти ID работающего контейнера
CONTAINER_ID=$(docker ps | grep takenote | cut -d" " -f1)

# Остановить старый контейнер, запустить новый, очистить систему
docker stop ${CONTAINER_ID}
docker run --restart unless-stopped -d -p 80:5000 ${IMAGE}:${GIT_VERSION}
docker system prune -a -f

บางสิ่งที่ต้องใส่ใจ

อาจเป็นไปได้ว่าเมื่อคุณเชื่อมต่อกับเซิร์ฟเวอร์ผ่าน SSH จาก Travis CI คุณจะเห็นคำเตือนที่จะป้องกันไม่ให้คุณดำเนินการติดตั้งต่อไป เนื่องจากระบบจะรอการตอบกลับของผู้ใช้

The authenticity of host '<hostname> (<IP address>)' can't be established.
RSA key fingerprint is <key fingerprint>.
Are you sure you want to continue connecting (yes/no)?

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

echo <public key> | base64 # выводит <публичный ключ, закодированный в base64>

ในทางปฏิบัติ คำสั่งนี้อาจมีลักษณะดังนี้:

echo "123.45.67.89 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU
GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3
Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA
t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En
mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx
NrRFi9wrf+M7Q== [email protected]" | base64

และนี่คือสิ่งที่สร้างขึ้น - สตริงที่เข้ารหัส base64:

MTIzLjQ1LjY3Ljg5IHNzaC1yc2EgQUFBQUIzTnphQzF5YzJFQUFBQUJJd0FBQVFFQWtsT1Vwa0RIcmZIWTE3U2JybVRJcE5MVEdLOVRqb20vQldEU1UKR1BsK25hZnpsSERUWVc3aGRJNHlaNWV3MThKSDRKVzlqYmhVRnJ2aVF6TTd4bEVMRVZmNGg5bEZYNVFWa2JQcHBTd2cwY2RhMwpQYnY3a09kSi9NVHlCbFdYRkNSK0hBbzNGWFJpdEJxeGlYMW5LaFhwSEFac01jaUxxOFY2UmpzTkFRd2RzZE1GdlNsVksvN1hBCnQzRmFvSm9Bc25jTTFROXg1KzNWMFd3NjgvZUlGbWIxenVVRmxqUUpLcHJyWDg4WHlwTkR2allOYnk2dncvUGIwcndlcnQvRW4KbVorQVc0T1pQblRQSTg5WlBtVk1MdWF5ckQyY0U4NlovaWw4YitndzNyMysxbkthdG1Ja2puMnNvMWQwMVFyYVRsTXFWU3NieApOclJGaTl3cmYrTTdRPT0geW91QGV4YW1wbGUuY29tCg==

นี่คือคำสั่งที่กล่าวถึงข้างต้น

install:
  - echo < публичный ключ, закодированный в base64> | base64 -d >> $HOME/.ssh/known_hosts

วิธีการเดียวกันนี้สามารถใช้กับคีย์ส่วนตัวเมื่อสร้างการเชื่อมต่อ เนื่องจากคุณอาจต้องใช้คีย์ส่วนตัวเพื่อเข้าถึงเซิร์ฟเวอร์ เมื่อทำงานกับคีย์ คุณเพียงแค่ต้องแน่ใจว่าคีย์นั้นถูกเก็บไว้อย่างปลอดภัยในตัวแปรสภาพแวดล้อม Travis CI และจะไม่แสดงคีย์นั้นที่ใดเลย

สิ่งที่ควรทราบอีกประการหนึ่งก็คือ คุณอาจต้องเรียกใช้สคริปต์การปรับใช้ทั้งหมดเป็นหนึ่งบรรทัด เช่น - ด้วย doctl. ซึ่งอาจต้องใช้ความพยายามเป็นพิเศษ

doctl compute ssh <droplet> --ssh-command "все команды будут здесь && здесь"

TLS/SSL และการทำโหลดบาลานซ์

หลังจากที่ฉันทำทุกอย่างที่กล่าวมาข้างต้น ปัญหาสุดท้ายที่ฉันพบคือเซิร์ฟเวอร์ไม่มี SSL เนื่องจากฉันใช้เซิร์ฟเวอร์ Node.js เพื่อบังคับ ไปทำงาน Reverse proxy Nginx และ Let's Encrypt คุณต้องคนจรจัดมาก

ฉันไม่ต้องการกำหนดค่า SSL ทั้งหมดนี้ด้วยตนเองจริงๆ ดังนั้นฉันจึงสร้างโหลดบาลานเซอร์และบันทึกรายละเอียดใน DNS ตัวอย่างเช่น ในกรณีของ DigitalOcean การสร้างใบรับรองที่ลงนามด้วยตนเองแบบต่ออายุอัตโนมัติบนโหลดบาลานเซอร์เป็นขั้นตอนที่ง่าย ฟรี และรวดเร็ว วิธีการนี้มีประโยชน์เพิ่มเติมที่ทำให้การตั้งค่า SSL บนเซิร์ฟเวอร์หลายเครื่องที่ทำงานอยู่เบื้องหลังโหลดบาลานเซอร์เป็นเรื่องง่ายมาก หากจำเป็น สิ่งนี้ทำให้เซิร์ฟเวอร์ไม่ต้อง "คิด" เกี่ยวกับ SSL เลย แต่ในขณะเดียวกันก็ใช้พอร์ตตามปกติ 80. ดังนั้นการตั้งค่า SSL บนโหลดบาลานเซอร์จึงง่ายและสะดวกกว่าวิธีอื่นในการตั้งค่า SSL

ตอนนี้คุณสามารถปิดพอร์ตทั้งหมดบนเซิร์ฟเวอร์ที่ยอมรับการเชื่อมต่อขาเข้า - ยกเว้นพอร์ต 80ใช้เพื่อสื่อสารกับโหลดบาลานเซอร์และพอร์ต 22 สำหรับ SSH ด้วยเหตุนี้ ความพยายามในการเข้าถึงเซิร์ฟเวอร์โดยตรงบนพอร์ตใดๆ นอกเหนือจากสองพอร์ตนี้จะล้มเหลว

ผลของการ

หลังจากที่ฉันทำทุกอย่างที่พูดถึงในเอกสารนี้ ทั้งแพลตฟอร์ม Docker หรือแนวคิดของห่วงโซ่ CI/CD อัตโนมัติทำให้ฉันไม่กลัวอีกต่อไป ฉันสามารถตั้งค่าห่วงโซ่การบูรณาการอย่างต่อเนื่อง ในระหว่างนั้นโค้ดจะถูกทดสอบก่อนที่จะเข้าสู่การใช้งานจริง และโค้ดจะถูกปรับใช้บนเซิร์ฟเวอร์โดยอัตโนมัติ ทั้งหมดนี้ยังค่อนข้างใหม่สำหรับฉัน และฉันแน่ใจว่ามีวิธีปรับปรุงขั้นตอนการทำงานอัตโนมัติของฉันและทำให้มีประสิทธิภาพมากขึ้น ดังนั้นหากคุณมีความคิดเห็นเกี่ยวกับเรื่องนี้ โปรดแจ้งให้เราทราบ ฉัน ทราบ. ฉันหวังว่าบทความนี้จะช่วยคุณในความพยายามของคุณ ฉันอยากจะเชื่อว่าหลังจากอ่านแล้ว คุณได้เรียนรู้มากเท่ากับที่ฉันได้เรียนรู้ไปพร้อมๆ กับการหาทุกสิ่งที่ฉันพูดถึงในนั้น

PS Внашем ตลาด มีรูปภาพอยู่ นักเทียบท่าซึ่งสามารถติดตั้งได้ในคลิกเดียว สามารถตรวจสอบการทำงานของตู้คอนเทนเนอร์ได้ที่ VPS. ลูกค้าใหม่ทุกคนจะได้รับการทดสอบฟรี 3 วัน

เรียนผู้อ่าน! คุณใช้เทคโนโลยี CI/CD ในโครงการของคุณหรือไม่?

การสร้างห่วงโซ่ CI/CD และการทำงานอัตโนมัติด้วย Docker

ที่มา: will.com

เพิ่มความคิดเห็น