Docker で Zenn の執筆環境を作ってみる
なんで?
Docker for Mac
が Apple Silicon に対応した。
ローカルで Markdown ゴリゴリ書いてもいいんだけど、Docker
のことを学ぶついでに。
環境
- Macbook Air (M1, 2020)
- Docker for Mac: 3.3.1
Docker for Mac
のインストール
まあ、Homebrew-cask
で入れるほうが丸かろう。
Homebrew
のインストール
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
...
$ export PATH=/opt/homebrew/bin:$PATH
$ brew --help
Example usage:
brew search TEXT|/REGEX/
brew info [FORMULA|CASK...]
brew install FORMULA|CASK...
brew update
brew upgrade [FORMULA|CASK...]
brew uninstall FORMULA|CASK...
brew list [FORMULA|CASK...]
Troubleshooting:
brew config
brew doctor
brew install --verbose --debug FORMULA|CASK
Contributing:
brew create URL [--no-fetch]
brew edit [FORMULA|CASK...]
Further help:
brew commands
brew help [COMMAND]
man brew
https://docs.brew.sh
Docker for Mac
のインストール
外部からインスコする App は $HOME/Applications
に入れておきたい人なので。
$ brew install --cask --appdir=$HOME/Applications docker
Docker
起動
インスコした Docker for Mac
を起動、「コマンド入れたいから許可してやー」のダイアログが表示されるのでええんやでする。
暫し待つと Docker
周りのコマンドがインスコされる。
$ which docker
/usr/local/bin/docker
$ docker version
Client: Docker Engine - Community
Cloud integration: 1.0.12
Version: 20.10.5
API version: 1.41
Go version: go1.13.15
Git commit: 55c4c88
Built: Tue Mar 2 20:13:00 2021
OS/Arch: darwin/amd64 (rosetta)
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.5
API version: 1.41 (minimum version 1.12)
Go version: go1.13.15
Git commit: 363e9a8
Built: Tue Mar 2 20:16:48 2021
OS/Arch: linux/arm64
Experimental: false
containerd:
Version: 1.4.4
GitCommit: 05f951a3781f4f2c1911b05e61c160e9c30eaa8e
runc:
Version: 1.0.0-rc93
GitCommit: 12644e614e25b05da6fd08a38ffa0cfe1903fdec
docker-init:
Version: 0.19.0
GitCommit: de40ad0
うん、大丈夫そう。
Container を作る
というわけで、初めての Container 作り開始。
右も左も分からないので素直にググってみる。
どうやら、Dockerfile
とやらを作らないといけないらしい。
Dockerfile を作る
Visual Studio Code
Lover なので VSCode
に Docker と Remote - Containers の拡張を突っ込んで Dockerfile を作ってみる。
Zenn CLI は nodejs
を利用する形らしい。nodejs
を利用できる Container image を使うことにした。
この記事 によると、Alpine(?)よりも Distroless(?)のほうが良いらしい。
が、どうやら Distroless では /bin/bash
がインストールされていないらしく、Remote - Containers
では起動することができなかった。
現時点で aarch64
(arm64)に対応しているのが node:buster
とのこと (参考) なので、それをベースの image に選択した。
# Base image
FROM node:15.14.0-buster-slim
# Maintainer
LABEL maintainer="nagakuta <xxx@example.com>"
Remote - Containers
で動いたことを確認、よしよし。
Zenn CLI を入れる
本題。Zenn CLI を入れる。
先程の Dockerfile で build 時に Zenn CLI をインスコするようにする。
…と、ここで問題発生。どうやら何も考えずに npm install
を Container 上で行うとハチャメチャに遅いらしい。
とのことで解決策をググる。ヒットしたのは「npm install
前に registry を http://registry.npmjs.org/
に指定しておく」だった(参考)。
# Base image
FROM node:15.14.0-buster-slim
# Maintainer
LABEL maintainer="nagakuta <xxx@example.com>"
+# Workdir
+WORKDIR /workspace
+# Copy files into container
+COPY articles/ books/ README.md .
+# Install Zenn CLI
+ENV NODE_ENV=production
+RUN npm config set registry http://registry.npmjs.org/
+RUN npm install -g npm --verbose
+RUN npm install --production zenn-cli --verbose
version: '3.8'
services:
build:
context: .
dockerfile: zenn/Dockerfile
volumes:
- ..:/workspace:cached
ports:
- 3000:3000
command: /bin/sh -c "while sleep 1000; do :; done"
docker build
時に npx zenn init
してみたが、なぜか RUN npx zenn init
した結果が Container のどこにも見当たらない。
ログ的には実行しているっぽいので、どこかしらのフォルダには npx zenn init
した結果が展開されているはずなのだが…
まあ、Container 内で npx zenn init
を打てばいいっちゃいいのでそこまで手間ではないし、基本的に Mac の local にリポジトリを clone してから build するから問題ないんだけど、モヤッとする。
Docker
ときちんと向き合ってみる
ここで、Dockerfile
と docker-compose.yml
をきちんと見つめ直してみる(ほぼほぼコピペだったので)。
Dockerfile
- COPY はファイルが増えたときに記述量が増えていくだろう。
→ 管理が面倒になるのが目に見えているので別の方法を考える。 - なんと、RUN 命令を実行するたびにイメージレイヤ(?)が生成されて少し容量が増えるらしい。
→ RUN はまとめるようにする。
これらをまとめると、
# Base image
FROM node:15.14.0-buster-slim
# Maintainer
LABEL maintainer="nagakuta <xxx@example.com>"
# Workdir
WORKDIR /workspace
-# Copy files into container
-COPY articles/ books/ README.md .
# Install Zenn CLI
ENV NODE_ENV=production
-RUN npm config set registry http://registry.npmjs.org/
-RUN npm install -g npm --verbose
-RUN npm install --production zenn-cli --verbose
+RUN npm config set registry http://registry.npmjs.org && \
+ npm install --production zenn-cli --verbose && \
+ rm /workspace/package*.json
docker-compose.yml
- volumes でディレクトリ全体を永続化している。
→ volumes は Container 内に永続化したいファイルのみをマウント(?)するらしい。
ってことで、修正。
version: '3.8'
services:
build:
context: .
dockerfile: zenn/Dockerfile
volumes:
- - ..:/workspace:cached
+ - ../articles:/workspace/articles:cached
+ - ../books:/workspace/books:cached
+ - ../README.md:/workspace/README.md:cached
ports:
- 3000:3000
command: /bin/sh -c "while sleep 1000; do :; done"
これで自分が達成したかった「必要なファイルのみが Container 内に送られている」ができた。嬉しい。