📑

CodespacesをDockerfileでカスタマイズする

2023/02/07に公開

この記事について

ZennブログはGitHubリポジトリと連携可能!
https://zenn.dev/zenn/articles/connect-to-github

なので、GitHub Codespacesを使った執筆も可能となります。
記事公開までの大まかな流れは以下の通り。

  1. Zenn CLIで記事の雛形を作成(Markdownファイル)
  2. Markdownファイルを更新
  3. Zenn CLIで作成した記事のプレビューを確認
  4. リポジトリにpushするとZenn側で記事が新規作成される

上記のように、GitHub連携した状態で記事を作成するにはZenn CLIをインストールした環境が必要です。

まぁ、インストール自体は簡単なんですが、せっかくなのでこれを題材として
Dockerfileで定義してCodespacesの環境をカスタマイズしてみよう!
といった内容になります。

Dockerfile化のメリット

環境の情報をDockerfileに記述することで、以下のようなメリットがあります。

  • 公式イメージをベースにカスタマイズできる
  • OS環境構成(カーネル除く)をコードで可視化できる
  • GitでOS環境構成(カーネル除く)の変更履歴を管理しやすい

そして僕が一番推している点は、自分以外の他のメンバーでも、コンテナ実行環境さえあればDockerfileからその環境をすぐに構築可能ということです!

Zennブログ執筆環境の構築

GitHubとの連携

こちらの手順に従い設定を進めます。

ただし、リポジトリを作成する際Add a README fileにチェックを入れるなどして初期化していたほうが、あとからCodespacesを利用しやすいです。

Codespacesでの作業

連携したリポジトリを開き、緑色のボタンからCodespacesを起動します。

開発環境が立ち上がったら、以下のドキュメントを参考に設定ファイルを作成していきます。

https://docs.github.com/ja/codespaces/setting-up-your-project-for-codespaces/adding-a-dev-container-configuration/introduction-to-dev-containers

Codespacesでは、Gitリポジトリのトップに.devcontainerというディレクトリを作成し、その中にdevcontainer.jsonファイルに定義することで、起動時の環境をカスタマイズ可能とのこと。

各種ファイルを作成

.devcontainer/**/devcontainer.json(サブフォルダがあってもいい)を以下内容で作ることで、環境をDockerfileからビルドするようになります。

devcontainer.json
{
    "build": { "dockerfile": "Dockerfile" }
}

次に、同一フォルダにDockerfileを以下内容で作成します。
Zenn CLIのインストールにはnpmが必要とのことで、ベースイメージはNode.jsの公式を選びました。
また、イメージを軽量化したいのでalpineのタグを指定。

Dockerfile
FROM node:19-alpine
WORKDIR /work
RUN npm init --yes && npm install zenn-cli

最終的に以下のフォルダ構成になります。

.devcontainer/
└── zenn-cli
    ├── devcontainer.json
    └── Dockerfile

Dockerfileのビルド確認

Dockerfileがある場所でdocker buildコマンドを実行し、イメージが問題なく作成されるかを確認しておきます。

workspaces/zenn-docs/.devcontainer/zenn-cli (feature_zenn-cli-test) $ docker build .
[+] Building 5.5s (7/7) FINISHED                                                                                                        
 => [internal] load build definition from Dockerfile                                                                               0.1s
 => => transferring dockerfile: 116B                                                                                               0.0s
 => [internal] load .dockerignore                                                                                                  0.1s
 => => transferring context: 2B                                                                                                    0.0s
 => [internal] load metadata for docker.io/library/node:19-alpine                                                                  0.8s
 => CACHED [1/3] FROM docker.io/library/node:19-alpine@sha256:72b0f918ad76b5ef68c6243869fab5800d7393c1dcccf54ef00958c2abc8164a     0.0s
 => [2/3] WORKDIR /work                                                                                                            0.2s
 => [3/3] RUN npm init --yes && npm install zenn-cli                                                                               3.6s
 => exporting to image                                                                                                             0.7s 
 => => exporting layers                                                                                                            0.7s 
 => => writing image sha256:3576c0767e05f9c571198a43b68f23d4f2f67d91d1312d0879624d041c0e9edc                                       0.0s 

成功しました!
ここまでできたら、それぞれリモートリポジトリにpushしておきます。

Zenn CLIの動作確認

これまで使っていたCodespace環境は一旦削除し、新たな環境を立ち上げます。
(左上のメニューからMy Codespacesを選択すると環境の一覧画面に飛ぶので、そこから消す)

まずは記事の雛形を作成。--slugオプションでファイル名を指定してます。

/workspaces/zenn-docs (feature_zenn-cli-test) $ npx zenn new:article --slug article_yyyymmdd
created: articles/article_yyyymmdd.md

この時点で、Zenn CLIが機能していることを確認できました!
続いてMarkdownファイルを更新し、プレビューを試してみます。

/workspaces/zenn-docs (feature_zenn-cli-test) $ npx zenn preview
👀 Preview: http://localhost:8000

ここで、あれ…localhostって行けるのかな…と思いましたが、Codespacesのポートフォワード機能でうまくやってくれました!
https://docs.github.com/ja/codespaces/developing-in-codespaces/forwarding-ports-in-your-codespace

無事にプレビューも確認できました。

まとめ

DockerfileでCodespacesの環境をカスタマイズできました。
これで、明示的に開発環境をコードで宣言して即開発可能な環境を作るイメージが伝わったかと思います!

ただしデメリットもあるようで、カスタマイズしたコンテナがStorageの枠を消費してしまうようです…。

https://zenn.dev/tktcorporation/articles/49505ff65ee384#codespace-コンテナでの消費

なのでイメージサイズには気をつけたいところですが、いざとなればローカルでも同じ環境作れると思うと安心です。
ちなみに標準で使われるイメージのDockerfileはこちら。
https://github.com/devcontainers/images/blob/main/src/universal/.devcontainer/Dockerfile
色々入っててかつ、標準だとStorageにカウントされないので、状況に応じて使い分けできればいいかなと思います。

Discussion