Docker-composeの設定オプション - Docker Composeのための実践的な演習その1

このチュートリアルでは、**Alibaba Cloud**上で**コンテナ**を扱う際に**Docker** Composeを使用して実践的な経験を積むことに焦点を当てています。

*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/practical-exercises-for-docker-compose-part-1_594413)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

#前提条件
すでに最新バージョンのDockerがインストールされているサーバー/VPSにアクセスする必要があります。このチュートリアルでは、CentOSとDockerでAlibaba Cloud [Elastic Compute Service](https://www.alibabacloud.com/ja/product/ecs) (ECS)インスタンスを使用します。

このチュートリアルに従うために大規模なインスタンスを購入する必要はありません。後のチュートリアルで6つのコンテナの大群を実行している場合でも、合計512MBのRAMしかないサーバーが必要になります。

このチュートリアルでは CentOS を使用していますが、Debian や Ubuntu を使用することもできます。このチュートリアルの大部分はDocker Composeコマンドを使用しているので、どのようなLinuxディストリビューションでも動作します。

Docker、イメージ、コンテナ、そして**docker-compose**と**docker ps -a**の使用について、非常に基本的な理解が必要です。**docker-compose**の概念を大まかに理解するためには、3回くらいは**docker-compose**を使ったことがある必要があります。

このチュートリアルの目的は、非常に簡単なdocker-composeファイルをいくつか作成することです。使っていくうちに、Docker-composeの概念の理解が深まっていくでしょう。

#クリーンアップの準備
コンテナをいくつか（できれば何も実行していない）だけ実行している場合は、本当に役立つでしょう。そうすれば、**docker ps -a** の出力リストから簡単にチュートリアルコンテナを見つけることができます。

そこで、コンテナを停止し、**docker-compose up**で作成されたコンテナを削除します。

(何も持っていない場合はこのステップをスキップしてください)

```
docker-compose down -t 0 --remove-orphans 
```
そこで、実行する必要のないコンテナをすべて停止してプルーニングしてください。

(開発環境で)これを素早く行うには、以下のようにします。

```
docker stop $(docker ps -a -q) #stop all containers
```
すべてのコンテナを削除するには、次のように実行します。

```
docker rm -f $(docker ps -a -q) # remove ALL containers
```

#ディレクトリとエディタを分ける
docker-compose のファイルは別のディレクトリに置いた方が良いでしょう。docker-composeサービス/スタックまたはスウォームごとに1つのディレクトリを作成します: 整然とした、整理された、小さく、効率的で、これらの属性のために完全に理解しやすいです。

したがって、入力します。

```
mkdir compose-tuts
cd compose-tuts
```

Linuxディストロでよく使われているエディタにはvimとnanoの2つがあります。私は nano の方が好きですが、vim でも十分に動作します。

nanoをインストールするには

Debian / Ubuntu .

```
apt install nano
```

CentOS .

```
yum install nano
```

Nanoビギナーズガイド:

```
* nano filename-to-edit ... this starts the nano editor
* cursor keys move around as expected
* cut tutorials text from alibaba tutorials web pages work as expected
* pasting into your docker-compose file work as expected
* press F3 to save your work
* press F2 to exit the editor.
```

以上、docker-composeのチュートリアル5つすべてにnanoを使うために知っておくべきことを紹介しました。

#イメージ
これはDockerfilesのimageと同じように動作します。image はコンテナをビルドするイメージを指定します。

以下の演習ではこれを使っています。

#tmpfs
引用元: [https://docs.docker.com/compose/compose-file/#tmpfs](https://docs.docker.com/compose/compose-file/?spm=a2c65.11461447.0.0.1ddc1d01iY0KWS#tmpfs)

tmpfs はコンテナ内の（RAM内の）一時ファイルシステムをマウントします。それは単一の値でもリストでも構いません。2つの一時ファイルシステムのリストを使ってデモをしてみましょう。

以下の内容を docker-compose.yml に追加します。

```
nano docker-compose.yml
```

```
version: "3.7"
services:
  alpine:

    image: alpine:3.8

    command: sleep 600

    tmpfs:

     - /my-run:size=10M

     - /my-app-tmp:size=20M
```

**docker-compose up** は、docker-compose.yml ファイルに定義されているサービスを起動します。
**docker exec** は実行中のコンテナに入ります。

実行してください。

```
docker-compose up -d -t 0      
docker exec -it compose-tuts_alpine_1 /bin/sh
```

2つのテンポラリファイルシステムのサイズを確認する必要があります。

```
/ # df -h /my*
Filesystem                Size      Used Available Use% Mounted on
tmpfs                    20.0M         0     20.0M   0% /my-app-tmp
tmpfs                    10.0M         0     10.0M   0% /my-run
```

完璧です。ご希望のサイズで取り付けました。使用率はゼロです。

15Mのゼロを/my-runに書き込んでみます(サイズは10M)

```
/ # dd if=/dev/zero of=/my-run/output.dat  bs=1M  count=15
dd: writing '/my-run/output.dat': No space left on device
11+0 records in
10+0 records out
/ # echo $?
1
```

dd コマンドはエラーを表示しませんが、**$? **は最後のコマンドの終了ステータスを表示します: この場合は 1 : エラーを意味します。

**df**をもう一度実行してください。

```
/ # df -h /my*
Filesystem                Size      Used Available Use% Mounted on
tmpfs                    20.0M         0     20.0M   0% /my-app-tmp
tmpfs                    10.0M     10.0M         0 100% /my-run
```

/docker-compose は tmpfs を正しいサイズで作成することに成功し、期待通りに動作しています。

15Mのゼロを/my-app-tmp(サイズ20M)に書き込んでみましょう。

```
/ # dd if=/dev/zero of=/my-app-tmp/output.dat  bs=1M  count=15
15+0 records in
15+0 records out
/ # echo $?
0
```

echo $? my-app-tmpが使用しているサイズを確認してみましょう。

```
/ # df -h /my*
Filesystem                Size      Used Available Use% Mounted on
tmpfs                    20.0M     15.0M      5.0M  75% /my-app-tmp
tmpfs                    10.0M     10.0M         0 100% /my-run
```

15Mを使用しています。完璧です。

コンテナ内で動作するアプリケーションに必要な正しいサイズのtmpfsを定義する方法がわかりました。

ddコマンドの詳細については、**man dd**を使用することができます。

ネタバレ： if = 入力ファイル、of = 出力ファイル、bs = ブロックサイズ。シンプルです。

#env_file と環境
env_fileとenvironmentはコンテナに環境変数を追加します。

環境セクションで宣言された環境変数は env_file の値を上書きします。

ほぼすべての Linux アプリケーションは環境変数を持っているので、それをコンテナに注入する方法を知っておく必要があります。(私が知っている中で、これを必要としないアプリケーションは hello word アプリケーションだけです)

これがどのように動作するかを確認するために、いくつかの準備作業が必要です。

1、環境ファイルを作成します。
2、docker-compose でこれらのファイルを参照します。
3、環境変数が期待通りに定義されているかどうかを確認するために、/exec コンテナを入力します。
カレントディレクトリにあるこれらのファイルに以下の環境変数を追加します。

myvars.env

```
ENV_VAR_A=1
ENV_VAR_B=10
ENV_VAR_C=apple
ENV_VAR_F=CentOS 
```

mynewvars.env

```
ENV_VAR_A=2
ENV_VAR_C=pear
ENV_VAR_D=Docker 
```

3番目のファイルについては、入力を節約するために、以下のテキストを切り取ってシェルプロンプトに貼り付けてください。

```
cat <<EOT >> mybestvars.env
ENV_VAR_A=3
ENV_VAR_B=333
ENV_VAR_C=lemon
ENV_VAR_E=Kubernetes 
EOT
```

(catはすべてのENV行をmybestvars.envに送ります)

詳しくはこちらをご覧ください: [https://www.tldp.org/LDP/abs/html/here-docs.html](https://www.tldp.org/LDP/abs/html/here-docs.html?spm=a2c65.11461447.0.0.1ddc1d01CY8rcr)

似たような名前の変数がどのようにオーバーライドされるか、もうお分かりでしょうか？

docker-compose.yml に次のように追加します。

```
nano docker-compose.yml
```

```
version: "3.7"
services:
  alpine:

    image: alpine:3.8

    command: sleep 600

    env_file:
      - myvars.env
      - mynewvars.env
      - mybestvars.env

    environment:
      - ENV_VAR_A=42
      - ENV_VAR_E=Apache web server
```

実行します。

```
docker-compose up -d -t 0 
docker exec -it compose-tuts_alpine_1 /bin/sh
```

表示されているようにprintenvを実行します。

```
/ # printenv
HOSTNAME=1c8abf6141ec
SHLVL=1
HOME=/root
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ENV_VAR_A=42
ENV_VAR_B=333
ENV_VAR_C=lemon
PWD=/
ENV_VAR_D=Docker
ENV_VAR_E=Apache web server
ENV_VAR_F=CentOS
/ # exit
```

それらの値はどのようにして決定されたのでしょうか？

ENV_VAR_A=42 ... docker-compose ファイルの environment: の値。
環境: の値は、これら3つのファイルで設定されているすべての値を上書きします。

```
ENV_VAR_B=333 ... the value from the last file: mybestvars.env
ENV_VAR_C=lemon ... the value from the last file: mybestvars.env
ENV_VAR_D=Docker ... value from mynewvars.env: never overridden anywhere
ENV_VAR_E=Apache web server... the value from environment: in the docker-compose file.
ENV_VAR_F=CentOS ... value from first file: myvars.env : never overridden anywhere
```

これが環境変数の仕組みです。後のファイルは、前のファイルにある同様の名前の変数を上書きします。しかし、docker-compose ファイルの environment: は 全てを上書きします。


これら3つのファイルはコンテナには存在しませんが、その内容は環境変数の中で生きています。

重要: HOSTシェルで作成した3つの環境ファイルは重要です。これらは docker-compose ファイルの一部であり、docker-compose ファイルと一緒にソース管理下に置いておく必要があります。

#extra_hosts
extra_hosts は、コンテナ内の /etc/hosts ファイル内のホスト名とその ip アドレスをリンクします。

以下を docker-compose.yml に追加します。

```
nano docker-compose.yml
```

```
version: "3.7"
services:
  alpine:

    image: alpine:3.8

    command: sleep 600

    extra_hosts:
      - "myhost:123.242.195.42"
      - "myotherhost:150.31.209.42"
```

実行します。

```
docker-compose up -d -t 0 

docker exec -it compose-tuts_alpine_1 /bin/sh
```

以下のコマンドを入力してください: ip r : ルーティングテーブルを表示し、cat /etc/hosts はhostsファイルの内容を表示します。

Dockerはコンテナがこれら2つの新しいホストを見つけられるようにするためにルーティングテーブルに何も追加しません。それは、/etc/hosts ファイルにこれら 2 つのマッピングを追加するだけです。

```
/ # ip r
default via 172.22.0.1 dev eth0
172.22.0.0/16 dev eth0 scope link  src 172.22.0.2
/ # cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
123.242.195.42  myhost
150.31.209.42   myotherhost
172.22.0.2      024481ed6ce7
/ # exit
```

これらのホスト名のマッピングは固定の IP アドレスのみを含むことができます。

最後のランダムなホスト名がこのコンテナのホスト名です。CONTAINER プロンプトで hostname コマンドを実行すると、これがホスト名として表示されます。

#ヘルスチェック
Dockerfile のヘルスチェックに慣れているのであれば、docker-compose のヘルスチェックは簡単です。

docker-compose.ymlに以下を追加してください。

```
nano docker-compose.yml
```

```
version: "3.7"
services:
  alpine:

    image: alpine:3.8

    command: sleep 600

    healthcheck:
      test: exit 0
      interval: 1s
      timeout: 1s
      retries: 3
      start_period: 0s
```

実行します。

```
docker-compose up -d -t 0

docker ps -a
```

スピーディーなコンピュータを持っている場合は、このように表示されます：health checks ... still starting.

```
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                           PORTS               NAMES
2979837d1a56        alpine:3.8          "sleep 600"         3 seconds ago       Up 1 second (health: starting) 
```

遅いコンピュータ/サーバでは、正常にヘルスチェックを完了するまでに**docker ps -a**コマンドを何度も実行しなければなりません。(**healthy**)

```
docker ps -a
```

出力します。

```
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                   PORTS               NAMES
d7ceefcc2ad2        alpine:3.8          "sleep 600"         6 seconds ago       Up 4 seconds (healthy)                       compose-tuts_alpine_1
```

docker-compose.ymlを編集して、10行目あたりを以下のように修正します。

```
   test: exit 1
```

これで、ヘルスチェックは完全に失敗します-エラー終了コード1。

再実行してください。

```
docker-compose up -d -t 0 
docker ps -a
docker ps -a
docker ps -a
```

数秒でわかるようになります:(**unhealthy**)

```
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
ed54a3189e7a        alpine:3.8          "sleep 600"         6 seconds ago       Up 5 seconds (unhealthy)                       compose-tuts_alpine_1
```

アプリケーションに応じて、それぞれの特定のアプリケーションに適した正確なヘルスチェックを決定する必要があります。

また、適切な間隔とタイムアウト値を決定する必要があります。

両方とも 1 秒というのは、本番環境では低すぎます。ここでは、クイックテストとデモのためだけに1秒を使用しています。

同様に、start_period は実生活ではゼロにすることはできません。ヘルスチェックを実行する前に、まずアプリケーションを起動する時間を与えるべきです。

ヘルスチェックの詳細については、Alibaba Cloudの公式ドキュメントを参照してください。[コンテナサービスのベストプラクティス - Dockerコンテナのヘルスチェック](https://www.alibabacloud.com/help/ja/doc-detail/58588.htm)

Dockerコミュニティでは、ヘルスチェックを含むいくつかのインスタンスイメージを [https://github.com/docker-library/healthcheck](https://github.com/docker-library/healthcheck?spm=a2c65.11461447.0.0.1ddc1d01Gfkvlx) で提供しています。

これらの例ではソフトウェアを使用していなくても、自分の健康診断書の書き方について非常に良いアイデアを得ることができます。


*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*