Next.js+NestJS+HackMD(CodiMD)でブログを構築した話

6 min read

はじめに

今回は本ブログにも使用しているシステムであるNext.js + NestJS + HackMD(CodiMD)を一般化し、誰でも使用できるようにしたので紹介したいと思います。 一般化する際にVercel社が公式にリリースしている、Blog Starter Kitをベースに作成しています。

リンク関連

リポジトリ

https://github.com/MuNeNICK/nextjs-nestjs-codimd

サンプルサイト

https://next-app--main--next-nest-codimd--munenick.coder.munenick.me/

インストール方法

Docker環境の構築

各自docker-compose環境を構築してください。 以下参考 https://www.munenick.me/blog/centos8-stream-docker

gitクローン

以下のコマンドを使用してリポジトリからクローンを行ってください。

git clone https://github.com/MuNeNICK/nextjs-nestjs-codimd

初回セットアップ

初回セットアップをする際には少し工夫が必要です。

entrypoint.shの書き換え

frontendフォルダ及びbackendフォルダにはそれぞれentrypoint.shというフォルダが存在します。 それらを以下のように書き換えます。

frontendの方のentrypoint.sh
#!/bin/bash

cd /usr/src/app

bash

# if grep next package.json >/dev/null; then
#     echo Next is EXIST.
# else
#     cd /usr/src/app
#     yarn create next-app --example blog-starter .
# fi

# while read line
# do
#   if grep "$line" package.json >/dev/null; then
#     echo $line is EXIST.
#   else
#     echo $line is NOT EXIST.
#     yarn add $line
#   fi
# done < /packages.txt


# if [ "$STATUS" == "development" ]; then
#   echo Starting in developer mode...
#   yarn dev
# elif [ "$STATUS" == "production" ]; then
#   echo Starting in production mode...
#   yarn build
#   yarn start
# else 
#   echo Incorrect environment variable.
# fi
backendの方のentrypoint.sh
#!/bin/bash

cd /usr/src/app
    
bash

# if grep nest package.json >/dev/null; then
#     echo Nest is EXIST.
# else
#     echo Nest is NOT EXIST.
#     git clone https://github.com/nestjs/typescript-starter.git .
#     yarn install
# fi

# while read line
# do
#   if grep "$line" package.json >/dev/null; then
#     echo $line is EXIST.
#   else
#     echo $line is NOT EXIST.
#     yarn add $line
#   fi
# done < /packages.txt


# if [ "$STATUS" == "development" ]; then
#   echo Starting in developer mode...
#   yarn prisma studio &
#   yarn start:dev
# elif [ "$STATUS" == "production" ]; then
#   echo Starting in production mode...
#   yarn start
# else 
#   echo Incorrect environment variable.
# fi

アプリケーションの構築

以下のコマンドで、アプリケーションの構築を行います

docker-compose up -d --build

必要パッケージのインストール

Next.js、NestJSのコンテナでそれぞれパッケージのインストールが必要です。 Next.jsでのパッケージのインストール

docker-compose exec next bash
yarn install

NestJSでのパッケージのインストール

docker-compose exec nest bash
yarn install

Dockerの停止

以下のコマンドでDockerを停止します。

docker-compose down

entrypoint.shの書き換え

entrypoint.shをもとに戻します。

docker-compose.ymlの書き換え

docker-compose.ymlのnext及びnestのenvironment欄に存在するSTATUSを以下のように書き換える。

  • production: サイトをリリースするときに使用する
    • Next.jsではビルドし、起動する
  • development: サイトを開発するときに使用する
    • 開発者モードで起動する
version: "3"

services:
  next:
    build:      
      context: .
      dockerfile: ./frontend/Dockerfile
    container_name: next-container
    hostname: next-server
    tty: true
    environment:
      - STATUS=production
      - WATCHPACK_POLLING=true
      - NEXT_PUBLIC_BACKEND_URL=${PUBLIC_BACKEND_URL}
      - NEXT_PUBLIC_HACKMD_URL=${PUBLIC_HACKMD_URL}
    ports:
      - 3000:3000
    volumes:
      - ./frontend/app:/usr/src/app
    restart: always

  nest:
    build:      
      context: .
      dockerfile: ./backend/Dockerfile
    container_name: nest-container
    hostname: nest-server
    tty: true
    environment:
      - STATUS=production
      - DATABASE_URL=${POSTGRES_URL}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - JWT_SECRET=${JWT_SECRET}
    ports:
      - 3001:3000
      - 5555:5555
    volumes:
      - ./backend/app:/usr/src/app
    restart: always

  codimd:
    build:      
      context: .
      dockerfile: ./codimd/Dockerfile
    container_name: codimd-container
    hostname: codimd-server
    environment:
      - CMD_DB_URL=${POSTGRES_URL}
      - CMD_DOMAIN=${PUBLIC_DOMAIN}
      - CMD_URL_PATH=${CODIMD_PATH}
      - CMD_PROTOCOL_USESSL=true
      - CMD_IMAGE_UPLOAD_TYPE=filesystem
      - CMD_ALLOW_EMAIL_REGISTER=false
      - CMD_ALLOW_ANONYMOUS=true
    depends_on:
      - postgres
    ports:
      - "3002:3000"
    volumes:
      - upload-data:/home/hackmd/app/public/uploads
    restart: always

  postgres:
    image: postgres:11.6-alpine
    container_name: postgres-container
    hostname: postgres-server
    environment:
      - POSTGRES_USER=codimd
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=codimd
    volumes:
      - "database-data:/var/lib/postgresql/data"
    restart: always

volumes:
  database-data: {}
  upload-data: {}

.envファイルの書き換え

それぞれ自身の環境にあったパラメータに書き換えてください。 本サイトではJWT Tokenが必要になります。 以下のコマンドをTokenの生成が可能です。

node -e "console.log(require('crypto').randomBytes(256).toString('base64'));"
## Arbitrary parameters. Rewrite as appropriate.

## POSTGRES-related parameters
POSTGRES_PASSWORD=ChangeMe
POSTGRES_URL=postgres://codimd:${POSTGRES_PASSWORD}@postgres/codimd

## CODIMD-related parameters
CODIMD_PASSWORD=ChangeMe
## If subdirectories are used, describe their paths
CODIMD_PATH=

## URL-related parameters
PUBLIC_DOMAIN=
PUBLIC_FRONTEND_URL=
PUBLIC_BACKEND_URL=
PUBLIC_HACKMD_URL=

## JWT Token If you generate a Token 
## node -e "console.log(require('crypto').randomBytes(256).toString('base64'));"
JWT_SECRET=""

Dockerの起動

以下のコマンドでDockerを起動する

docker-compose up -d --build

以上がこのリポジトリの使用方法になります。

サンプルサイトの使用方法

サンプルサイトの使用方法を説明します。

ログイン機能

https://next-app--main--next-nest-codimd--munenick.coder.munenick.me/login にアクセスし、EMAIL、PASSWORDにそれぞれ

test@example.com
testtesttest

と入力することでログインが可能です。

ダッシュボード機能

ダッシュボードページを用意しています。 new postsをクリックすることで、新規投稿ページに移動します。 リストに表示されているリンクをクリックすることで、それぞれのページに移動することができます。

新規投稿機能

ダッシュボードからnew postsをクリックするか以下のリンクにアクセスすることで新規投稿が可能です。 https://next-app--main--next-nest-codimd--munenick.coder.munenick.me/new

CodiMDを開くとデフォルトで以下が記述されています。

---
title: 'Enter title-slug here'
displayTitle: 'Enter display title here'
excerpt: 'Blog Description'
coverImage: '/assets/blog/hello-world/cover.jpg'
date: '2020-03-16T05:35:07.322Z'
author:
  name: Tim Neutkens
  picture: '/assets/blog/authors/tim.jpeg'
ogImage:
  url: '/assets/blog/hello-world/cover.jpg'
---
  • title: slug名、URLに使用される。 例:hello-world
  • displayTitle: 表示タイトル名、ブログのタイトルに該当する。
  • excerpt: 記事の説明欄
  • coverImage: カバー画像のパス
  • date: 投稿日時
  • author: 投稿者の名前と写真のパス
  • ogImage: OG画像に使用する画像のパス

各項目を書き換え、本文を記述したら右下のPostボタンで投稿が可能です。

編集機能

ログインをしている状態で記事を開くと右下にEditボタンが表示されます。

ログイン前

ログイン後

Editボタンを押すことで、記事の編集画面に移動することが可能です。

編集後、右下のViewボタンをクリックすることで編集を完了することができます。

削除機能

記事の編集画面に移動してください。

右下にDeleteボタンが表示されます。

Deleteボタンをクリックすることで、記事削除の確認画面が表示されます。 OKをクリックすることで、記事を削除することができます。

ログアウト機能

ダッシュボードに戻り、LOGOUTボタンをクリックすることでログアウトできます。

ログアウト後はEditボタンが表示されなくなります。

余談

Next.js + NestJS + HackMD(CodiMD)といったシステムでブログを作成した背景ですを少し説明しようと思います。 Next.jsでブログを作成する際にあたり、microCMSなどのクラウド型ヘッドレスを使用する例が多くありました。しかし、私はブログサイトを作成するにあたり、クラウドサービスを使用せずに作成したいと考えました。 そこで私はGrowiというOSSを思い出しました。これはwiki作成ソフトウェアでありHackMD(CodiMD)で編集が可能という特徴がありました。 これから着想を得て、iframe等でCodiMDを埋め込み、ヘッドレスCMS等を使用せずともブログ記事の管理ができないかと考え、本ブログを作成しました。