きれいな手順書をつくるための7つのポイント

インフラ

こんにちは。仁科(@nishina555)です。

エンジニアの業務では単純作業も多く存在し、日々どうやって自動化すればいいか試行錯誤しています。
しかし、自動化ができず、手順書を作成して手動でオペレーションする機会はどうしても存在するのも事実です。

そこで手順書を作成することになるのですが、手順書というのは決まったフォーマットがありませんし、人によって書き方は様々です。
今回はどうやったらきれいな手順書になるのか自分なりに色々調べて7つのポイントとしてまとめてみたので、その共有をしたいと思います。

7つのポイントまとめ

まず、結論を先に説明したいと思います。
きれいな手順書を書くためには以下の7つのポイントに気をつけるといいと思います。

  1. コマンドの先頭には「$」をおく
  2. コマンドの説明を「###」で記述する。
  3. チェックする項目については「->」で説明
  4. 期待値、具体的なコードは見出しをつけて分かりやすくする
  5. コマンドのパラメータや補足説明はコマンドの後に#で説明
  6. コマンドがケースによって変わるときはインデントして表現する
  7. コードブロックはなるべくまとめる

では、これからそれぞれのポイントについて詳細説明とサンプルを載せたいと思います。

コマンドの先頭には「$」をおく

手順書の中でどの行がコマンドを意味しているのかを識別させるために「$」をつけるようにします。

rootで実行する場合はプロンプトが「#」で表記されることが多いと思いますが、そうすると手順書の中でコメントアウトと見分けがつかなくなるので「$」で統一します。

その代わり、rootユーザーでの実行がわかるように「[root]」などと記述するようにします。

Before

command1
command2
command3
su

rootcommand1
rootcommand2

After

$ command1
$ command2
$ command3
$ su

[root]
$ rootcommand1
$ rootcommand2

コマンドの説明を「###」で記述する。

原則、各コマンドに対して説明を加えます。簡単なコマンドの場合はまとめて説明をするようにします。

Before

command1
command2
command3.1
command3.2

After

### コマンド1を実行
command1

### コマンド2を実行
command2

### コマンド3を実行
command3.1
command3.2

チェックする項目については「->」で説明

コマンドによってはターミナルなどで実行結果を確認するものも存在すると思います。
その場合、どのような結果を期待しているのか観点を明記します。

Before

pwd

After

pwd
-> /path/to/applicationにいることを確認

期待値、具体的なコードは見出しをつけて分かりやすくする

手順書において、具体的な内容を記述したり確認する場合があると思います。
例えばvimでファイルを編集したり、ファイル同士の差分を確認したりがそれにあたります。
そういった場合は見出しをつけることでどこからどこまでが該当範囲なのか分かりやすくさせます。

Before

vim hoge
hoge
fuga

diff hoge hoge.bk

After

vim hoge
#---------
hoge
fuga
#---------

diff hoge hoge.bk

コマンドのパラメータや補足説明はコマンドの後に「#」で説明

手順書を書く上で補足説明をしたい場合などがあると思います。その際は「#」で説明を加えます。

また、コマンドにオプションが存在したりコマンド自体が複雑な場合はその意味も補足として説明すると丁寧です。

補足説明を記述することで手順書をレビューする人もすぐに内容が理解できますし、他人がみても内容がわかる手順書となります。

Before

command -opt

After

command -opt
# -opt: ここにオプションの説明を書く

コマンドがケースによって変わるときはインデントして表現する

手順書によってはケースごとに実行するコマンドが変わるものもあると思います。
その場合はインデントすることで分岐を分かりやすくさせます。

ただし、分岐が多くなりすぎるとわかりにくくなるので、別の手順書に書くことをおすすめします。

Before

### ログイン
### 開発環境の場合
ssh dev
### 本番環境の場合
ssh prod

### ディレクトリの移動
cd /path/to/application

After

### ログイン
  ### 開発環境の場合
  ssh dev
  ### 本番環境の場合
  ssh prod

### ディレクトリの移動
cd /path/to/application

コードブロックはなるべくまとめる

手順書は上下を行き来するのではなく、なにも考えずに上から順番にコマンドを実行していく形が理想です。

しかし、コードブロックがいくつもあると自分がどこまで手順を終わらせたかが分かりにくくなります。ですので、コードブロックはなるべくまとめるようにします。

もし、処理項目でコマンドがカテゴライズできるのであれば、コードブロックで分けるのではなくコードブロック内の見出しで分け、なるべく一回のオペレーションは一つのコードブロックで完結するようにさせます。
例えば、「オペレーションするサーバー」「オペレーション日」などでコードブロックは分割するといいと思います。

Before

準備
command1
command2
リリース
command3
command4
リリース確認
command5
command6

After

------------------------------
■ 準備
------------------------------
command1
command2

------------------------------
■ リリース
------------------------------
command3
command4

------------------------------
■ リリース確認
------------------------------
command5
command6

サンプル

今まで説明した7つのポイントに気をつけて手順書を作成すると以下のような感じになります。

Dockerイメージのビルド・コンテナ起動@localhost

------------------------------
■雛形の作成
------------------------------

### アプリのディレクトリ作成・移動
$ mkdir rails-docker-starter
$ cd rails-docker-starter

### ファイルのコピー
$ ./init.sh /path/to/application
# docker-compose.dev.yml, Dockerfile.dev, .env.dev, database.ymlがコピーされる
# docker-compose.dev.yml -> docker-compose.yml にリネームされる
# Dockerfile.dev -> Dockerfileにリネームされる

### Gemfileの作成
$ echo "source 'https://rubygems.org'\ngem 'rails', '5.0.0.1'"> Gemfile

### イメージの構築
$ docker-compose build

### railsの雛形作成
  ### mysqlの場合
  $ docker-compose run --rm web bundle exec rails new . --force --database=mysql --skip-bundle -d
  # --rm: 実行後コンテナを削除
  # --force: ファイルが存在したら上書きする
  # -d: デーモン(バックグラウンド)実行

  ### postgresqlの場合
  $ docker-compose run --rm web bundle exec rails new . --force --database=postgresql --skip-bundle -d
  # --rm: 実行後コンテナを削除
  # --force: ファイルが存在したら上書きする
  # -d: デーモン(バックグラウンド)実行

### docker volumeの確認
$ docker volume ls
-> bundleとdbのvolumeが作成されていることを確認
#------------------------------
DRIVER              VOLUME NAME
local               railsdockerstarter_bundle_install
local               railsdockerstarter_db
#------------------------------  

### プロセス確認
$ docker ps
-> dbのプロセスが立ち上がっていることを確認
#------------------------------
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
462efa6ab9cf        mysql:5.7           "docker-entrypoint..."   4 minutes ago       Up 4 minutes        0.0.0.0:3306->3306/tcp   railsdockerstarter_db_1
#------------------------------

### databaseのconfigの編集
$ cp database.yml config/database.yml

### gitignoreのアップデート
$ echo "\n# Docker\n.env.dev" >> .gitignore
# .env.devに環境変数が書かれているため、.env.devを.gitignoreに追加

### datebase.ymlの設定に従って、データベースを作成する
$ docker-compose run web bundle exec rails db:create

------------------------------
■コンテナの作成
------------------------------

### コンテナを作成して起動する
$ docker-compose up -d
# -d: デーモン(バックグラウンド)実行

### コンテナ起動確認
docker ps
-> webとdbのプロセス実行されていることを確認
#------------------------------
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS                    NAMES
5b57c2dce81c        railsdockerstarter_web   "prehook 'ruby -v'..."   53 seconds ago      Up 52 seconds       0.0.0.0:3000->3000/tcp   railsdockerstarter_web_1
f6cc03baa3d7        mysql:5.7                "docker-entrypoint..."   55 seconds ago      Up 53 seconds       0.0.0.0:3306->3306/tcp   railsdockerstarter_db_1
#------------------------------

------------------------------
■起動したコンテナにログイン
------------------------------

### webコンテナにログインする
$ docker exec -it $WEB_CONTAINER_NAME /bin/bash
# 例. docker exec -it railsdockerstarter_web_1 /bin/bash
#
# コンテナにログインせずに直接コマンド実行したい場合、上記の/bin/bashの部分をコンテナで実行するコマンドに変更すればいい。
# 例. $ docker exec -it railsdockerstrater_web_1 bundle exec rails db
アプリケーションの起動@webコンテナ

### railsを実行する。その間ログも別ターミナルで確認しておくとよい
[root]
$ tail -f log/development.log
# 初回はdevelopment.logは存在していない
$ bundle exec rails s -b 0.0.0.0
-> 起動後、http://localhost:3000/ にアクセスし、Railsのトップページが表示されたらOK

終わりに

今回はきれいな手順書を作る上で工夫しているポイントを共有しました。
もし、もっとこうしたほうがいいということがありましたら教えていただければと思います。

参考

インフラエンジニアの綺麗で優しい手順書の書き方