YAML文法完全ガイド!~Docker Compose実践例付き~

eyecatch-yaml
目次

YAMLとは?

概要

YAMLはJSONやXMLと同様にデータを構造化して保存するためのフォーマットです。一方、YAMLは人間が読みやすく書きやすいことを重視して設計されています。そのため見た目で階層構造が把握できるようインデントやスペースを使ってデータの階層構造を表現します。

そしてYAMLを学ぶ大きな理由の1つは、多くのIaC(Infra as Code)サービスの設定ファイル形式として利用されることが多いためです。例えばDockerComposeやAnsible、Kubernetesといったツールが挙げられます。

YAMLを理解する方法

前述のようにYAMLとJSONはデータを構造化して表現することができ、お互い変換が可能です。特にYAMLの文法に慣れないうちはJSONと比較するとわかりやすいので、オンラインツールであるTransform YAML into JSON(YAMLからJSONに変換)、Convert JSON to YAML online(JSONからYAMLに変換)などを利用しながら表記を確認してみることをおススメします。

押さえておくべきYAMLの文法

コメント

コメントには # を使用します。コメントは一行で書くこともできますし、3行目のようにインラインコメントとして入力することができますが、コメントはその行の最後まで有効です。また複数行のコメントアウトはできないので#を該当の範囲だけ入力する必要があります。

# コメント1
# コメント2
key: value # コメント3

インデントとスペース

YAMLではインデントが重要です。インデントにはスペースを使用しタブは使用しません。各レベルのインデントは、階層構造を表現します。

example:
  - item1
  - item2

データタイプ(スカラー、シーケンス、マップ)

YAMLを理解する際にここが一番の肝となる部分かなと思います。スカラー、シーケンス、マップを理解して、表記に慣れましょう。

# スカラー
string: "文字列"
number: 123
boolean: true

# シーケンス(配列)
fruits:
  - apple
  - banana
  - cherry

# マップ(key-value型のデータでディクショナリーと同じ)
person:
  name: John Doe
  age: 30

データタイプの注意点

YAMLでハイフンあり、ハイフンなしの違いに少し混乱されている方もいるかもしれません。下記のYAMLを見てください。パターン1とパターン2-1・2-2は異なるデータタイプで、パターン2-1とパターン2-2は同じデータタイプです。

# パターン1
fruits1:
  - apple
  - banana
  - cherry

# パターン2-1
fruits2-1:
  - apple
    banana
    cherry
    
# パターン2-2
fruits2-2:
  - apple banana cherry

これを確認するためにJSONに変換してみます。パターン1は3つの要素からなるリストになっていますが、パターン2-1と2-2は3つの単語+スペースを含む文字列として1つの要素からなるリストになっていることがわかります。
ちなみにJSONはコメント入力ができないので表示されていません。

{
  "fruits1": [
    "apple",
    "banana",
    "cherry"
  ],
  "fruits2-1": [
    "apple banana cherry"
  ],
  "fruits2-2": [
    "apple banana cherry"
  ]
}

特殊な記法

複数行の文字列を扱う場合は|(パイプ)を使用します。

# 複数行
multiline: |
  これは
  複数行の
  文字列です  
 

重複する記述を避けるため、記述の再利用方法を説明します。&の記述はアンカー(呼び出し元のデータ)、<<: *の記述はエイリアス(呼び出し先ぼ場所)と呼ばれ、このアンカーとエイリアスを利用した記述の再利用方法をリファレンスと言います。

下記のリファレンス1-1とリファレンス1-2は同じ内容を示しています。

# リファレンス1-1
default: &default
  name: John Doe
user1:
  <<: *default
  age: 25

# リファレンス1-2
default:
  name: John Doe
user1:
  name: John Doe
  age: 25

下記のリファレンス2-1とリファレンス2-2も同じ内容を示しています。リファレンス2-1ではhostを再定義(9行目、14行目)することでリファレンスデータの上書きを図っています。

# リファレンス2-1
defaults: &defaults
  adapter: postgres
  host: localhost

development:
  database: dev_db
  <<: *defaults
  host: 192.168.1.5

test:
  database: test_db
  <<: *defaults
  host: 192.168.1.8

# リファレンス2-2
defaults: &defaults
  adapter: postgres
  host: localhost

development:
  database: dev_db
  <<: *defaults
  host: 192.168.1.5

test:
  database: test_db
  <<: *defaults
  host: 192.168.1.8 

トラブルシューティング

YAMLを記述する際に出くわすエラーはほとんど下の2点になるかと思います。エラーにならないよう、タブとインデントの混在、データタイプを理解した記述を心がけましょう

  • インデントエラー
    インデントの不一致が原因で発生するエラーです。適切なインデントを確認して修正しましょう。
  • データタイプのミスマッチ
    キーや値が適切なデータタイプでない場合に発生するエラーです。正しいデータタイプを使用していることを確認しましょう。

もしYAMLの文法で迷ったらこちらの公式ドキュメントで確認してみてくださいね。

実際のYAMLを解説

それでは実際のYAMLを見ていきます。構造把握のポイントは一番左のインデントからセクションを把握していくこと、リファレンスがある場合は落ち着いて参照元と参照先を確認することです。

下記のYAMLファイルは、Docker Composeを使って4つのサービス(web, db, app1, app2)を定義しています。db_data ボリュームと my-predefined-network ネットワークも設定されています。さらに、アンカーとエイリアスを使って環境変数のリストを複数のサービス間で再利用しています。この方法により、重複を避けてYAMLファイルの可読性とメンテナンス性を向上させています。

version: '3.8'

services:
  web:
    image: nginx
    ports:
      - "80:80"
    environment:
      - NGINX_HOST=localhost
      - NGINX_PORT=80

  db:
    image: postgres
    environment:
      POSTGRES_DB: mydatabase
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    volumes:
      - db_data:/var/lib/postgresql/data

volumes:
  db_data:

networks:
  default:
    external:
      name: my-predefined-network

# アンカーとエイリアスの使用例
common_env: &common_env
  - TZ=UTC
  - LANG=en_US.UTF-8

services:
  app1:
    image: myapp1
    environment: *common_env

  app2:
    image: myapp2
    environment: *common_env

まとめ

本記事ではYAMLの文法とDockerComposeの読み解き方について解説しました。なんとなく扱えてしまうのでなあなあになっていた文法の理解が少しでも進んだのであればうれしいなと思います!YAMLの文法に早く慣れて、IaCの設定がスムーズになることを祈っています!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

Hack Luck Labの管理人hakula(ハクラ)です。2012年にSIerに新卒入社し、SE、新規事業、情シスを担当。その後、ITコンサルを経て、現在はバックエンドエンジニア。過去にはC#、SQL Server、JavaScriptで開発を行い、現在はPython、Rest Framework、Postgresql、Linux、AWSなどを使用しています。ノーコードツールやDX関連も興味あり。「技術は価値を生むために使う」ことが信条で、顧客や組織への貢献を重視しています。

目次