プログラミングをしていると拡張子が「.yml」や「.yaml」といったファイルを見かけることがあります。
あまり聞きなれないもので、何だろう?と疑問に持たれる方も少なくありません。
しかもファイルの中には、「-(ハイフン)」「&(アンド・アンパサンド)」,「 *(アスタリスク),」 「<<(小なり2つ)」といったの独特の記述があります。
ですが、「.yml」や「.yaml」のファイルはとても便利で、慣れてくると少ない記述でコードを書くことができます。
ここでは、「.yml」や「.yaml」ファイルとは何か?や使い方について解説しています。
.ymlや.yamlはどこで使われているか?
.ymlや.yamlは様々なサービスの根幹となるファイルで使用されています。
例えば、Docker(ドッカー)で根本となる「docker-compose.yml」。
Ruby on Railsでデータベースの情報が記述してある「database.yml」やコンパイルを行うWebpackerの設定が書かれた「Webpacker.yml」。
AWSでキャッシュを提供するサービスCloudFrontや、EC2などの設定ファイルも「.yaml」といった拡張しのファイルを持っています。
.ymlや.yamlとは何か?
まず、拡張子に「.yml」と「.yaml」の2種類が存在しますが、どちらも同じで、「ヤムル」と呼びます
拡張子は「.gif」「.png」など3文字で書くことが一般的です。これに合わせて、「.yaml」も「.yml」という省略された書き方が用意されています。
「.jpeg」が「.jpg」としても記述できるのと同じです。
ヤムルファイルは、XMLやJSONをより少ない記述量で書くための書式です。このため、ヤムル(.yml, .yaml)からXML(.xml)やJSON(.json)にコンパイルすることもできます。
より少ないコード量で記述でき軽量なので、使われる場面が増えていいます。
ヤムル(.ymlや.yaml)を使う時のポイントまとめ
ヤムル(.ymlや.yaml)を使うポイントをまとめると以下のようになります。
jsonファイルでよく目にする、{ }
, [ ]
, ,
, " "
などをを使わないのでデータ量がかなり少なくなります。更に、変数(のようなもの)を使うことができます。
以下でそれぞれの使い方をJSONとの記述と対比しながら実例で紹介しています。
オブジェクトの書き方
基本形
ヤムルでは、「プロパティ名」と「値」がセットになったオブジェクトを記述するときに、{ }を使わずに記述します。
プロパティ名: 値
実例
name: yamada
gender: male
age: 27
↓ JSON形式にコンパイル
{
"name": "yamada",
"gender": "male",
"age": 27
}
入れ子(ネスト)したオブジェクトの書き方
オブジェクトの値に、オブジェクトを含める場合など、入れ子(ネスト)させたい場合は、インデント(TABキー)を使います。
プロパティ名1:
プロパティ名2: 値2
プロパティ名3: 値3
,,,,
実例
yamada:
gender: male
age: 27
↓ JSON形式にコンパイル
{
"yamada": {
"gender": "male",
"age": 27
}
}
複数のオブジェクトを並列に記述する方法
複数のオブジェクトを並列に記述したい場合は、改行して「プロパティ名: 値」の組み合わせを記述します。
プロパティ名1: 値1
プロパティ名2: 値2
実例
yamada:
gender: male
age: 27
tnaka:
gender: female
age: 23
↓ JSON形式にコンパイル
{
"yamada": {
"gender": "male",
"age": 27
},
"tnaka": {
"gender": "female",
"age": 23
}
}
配列の書き方
基本形
ヤムル(.ymlや.yaml)で配列を記述する場合は冒頭に「-
」をつけます。
値を複数記述する場合は改行します。
- 値1
- 値2
,,,
実例
- a
- b
↓ JSON形式にコンパイル
[ "a", "b" ]
入れ子(ネスト)した配列の書き方(多次元の配列)
配列を中に、配列を持たせ入れ子(ネスト・多次元)構造にする場合は、値のない「-
」で改行し、インデントをつけます。
- 値1
-
- 値2
実例1(2次元配列の場合)
- a
-
- b
↓ JSON形式にコンパイル
[ "a", [ "b" ] ]
実例2(3次元配列の場合)
- a
-
- b
- c
- c
- d
-
- f
-
- g
↓ JSON形式にコンパイル
[ "a", [ "b", "c" ], "c", "d", [ "f", [ "g" ] ] ]
配列とオブジェクトを組み合わせる方法
ヤムルでは、配列の値にオブジェクトを入れたり、オブジェクトの値に配列を指定することもできます。
配列の中にオブジェクトを入れる方法
配列の値であることを表す「-」の後ろに、オブジェクトを表す「プロパティ名: 値」を記述します。
- プロパティ名: 値
実例1(1次元配列の場合)
- a: 1
- b: 2
↓ JSON形式にコンパイル
[ { "a": 1 }, { "b": 2 } ]
実例2(多次元配列の場合)
- a: 1
- b: 2
- 3
-
- 4
- 5
- c :6
↓ JSON形式にコンパイル
[ { "a": 1 }, { "b": 2 }, 3, [ 4, 5, "c :6" ] ]
オブジェクトの値に配列を指定する
「プロパティ名:」で改行し、「-」で値を記述します。
プロパティ名:
- 値1
- 値2
上記は値をインデントさせて見やすくしていますが、インデントがなくても機能します。
プロパティ名:
- 値1
- 値2
実例1:インデントがある場合
a:
- 1
- 2
↓ JSON形式にコンパイル
{ "a": [1, 2] ] }
実例2:インデントがない場合
a:
- 1
- 2
↓ JSON形式にコンパイル
{ "a": [1, 2] ] }
オブジェクトの中に値がオブジェクトの配列をいれる方法
オブジェクトの中に、値がオブジェクトの配列を入れる場合は、「プロパティ名:」で改行し、「-」で値を記述するときに値を「プロパティ名:」とします。
プロパティ名:
- プロパティ名1: 値1
- プロパティ名2: 値2
実例
a:
- b: 1
- c: 2
↓ JSON形式にコンパイル
{ "a": [ { "b": 1 }, { "c": 2 } ] }
「&」と「*」の使い方
「&」と「*」とは何か?
ヤムル(.ymlや.yaml)では「&(アンド/アンパサンド)」と「*(アスタリスク)」を使った記述がでてきます。
これは、変数のような機能です。
&を使って名前を付け、*でアンカー名を指定して対象の値を呼び出すことができます。
「&」指定した名前の目印をつけるため「アンカー」(またはアンカリング)とよび、つけた名前を「エイリアス」と呼びます。エイリアスとは「別名」という意味です。
「&」の使い方
単一の値を指定する場合
「&」を使うときは、「&」の後ろに空白を開けずに、エイリアス名を記載します。その後ろに空白を空けて値を記述します。
&エイリアス 値
これで、値が指定したエイリアスの中に入ります。このエイリアスが変数的な働きになります。
オブジェクトの中の値を指定する場合
オブジェクトの中の値をエイリアスに代入したい場合は以下のようにします。
プロパティ名: &エイリアス
値1
値2
,,,,
「*」の使い方
「*」を使うときは、「*」の後ろに空白を開けずに、呼び出したいエイリアス(変数名)を記載します。
*エイリアス
すると、「&」で指定したエイリアスに対応する値を呼び出すことができます。
実例:単一データの場合
エイリアス「ankor」に1を代入して、「*ankor」で呼び出す場合は以下のようになります。
a:
- &ankor 1
- *ankor
↓ JSON形式にコンパイル
{ "a": [ 1, 1 ] }
実例:単一のオブジェクトの場合
エイリアス「x」に「a: 1」を代入して、「*x」で呼び出す場合は以下のようになります。
- &x a:1
- *x
↓ JSON形式にコンパイル
[ "a": 1, "a": 1 ]
実例:オブジェクトの値として呼び出す場合
エイリアス「x」に「1」を代入して、プロパティ名「b」の値の一つとして呼び出す場合は以下のようになります。
a:
- &x 1
- 2
b:
- 3
- *x
↓ JSON形式にコンパイル
{ "a": [ 1, 2 ], "b": [ 3, 1 ] }
実例:オブジェクトの中の複数データを代入する場合
オブジェクトの中の複数データをエイリアスに代入する場合は、プロパティ名の後ろに「&エイリアス」を記述して、その下に改行して値を記述します。
エイリアス「x」に[1, 2]を代入して、プロパティ名「b」の値として呼び出す場合は以下のようになります。
a: &x
- 1
- 2
b: *x
↓ JSON形式にコンパイル
{ "a": [ 1, 2 ], "b": [ 1, 2 ] }
エラー例:配列自体を代入することはできない
配列そのものをエイリアスに代入することはできません。
&x
- 1
- 2
*x
↓ JSON形式にコンパイル
Error : Unable to parse.
Line : 1 &x
「Unable to parse.(解析できません)」というエラーが発生します。
エラー例:オブジェクト自体を代入することはできない
オブジェクトそのものをエイリアスに代入することはできません。
&x :
- 1
- 2
*x
↓ JSON形式にコンパイル
Error : Unable to parse.
Line : 4 *x
「Unable to parse.(解析できません)」というエラーが発生します。
エラー例: 「*」でマージすることはできない
「*」ではオブジェクトの値の中に別の要素をマージすることはできません。(要素の一つとして指定したエイリアスを呼び出すことができません)
例えば、以下のようにするとエイリアス「x」に「c:1 d:2」を代入して、プロパティ名「b」の値として呼び出すことができます。
a: &x
c: 1
d: 2
b: *x
↓ JSON形式にコンパイル
{
"a": {
"c": 1,
"d": 2
},
"b": {
"c": 1,
"d": 2
}
}
しかし、このエイリアス「x」と「e: 3」をbの中の要素として呼び出そうとするとエラーが発生します。
a: &x
c: 1
d: 2
b:
*x
e: 3
↓ JSON形式にコンパイル
Error : Unable to parse.
Line : 5 *x
「Unable to parse.(解析できません)」というエラーが発生します。
上記のようにオブジェクトの値をマージさせたい場合は「<<」を使う必要があります。
<<(インジェクト)の使い方
「<<」とは何か?
「<<」はオブジェクトの中に値をマージするための記述です。
オブジェクトの値の中に注入するので、「インジェクト」と呼ばれます。
「<<」の使い方
「<<」は「&」と「*」と合わせて使います。
オブジェクトをマージする
以下のようにあるオブジェクトの中に、オブジェクト形式の複数の値が入っている場合に、その値をエイリアスとして設定する場合は「&」を使います。
オブジェクト名: &エイリアス
プロパティ名1: 値1
プロパティ名2: 値2
,,,,
これを、他のオブジェクトの中で呼び出して、他の要素とマージさせるためには、「<<: *エイリアス」を記述します。
オブジェクト名':
<<: *エイリアス
プロパティ名: 値
要素は「<<: *エイリアス」で指定した場所に入ります。
配列をマージする
以下のようにあるオブジェクトの中に、配列形式の複数の値が入っている場合に、その値をエイリアスとして設定する場合は「&」を使います。
オブジェクト名: &エイリアス
- 値1
- 値2
,,,,
この配列となっている値も、「<<: *エイリアス」を使うことで、他のオブジェクトの中で呼び出して、他の要素とマージさせることができます。
オブジェクト名':
<<: *エイリアス
プロパティ名: 値
要素は「<<: *エイリアス」で指定した場所に入ります。
その際、配列の要素のプロパティ名は「0」「1」というように配列番号が入ります。
実例:一番上に挿入する場合
a: &x
b: 1
c: 2
d:
<<: *x
e: 3
↓ JSON形式にコンパイル
{ "a": { "b": 1, "c": 2 }, "b": { "b": 1, "c": 2, "e": 3 } }
実例:間に挿入する場合
a: &x
b: 1
c: 2
d:
e: 3
<<: *x
f: 4
↓ JSON形式にコンパイル
{ "a": { "b": 1, "c": 2 }, "b": { "e": 3, "b": 1, "c": 2, "f": 4 } }
実例:配列をマージする
a: &x
- 1
- 2
d:
<<: *x
c: 3
↓ JSON形式にコンパイル
{ "a": { "b": 1, "c": 2 }, "b": { "0": 1, "1": 2, "c": 3 }
エラー例:「<<」を使わないとエラーになる
a: &x
b: 1
c: 2
d:
*x
d: 3
↓ JSON形式にコンパイル
Error : Unable to parse.
Line : 6 *x
コメントアウトの使い方
コメントアウトは「#
」で記述します。
なお、JSON形式ではコメントアウトはないので、JSONにコンパイルするとコメントアウトは無視されてなくなります。
実例
#コメントアウト
a: &x
#bを定義
b: 1
#cを定義
c: 2
d: *x
↓ JSON形式にコンパイル
{ "a": { "b": 1, "c": 2 }, "b": { "b": 1, "c": 2 } }
nullを明示する
オブジェクトでプロパティの値を指定しない場合は「~」を記述することで、値がnullであることを明示できます。
「~」は値に何も記述していない状態と同じです。
実例
a:
b: ~
c:
- d:
- e: ~
↓ JSON形式にコンパイル
{ "a": null, "b": null, "c": [ { "d": null }, { "e": null } ] }
docker-compose.ymlのコンパイル例
参考として、docker-compose.ymlをjsonに変換するとどのように表示されるかを記載しておきます。
version: "3"
services:
db:
image: postgres:11.1-alpine
web:
build: .
command: bin/rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/usr/src/app
ports:
- "3000:3000"
depends_on:
- db
↓ JSON形式にコンパイル
{
"version": "3",
"services": {
"db": {
"image": "postgres:11.1-alpine"
},
"web": {
"build": ".",
"command": "bin/rails s -p 3000 -b '0.0.0.0'",
"volumes": [
".:/usr/src/app"
],
"ports": [
"3000:3000"
],
"depends_on": [
"db"
]
}
}
}
database.ymlのコンパイル例
database.ymlをjsonに変換するとどのように表示されるかの例です。
大量のコメントアウトがなくなります。
# PostgreSQL. Versions 9.3 and up are supported.
#
# Install the pg driver:
# gem install pg
# On macOS with Homebrew:
# gem install pg -- --with-pg-config=/usr/local/bin/pg_config
# On macOS with MacPorts:
# gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
# On Windows:
# gem install pg
# Choose the win32 build.
# Install PostgreSQL and put its /bin directory on your path.
#
# Configure Using Gemfile
# gem 'pg'
#
default: &default
adapter: postgresql
encoding: unicode
# For details on connection pooling, see Rails configuration guide
# https://guides.rubyonrails.org/configuring.html#database-pooling
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
development:
<<: *default
database: rails6_docker_alpine_development
# The specified database role being used to connect to postgres.
# To create additional roles in postgres see `$ createuser --help`.
# When left blank, postgres will use the default role. This is
# the same name as the operating system user running Rails.
#username: rails6_docker_alpine
# The password associated with the postgres role (username).
#password:
# Connect on a TCP socket. Omitted by default since the client uses a
# domain socket that doesn't need configuration. Windows does not have
# domain sockets, so uncomment these lines.
#host: localhost
# The TCP port the server listens on. Defaults to 5432.
# If your server runs on a different port number, change accordingly.
#port: 5432
# Schema search path. The server defaults to $user,public
#schema_search_path: myapp,sharedapp,public
# Minimum log levels, in increasing order:
# debug5, debug4, debug3, debug2, debug1,
# log, notice, warning, error, fatal, and panic
# Defaults to warning.
#min_messages: notice
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: rails6_docker_alpine_test
# As with config/credentials.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password or a full connection URL as an environment
# variable when you boot the app. For example:
#
# DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
#
# If the connection URL is provided in the special DATABASE_URL environment
# variable, Rails will automatically merge its configuration values on top of
# the values provided in this file. Alternatively, you can specify a connection
# URL environment variable explicitly:
#
# production:
# url: <%= ENV['MY_APP_DATABASE_URL'] %>
#
# Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full overview on how database connection configuration can be specified.
#
production:
<<: *default
database: rails6_docker_alpine_production
username: rails6_docker_alpine
password: <%= ENV['RAILS6_DOCKER_ALPINE_DATABASE_PASSWORD'] %>
↓ JSON形式にコンパイル
{
"default": {
"adapter": "postgresql",
"encoding": "unicode",
"pool": "<%= ENV.fetch(\"RAILS_MAX_THREADS\") { 5 } %>"
},
"development": {
"adapter": "postgresql",
"encoding": "unicode",
"pool": "<%= ENV.fetch(\"RAILS_MAX_THREADS\") { 5 } %>",
"database": "rails6_docker_alpine_development"
},
"test": {
"adapter": "postgresql",
"encoding": "unicode",
"pool": "<%= ENV.fetch(\"RAILS_MAX_THREADS\") { 5 } %>",
"database": "rails6_docker_alpine_test"
},
"production": {
"adapter": "postgresql",
"encoding": "unicode",
"pool": "<%= ENV.fetch(\"RAILS_MAX_THREADS\") { 5 } %>",
"database": "rails6_docker_alpine_production",
"username": "rails6_docker_alpine",
"password": "<%= ENV['RAILS6_DOCKER_ALPINE_DATABASE_PASSWORD'] %>"
}
}
&default
が<<: *default
で共通部として呼び出されていることがわかります。
default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
webpack.ymlのコンパイル例
webpack.ymlをjsonに変換するとどのように表示されるかの例です。
# Note: You must restart bin/webpack-dev-server for changes to take effect
default: &default
source_path: app/javascript
source_entry_path: packs
public_root_path: public
public_output_path: packs
cache_path: tmp/cache/webpacker
webpack_compile_output: true
# Additional paths webpack should lookup modules
# ['app/assets', 'engine/foo/app/assets']
additional_paths: []
# Reload manifest.json on all requests so we reload latest compiled packs
cache_manifest: false
# Extract and emit a css file
extract_css: false
static_assets_extensions:
- .jpg
- .jpeg
- .png
- .gif
- .tiff
- .ico
- .svg
- .eot
- .otf
- .ttf
- .woff
- .woff2
extensions:
- .mjs
- .js
- .sass
- .scss
- .css
- .module.sass
- .module.scss
- .module.css
- .png
- .svg
- .gif
- .jpeg
- .jpg
development:
<<: *default
compile: true
# Reference: https://webpack.js.org/configuration/dev-server/
dev_server:
https: false
host: localhost
port: 3035
public: localhost:3035
hmr: false
# Inline should be set to true if using HMR
inline: true
overlay: true
compress: true
disable_host_check: true
use_local_ip: false
quiet: false
pretty: false
headers:
'Access-Control-Allow-Origin': '*'
watch_options:
ignored: '**/node_modules/**'
test:
<<: *default
compile: true
# Compile test packs to a separate directory
public_output_path: packs-test
production:
<<: *default
# Production depends on precompilation of packs prior to booting for performance.
compile: false
# Extract and emit a css file
extract_css: true
# Cache manifest.json for performance
cache_manifest: true
↓ JSON形式にコンパイル
{
"default": {
"source_path": "app/javascript",
"source_entry_path": "packs",
"public_root_path": "public",
"public_output_path": "packs",
"cache_path": "tmp/cache/webpacker",
"webpack_compile_output": true,
"additional_paths": [],
"cache_manifest": false,
"extract_css": false,
"static_assets_extensions": [
".jpg",
".jpeg",
".png",
".gif",
".tiff",
".ico",
".svg",
".eot",
".otf",
".ttf",
".woff",
".woff2"
],
"extensions": [
".mjs",
".js",
".sass",
".scss",
".css",
".module.sass",
".module.scss",
".module.css",
".png",
".svg",
".gif",
".jpeg",
".jpg"
]
},
"development": {
"source_path": "app/javascript",
"source_entry_path": "packs",
"public_root_path": "public",
"public_output_path": "packs",
"cache_path": "tmp/cache/webpacker",
"webpack_compile_output": true,
"additional_paths": [],
"cache_manifest": false,
"extract_css": false,
"static_assets_extensions": [
".jpg",
".jpeg",
".png",
".gif",
".tiff",
".ico",
".svg",
".eot",
".otf",
".ttf",
".woff",
".woff2"
],
"extensions": [
".mjs",
".js",
".sass",
".scss",
".css",
".module.sass",
".module.scss",
".module.css",
".png",
".svg",
".gif",
".jpeg",
".jpg"
],
"compile": true,
"dev_server": {
"https": false,
"host": "localhost",
"port": 3035,
"public": "localhost:3035",
"hmr": false,
"inline": true,
"overlay": true,
"compress": true,
"disable_host_check": true,
"use_local_ip": false,
"quiet": false,
"pretty": false,
"headers": {
"Access-Control-Allow-Origin": "*"
},
"watch_options": {
"ignored": "**/node_modules/**"
}
}
},
"test": {
"source_path": "app/javascript",
"source_entry_path": "packs",
"public_root_path": "public",
"public_output_path": "packs-test",
"cache_path": "tmp/cache/webpacker",
"webpack_compile_output": true,
"additional_paths": [],
"cache_manifest": false,
"extract_css": false,
"static_assets_extensions": [
".jpg",
".jpeg",
".png",
".gif",
".tiff",
".ico",
".svg",
".eot",
".otf",
".ttf",
".woff",
".woff2"
],
"extensions": [
".mjs",
".js",
".sass",
".scss",
".css",
".module.sass",
".module.scss",
".module.css",
".png",
".svg",
".gif",
".jpeg",
".jpg"
],
"compile": true
},
"production": {
"source_path": "app/javascript",
"source_entry_path": "packs",
"public_root_path": "public",
"public_output_path": "packs",
"cache_path": "tmp/cache/webpacker",
"webpack_compile_output": true,
"additional_paths": [],
"cache_manifest": true,
"extract_css": true,
"static_assets_extensions": [
".jpg",
".jpeg",
".png",
".gif",
".tiff",
".ico",
".svg",
".eot",
".otf",
".ttf",
".woff",
".woff2"
],
"extensions": [
".mjs",
".js",
".sass",
".scss",
".css",
".module.sass",
".module.scss",
".module.css",
".png",
".svg",
".gif",
".jpeg",
".jpg"
],
"compile": false
}
}
オブジェクトや値がたくさん記載されているのがわかります。