paint-brush
GitHub Actions, Node.js, CouchDB 및 Aptible을 사용하여 블로그 게시물 앱 배포를 자동화하는 방법~에 의해@wise4rmgod
3,259 판독값
3,259 판독값

GitHub Actions, Node.js, CouchDB 및 Aptible을 사용하여 블로그 게시물 앱 배포를 자동화하는 방법

~에 의해 Wisdom Nwokocha19m2023/12/04
Read on Terminal Reader

너무 오래; 읽다

GitHub Actions, Node.js를 사용하여 블로그 게시물 앱 배포 자동화에 대한 가이드에 오신 것을 환영합니다. CouchDB 및 Aptible. 이 포괄적인 튜토리얼은 위의 도구와 기술을 사용하여 블로그 게시물 애플리케이션을 구축, 배포 및 관리하는 방법을 안내합니다. 하지만 먼저 Blogpost 앱에 대한 간략한 개요와 그 기능, 주요 구성 요소에 대해 설명하겠습니다. Blogpost 앱은 사용자가 블로그 게시물을 작성하고 공유할 수 있는 웹 애플리케이션입니다. 사용자는 다른 사용자가 게시한 게시물을 작성, 편집, 삭제하고 볼 수 있습니다. 이 앱은 Node.js를 백엔드로, CouchDB를 데이터베이스로, GitHub Actions를 지속적인 통합 및 배포 도구로 사용합니다.
featured image - GitHub Actions, Node.js, CouchDB 및 Aptible을 사용하여 블로그 게시물 앱 배포를 자동화하는 방법
Wisdom Nwokocha HackerNoon profile picture

GitHub Actions, Node.js를 사용하여 블로그 게시물 앱 배포 자동화에 대한 가이드에 오신 것을 환영합니다.

CouchDB 및 Aptible.


이 포괄적인 튜토리얼은 위의 도구와 기술을 사용하여 블로그 게시물 애플리케이션을 구축, 배포 및 관리하는 방법을 안내합니다.


하지만 먼저 Blogpost 앱에 대한 간략한 개요와 그 기능, 주요 구성 요소에 대해 설명하겠습니다. Blogpost 앱은 사용자가 블로그 게시물을 작성하고 공유할 수 있는 웹 애플리케이션입니다.


사용자는 다른 사용자가 게시한 게시물을 작성, 편집, 삭제하고 볼 수 있습니다. 이 앱은 Node.js를 백엔드로, CouchDB를 데이터베이스로, GitHub Actions를 지속적인 통합 및 배포 도구로 사용합니다.


내가 이것을 선택한 이유는 무엇입니까? 글쎄, 많은 이유가 있지만 다음은 주요 이유 중 일부입니다.


  • Node.js는 다양한 플랫폼에서 실행할 수 있는 빠르고 확장 가능하며 사용하기 쉬운 JavaScript 런타임 환경입니다. 여기에는 제가 이 프로젝트에서 사용할 미니멀하고 유연한 웹 애플리케이션 프레임워크인 Express와 같은 웹 개발을 위한 많은 라이브러리와 프레임워크가 있습니다.


  • CouchDB는 안정적이고 안전하며 강력한 오픈 소스 NoSQL 데이터베이스 시스템입니다. JSON을 사용하여 데이터를 저장하는 문서 중심의 데이터베이스입니다.


  • GitHub Actions는 GitHub 리포지토리의 워크플로를 자동화할 수 있는 유연하고 편리한 통합 도구입니다. 또한 이 프로젝트에서 Aptible에 앱을 배포하기 위해 사용할 Aptible Deploy 작업과 같이 필요에 따라 사용하거나 사용자 정의할 수 있는 사전 구축된 작업이 많이 있습니다.


  • Aptible 은 컨테이너화된 애플리케이션을 배포 및 관리하기 위한 클라우드 기반 플랫폼으로, 손쉬운 프로비저닝, 확장 및 모니터링 기능을 제공합니다.

전제조건

개발 여정을 시작하기 전에 필요한 도구와 기술을 설정하는 것이 필수적입니다.


  • Node.js: Node.js가 컴퓨터에 설치되어 있는지 확인하세요.


  • CouchDB: CouchDB가 시스템에 설치되어 실행 중인지 확인하세요.


  • Node.js 및 JavaScript 전문 지식: Node.js 및 JavaScript 기본 사항에 대한 확실한 이해를 보유하고 있습니다.


  • Docker: 컴퓨터에 Docker를 설치하고 실행합니다.


  • Aptible 계정: Aptible 계정을 생성하고 기본 애플리케이션 배포에 익숙해지세요.


  • Docker 클라우드 계정: 애플리케이션을 호스팅하려면 Docker 클라우드 계정을 획득하세요.

Blogpost 앱 개발

1: Node.js 프로젝트 설정

  • 블로그 게시물 앱용 프로젝트 디렉터리를 만듭니다.


  • npm을 사용하여 Node.js 프로젝트를 초기화합니다.
 npm init -y


  • 백엔드의 기반이 될 Express.js 프레임워크를 설치합니다.
 npm install express nano

2단계: CouchDB 설정

  • CouchDB가 설치되어 실행 중인지 확인하세요. http://127.0.0.1:5984/_utils/ 에서 브라우저를 통해 CouchDB에 액세스할 수 있습니다.


CouchDB 대시보드

3단계: Node.js 애플리케이션 생성

  • 프로젝트 디렉터리에 blog.js 파일을 만듭니다.


  • Express를 초기화하고 CouchDB에 연결합니다.
 const express = require("express"); const nano = require("nano")("http://admin:[email protected]:5984"); const app = express(); const port = 3000; // Middleware to parse JSON data app.use(express.json()); // async function asyncCall() { // // await nano.db.destroy("alice"); // await nano.db.create("blogposts"); // const db = nano.use("blogposts"); // return response; // } // asyncCall(); const db = nano.use("blogposts");


  • 이 코드는 CouchDB 데이터베이스를 사용하여 블로그 게시물을 생성, 검색, 업데이트 및 삭제하기 위한 API 엔드포인트를 정의합니다.


 // Create a new blog post app.post("/posts", async (req, res) => { const { title, description, author } = req.body; try { const doc = await db.insert({ title, description, author, createdAt: new Date(), updatedAt: new Date(), }); res.json({ id: doc.id, rev: doc.rev }); } catch (err) { console.error(err); res.status(500).send("Error creating post"); } }); // Get all blog posts app.get("/posts", async (req, res) => { try { const docs = await db.list({ include_docs: true }); res.json(docs.rows); } catch (err) { console.error(err); res.status(500).send("Error retrieving posts"); } }); // Get a specific blog post app.get("/posts/:id", async (req, res) => { const { id } = req.params; try { const doc = await db.get(id); res.json(doc); } catch (err) { console.error(err); res.status(404).send("Post not found"); } }); // Update a blog post app.put("/posts/:id", async (req, res) => { const { id } = req.params; const { title, description } = req.body; try { await db.insert({ _id: id, title, description, updatedAt: new Date(), }); res.json({ message: "Post updated successfully" }); } catch (err) { console.error(err); res.status(500).send("Error updating post"); } }); // Delete a blog post app.delete("/posts/:id", async (req, res) => { const { id } = req.params; try { await db.destroy(id); res.json({ message: "Post deleted successfully" }); } catch (err) { console.error(err); res.status(500).send("Error deleting post"); } }); app.listen(port, () => { console.log(`Blogpost app listening on port ${port}`); });


로컬에서 테스트하기:

프로젝트의 기능과 견고성을 보장하려면 철저한 테스트가 중요합니다. 테스트 프로세스를 안내하는 샘플 API 문서는 다음과 같습니다.

API 문서

기본 URL :

서버가 포트 3000에서 로컬로 실행되고 있다고 가정하면 API의 기본 URL은 다음과 같습니다.

 http://localhost:3000

API 엔드포인트:

새 블로그 게시물 만들기

  • 끝점 : POST /posts

  • 설명 : 새 블로그 게시물을 만듭니다.

  • 요청 본문 :

     { "title": "String", "description": "String", "author": "String" }
  • :

     POST http://localhost:3000/posts { "title": "Sample Title", "description": "Sample Description", "author": "John Doe" }

모든 블로그 게시물 가져오기

  • 엔드포인트 : GET /posts

  • 설명 : 모든 블로그 게시물을 검색합니다.

  • 응답 :

     [ { "id": "String", "key": "String", "value": { "rev": "String" }, "doc": { "_id": "String", "_rev": "String", "title": "String", "description": "String", "author": "String", "createdAt": "Date", "updatedAt": "Date" } } ]
  • :

     GET http://localhost:3000/posts

특정 블로그 게시물 얻기

  • 엔드포인트 : GET /posts/:id

  • 설명 : 특정 블로그 게시물을 해당 ID로 검색합니다.

  • 매개변수 :

    • id : 블로그 게시물의 ID입니다.
  • 응답 :

     { "_id": "String", "_rev": "String", "title": "String", "description": "String", "author": "String", "createdAt": "Date", "updatedAt": "Date" }
  • :

     GET http://localhost:3000/posts/your-post-id

블로그 게시물 업데이트

  • 엔드포인트 : PUT /posts/:id

  • 설명 : 특정 블로그 게시물을 해당 ID로 업데이트합니다.

  • 매개변수 :

    • id : 블로그 게시물의 ID입니다.
  • 요청 본문 :

     { "title": "String", "description": "String" }
  • :

     PUT http://localhost:3000/posts/your-post-id { "title": "Updated Title", "description": "Updated Description" }

블로그 게시물 삭제

  • 엔드포인트 : DELETE /posts/:id

  • 설명 : 특정 블로그 게시물을 해당 ID로 삭제합니다.

  • 매개변수 :

    • id : 블로그 게시물의 ID입니다.
  • :

     DELETE http://localhost:3000/posts/your-post-id


GET , PUTDELETE 요청을 테스트할 때 your-post-id 블로그 게시물의 실제 ID로 바꾸세요.

4단계: Node.js 애플리케이션 Docker화

Docker Hub 계정이 필요합니다. 아직 만들지 않았다면 Docker Hub에 등록하세요.

로컬 머신에 Docker가 설치되어 실행 중인지 확인하세요.

Docker화된 앱을 Docker Hub에 푸시하는 단계:

  • Node.js 프로젝트의 루트 디렉터리에 Dockerfile 을 만듭니다 .
 # Use an official Node.js runtime as the base image FROM node:16 # Set the working directory in the container WORKDIR /usr/src/app # Copy package.json and package-lock.json to the working directory COPY package*.json ./ # Install app dependencies RUN npm install # Copy the rest of the application files to the working directory COPY . . # Expose the port the app runs on EXPOSE 3000 # Define the command to run the app CMD ["node", "blog.js"]
  • Docker 이미지에 태그 지정: 터미널/명령 프롬프트를 열고 Dockerfile이 있는 Node.js 애플리케이션의 루트 디렉터리로 이동합니다.


다음 명령을 실행하여 Docker 이미지를 빌드하고 Docker Hub 사용자 이름과 원하는 리포지토리 이름으로 태그를 지정합니다.


 docker build -t your-docker-username/blogpost-app:latest .

your-docker-username Docker Hub 사용자 이름으로 바꾸고 blogpost-app 원하는 저장소 이름으로 바꾸세요.


다음과 비슷한 응답을 받게 됩니다.

 [+] Building 1.1s (10/10) FINISHED docker:desktop-linux => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 489B 0.0s => [internal] load metadata for docker.io/library/node:16 1.0s => [1/5] FROM docker.io/library/node:16@sha256:f77a1aef2da8d83e45ec990f45df50f1a286c5fe8bbfb8c6e4246c6389705c0b 0.0s => [internal] load build context 0.0s => => transferring context: 45.31kB 0.0s => CACHED [2/5] WORKDIR /usr/src/app 0.0s => CACHED [3/5] COPY package*.json ./ 0.0s => CACHED [4/5] RUN npm install 0.0s => CACHED [5/5] COPY . . 0.0s => exporting to image 0.0s => => exporting layers 0.0s => => writing image sha256:c5f046a9b99389aea6bf3f503e9b05cce953daf1b3f77ee5fb3f7469dc36c709 0.0s => => naming to docker.io/wise4rmgod/blogpost-app:latest


  • Docker Hub에 로그인: 다음 명령을 실행하여 Docker Hub 계정으로 Docker 클라이언트를 인증합니다.
 docker login


메시지가 나타나면 Docker Hub 사용자 이름과 비밀번호를 입력하세요.

 Authenticating with existing credentials... Login Succeeded


  • Docker 이미지를 Docker Hub에 푸시: 로그인한 후 다음 명령을 사용하여 태그가 지정된 Docker 이미지를 Docker Hub 저장소에 푸시하세요.
 docker push your-docker-username/blogpost-app:latest

이 명령은 지정된 리포지토리 아래의 Docker Hub에 로컬 이미지를 업로드합니다.


  • 푸시 확인: 웹에서 Docker Hub 계정으로 이동하고 리포지토리로 이동하여 Docker 이미지가 성공적으로 푸시되었는지 확인합니다.

    Docker 클라우드 대시보드



 aptible deploy --app reactgame --docker-image wise4rmgod/blogpost-app --private-registry-username wise4rmgod --private-registry-password H$(_tS+W~ZBST63

5단계: 적절한 배포

이 튜토리얼에서는 귀하가 Aptible 플랫폼에서 환경 , 애플리케이션 , 엔드포인트데이터베이스 설정에 대한 기본 지식을 가지고 있다고 가정합니다. 이 튜토리얼에서는 CouchDB를 데이터베이스로 활용하고 배포를 위해 Direct Docker를 사용합니다.


  • 다음 명령을 사용하여 CLI를 통해 Aptible에 로그인합니다.
 aptible login


이메일과 비밀번호를 입력하라는 메시지가 표시됩니다. 성공하면 다음과 유사한 응답을 받게 됩니다.

 Token written to /Users/wisdomnwokocha/.aptible/tokens.json This token will expire after 6 days, 23 hrs (use --lifetime to customize)


  • 이제 다음 명령을 사용하여 앱을 배포합니다.

통사론:

 aptible deploy --app <app name> --docker-image <docker image in cloud>


다음은 명령의 예입니다.

 aptible deploy --app reactgame --docker-image wise4rmgod/blogpost-app


다음과 유사한 응답을 받게 됩니다.

 INFO -- : Starting App deploy operation with ID: 61135861 INFO -- : Deploying without git repository INFO -- : Writing .aptible.env file... INFO -- : Fetching app image: wise4rmgod/blogpost-app... INFO -- : Pulling from wise4rmgod/blogpost-app INFO -- : 26ee4ff96582: Pulling fs layer INFO -- : 446eab4103f4: Pulling fs layer INFO -- : 2e3c22a0f840: Pulling fs layer INFO -- : a7ab8ad9b408: Pulling fs layer INFO -- : 3808fdf0c601: Pulling fs layer INFO -- : ab9e4075c671: Pulling fs layer INFO -- : 362360c8cef6: Pulling fs layer INFO -- : 928b5d11ac66: Pulling fs layer INFO -- : dc87e077ac61: Pulling fs layer INFO -- : f108e80f4efc: Pulling fs layer INFO -- : 84ac53840ac8: Pulling fs layer INFO -- : e81f21b79a1f: Pulling fs layer INFO -- : 2e3c22a0f840: Downloading: 523 KB / 49.8 MB INFO -- : 446eab4103f4: Downloading: 173 KB / 16.6 MB INFO -- : 26ee4ff96582: Downloading: 483 KB / 47 MB INFO -- : 2e3c22a0f840: Downloading: 25.7 MB / 49.8 MB INFO -- : a7ab8ad9b408: Downloading: 528 KB / 175 MB INFO -- : ab9e4075c671: Downloading: 355 KB / 33.4 MB INFO -- : a7ab8ad9b408: Downloading: 35.3 MB / 175 MB INFO -- : 26ee4ff96582: Pull complete INFO -- : 446eab4103f4: Pull complete INFO -- : 2e3c22a0f840: Pull complete INFO -- : a7ab8ad9b408: Downloading: 71.2 MB / 175 MB INFO -- : a7ab8ad9b408: Downloading: 106 MB / 175 MB INFO -- : a7ab8ad9b408: Downloading: 142 MB / 175 MB INFO -- : a7ab8ad9b408: Pull complete INFO -- : 3808fdf0c601: Pull complete INFO -- : ab9e4075c671: Pull complete INFO -- : 362360c8cef6: Pull complete INFO -- : 928b5d11ac66: Pull complete INFO -- : dc87e077ac61: Pull complete INFO -- : f108e80f4efc: Pull complete INFO -- : 84ac53840ac8: Pull complete INFO -- : e81f21b79a1f: Pull complete INFO -- : Digest: sha256:de9d04d069ca89ebdb37327365a815c88cd40d90cbc5395cc31c351fff1206dd INFO -- : Status: Downloaded newer image for wise4rmgod/blogpost-app:latest INFO -- : No Procfile found in git directory or /.aptible/Procfile found in Docker image: using Docker image CMD INFO -- : No .aptible.yml found in git directory or /.aptible/.aptible.yml found in Docker image: no before_release commands will run INFO -- : Pushing image dualstack-v2-registry-i-0a5ec8cff8e775b34.aptible.in:46022/app-63213/72184c41-7dc6-4313-b10e-749125f72577:latest to private Docker registry... INFO -- : The push refers to repository [dualstack-v2-registry-i-0a5ec8cff8e775b34.aptible.in:46022/app-63213/72184c41-7dc6-4313-b10e-749125f72577] INFO -- : dd387bc6b362: Pushed INFO -- : 586bd9d5efcf: Pushed INFO -- : 8ae0c889ca84: Pushed INFO -- : c91ec53bcc27: Pushing: 522 KB / 93.6 MB INFO -- : aec897bac4f0: Pushed INFO -- : 0ead224631d3: Pushed INFO -- : ad3b30eb29d3: Pushing: 542 KB / 444 MB INFO -- : 2a7587eb01b6: Pushing: 544 KB / 137 MB INFO -- : be36d2a441aa: Pushed INFO -- : 03f6e3800bbe: Pushed INFO -- : a10e482288d1: Pushing: 338 KB / 30.7 MB INFO -- : f9cfc9f6b603: Pushing: 513 KB / 103 MB INFO -- : c91ec53bcc27: Pushing: 31.3 MB / 93.6 MB INFO -- : c91ec53bcc27: Pushing: 62.7 MB / 93.6 MB INFO -- : ad3b30eb29d3: Pushing: 44.5 MB / 444 MB INFO -- : 2a7587eb01b6: Pushing: 34.4 MB / 137 MB INFO -- : a10e482288d1: Pushed INFO -- : ad3b30eb29d3: Pushing: 88.9 MB / 444 MB INFO -- : f9cfc9f6b603: Pushing: 34.6 MB / 103 MB INFO -- : 2a7587eb01b6: Pushing: 68.9 MB / 137 MB INFO -- : ad3b30eb29d3: Pushing: 133 MB / 444 MB INFO -- : f9cfc9f6b603: Pushing: 70.2 MB / 103 MB INFO -- : c91ec53bcc27: Pushed INFO -- : 2a7587eb01b6: Pushing: 103 MB / 137 MB INFO -- : ad3b30eb29d3: Pushing: 178 MB / 444 MB INFO -- : ad3b30eb29d3: Pushing: 224 MB / 444 MB INFO -- : 2a7587eb01b6: Pushed INFO -- : f9cfc9f6b603: Pushed INFO -- : ad3b30eb29d3: Pushing: 270 MB / 444 MB INFO -- : ad3b30eb29d3: Pushing: 312 MB / 444 MB INFO -- : ad3b30eb29d3: Pushing: 355 MB / 444 MB INFO -- : ad3b30eb29d3: Pushing: 401 MB / 444 MB INFO -- : ad3b30eb29d3: Pushed INFO -- : latest: digest: sha256:de9d04d069ca89ebdb37327365a815c88cd40d90cbc5395cc31c351fff1206dd size: 2841 INFO -- : Pulling from app-63213/72184c41-7dc6-4313-b10e-749125f72577 INFO -- : Digest: sha256:de9d04d069ca89ebdb37327365a815c88cd40d90cbc5395cc31c351fff1206dd INFO -- : Status: Image is up to date for dualstack-v2-registry-i-0a5ec8cff8e775b34.aptible.in:46022/app-63213/72184c41-7dc6-4313-b10e-749125f72577:latest INFO -- : Image app-63213/72184c41-7dc6-4313-b10e-749125f72577 successfully pushed to registry. INFO -- : STARTING: Register service cmd in API INFO -- : COMPLETED (after 0.28s): Register service cmd in API INFO -- : STARTING: Derive placement policy for service cmd INFO -- : COMPLETED (after 0.15s): Derive placement policy for service cmd INFO -- : STARTING: Create new release for service cmd INFO -- : COMPLETED (after 0.24s): Create new release for service cmd INFO -- : STARTING: Schedule service cmd .. INFO -- : COMPLETED (after 13.49s): Schedule service cmd INFO -- : STARTING: Stop old app containers for service cmd INFO -- : COMPLETED (after 0.0s): Stop old app containers for service cmd INFO -- : STARTING: Start app containers for service cmd INFO -- : WAITING FOR: Start app containers for service cmd INFO -- : WAITING FOR: Start app containers for service cmd INFO -- : COMPLETED (after 18.4s): Start app containers for service cmd INFO -- : STARTING: Delete old containers for service cmd in API INFO -- : COMPLETED (after 0.0s): Delete old containers for service cmd in API INFO -- : STARTING: Commit app containers in API for service cmd INFO -- : COMPLETED (after 0.26s): Commit app containers in API for service cmd INFO -- : STARTING: Commit service cmd in API INFO -- : COMPLETED (after 0.13s): Commit service cmd in API INFO -- : STARTING: Cache maintenance page INFO -- : COMPLETED (after 0.28s): Cache maintenance page INFO -- : STARTING: Commit app in API INFO -- : COMPLETED (after 0.19s): Commit app in API INFO -- : App deploy successful.


  • Aptible Dashboard를 방문하여 배포가 성공했는지 확인하세요.

  • 대시보드에서 엔드포인트 탭을 클릭하고 엔드포인트를 저장합니다. 이를 통해 데이터베이스를 공용 인터넷에 노출할 수 있습니다.

  • 새 엔드포인트를 생성하려면 다음 화면에서 엔드포인트 추가를 클릭하세요.

결론

이 포괄적인 튜토리얼은 Node.js, CouchDB 및 Aptible을 사용하여 블로그 게시물 애플리케이션을 구축, 배포 및 관리하는 데 도움이 됩니다.


필수 도구 및 기술 설정, 블로그 게시물 애플리케이션의 백엔드 제작, 애플리케이션 도킹화, Docker 이미지를 Docker Hub로 푸시, 애플리케이션을 Aptible에 배포하는 기본 사항을 파악했습니다.


이 포괄적인 튜토리얼을 완료하고 Aptible을 사용한 클라우드 네이티브 애플리케이션 개발 여정을 완료한 것을 축하합니다!