Zenn-CLIをDockerで構築しつつMakefileで快適に動かす

2 min読了の目安(約2200字TECH技術記事

きっかけ

ということで実際にやってみました。

前提

リポジトリの構成を以下[1]のようにします。

zenn-contents.git
├ articles -> Zenn-CLIで管理される記事ディレクトリ
├ books -> Zenn-CLIで管理される本ディレクトリ
├ CLI
│ ├ Dockerfile
│ └ package.json -> Zenn-CLIのバージョン管理に使用
├ docker-compose.yml
└ Makefile

コンテナ内の作業ディレクトリ構成

まずはDockerfiledocker-compose.ymlを以下の通り作成します。

Dockerfile

FROM node:12

WORKDIR /zenn

ADD package.json /zenn/package.json
RUN npm install

EXPOSE 8000

ENTRYPOINT [ "npx", "zenn" ]
CMD [ "preview" ]

公式の手順のようにしても良かったのですが、複数のPCで編集できるようにすることを考えるとZenn-CLIのバージョンも管理した方がいいと思いpackage.jsonをgit管理することにしています。

また、ENTRYPOINTCMDを組み合わせることでコンテナ実行時の引数をよしなに省略することができます。

docker-compose.yml

version: '3.1'
services:
  zenn-cli:
    build:
      context: ./CLI
    volumes:
      - ./articles:/zenn/articles
      - ./books:/zenn/books
    working_dir: /zenn
    ports: 
      - 127.0.0.1:8000:8000

articlesbooksだけをマウントすることで記事と本のみをホスト-コンテナ間で共有でき、余計なファイルが行ったり来たりするのを防げます。

実際に動かしてみる

まずdocker-compose upと打って以下のようになることを確認します。

zenn-cli_1  | 👀Preview on http://localhost:8000

その後、ブラウザでhttp://localhost:8000/を開いてZenn Editorが出れば成功です。

ただし、このままだとターミナルがZenn-CLIに独占されてしまうので、今後はdocker-compose up -dでデーモンとして動かすようにします。

Makefileでコマンドを簡略化

ここに打つのが面倒なコマンドがあるじゃろ?

( ^ω^)
docker-compose up -d

これをこうして…
( ^ω^)
≡⊃⊂≡

こうじゃ
( ^ω^)
make

ここに覚えにくいコマンドがあるじゃろ?

( ^ω^)
docker-compose run zenn-cli new:article

これをこうして…
( ^ω^)
≡⊃⊂≡

こうじゃ
( ^ω^)
make article

up:
	docker-compose up -d

down:
	docker-compose down

article:
	docker-compose run zenn-cli new:article

book:
	docker-compose run zenn-cli new:book

shell:
	docker-compose run --entrypoint bash zenn-cli

update:
	@jq ".dependencies[\"zenn-cli\"] = \"`docker-compose run --entrypoint npm zenn-cli show zenn-cli version | tr -d '\r'`\"" CLI/package.json > CLI/tmp.json
	@mv CLI/tmp.json CLI/package.json
	docker-compose build

終わりに

プレビューを表示したまま記事のmdファイルを更新するとリアルタイムでプレビューに反映されるので捗りますね(・∀・)
更にGitHubで管理できる->GitHub Actionsが使える->CIでTextLintが簡単に動かせる!
ってことでTextLintも組み込めば快適な執筆環境が作れそうですね😇

脚注
  1. 厳密には.gitignoreREADME.mdもありますが本質ではないのでここでは割愛しています ↩︎