Dockerfile:LinuxサーバにDockerをインストールする

このチュートリアルでは、**Alibaba Cloud**上での**Dockerfile**の使用方法について実践的な経験を積むことに焦点を当てています。

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

#Dockerfile HEALTHCHECK
このセクションでは、DockerfileでのHEALTHCHECKの使い方を説明します。

HEALTHCHECKは、指定したスケジュールでコンテナの健全性を自動チェックします。

HEALTHCHECK [OPTIONS] CMDコマンド

CMDの前に表示されるオプションは、以下の通りです。

```
--interval=DURATION (default: 30s)
--timeout=DURATION (default: 30s)
--start-period=DURATION (default: 0s)
--retries=N (default: 3)
```

このチュートリアルでは、これらの時間は非常に長いです。すぐにテストして、チェックが機能するのを確認したいのです。

これをDockerfileに追加するには

nano Dockerfile

```
FROM alpine:3.8
HEALTHCHECK --interval=3s --timeout=1s \
   CMD curl -f http://localhost/ || exit 1
```

重要: この特定の Alpine コンテナでは、curl -f http://localhost/ health check コマンドは常に失敗することに注意してください。

イメージをビルドするには

```
docker build --tag tutorial:demo --file Dockerfile  .
```

コンテナを起動して結果を見てみましょう。

```
docker stop -t 0 tutorial ; docker container prune -f  
docker run -ti -d --name tutorial tutorial:demo /bin/sh -c 'while true; do sleep 60; done’
```

コンテナが起動したら、docker ps -aを1秒ごとに(10秒間)繰り返し実行して、ヘルスチェックの進行状況を確認します。

```
docker ps -a
```

期待される出力。

```
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                           PORTS               NAMES

27134771d5dd        tutorial:demo       "/bin/sh -c 'while t�"   3 seconds ago       Up 1 second (health: starting)
```

10秒後に以下のようになります。

```
docker ps -a
```

期待される出力。

```
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES

27134771d5dd        tutorial:demo       "/bin/sh -c 'while t�"   12 seconds ago      Up 10 seconds (unhealthy)                       tutorial
```

(health:starting)は10秒間表示されますが、チェックは3秒間隔で行われるので ( --interval=3s)、 --timeout=1sを指定しています。

この間隔を1秒に短縮して、より早くヘルスの結果を表示できるようにしましょう。

また、リトライ回数をデフォルトの3回から1回に減らしてみましょう。--retries=1

PROD環境ではretries = 1を使うことはほぼないでしょう。3の方がはるかに現実的な値です。

これをDockerfileに追加するには

nano Dockerfile

```
FROM alpine:3.8
HEALTHCHECK --interval=1s --timeout=1s --retries=1 \
   CMD curl -f http://localhost/ || exit 1
```

を使用して画像を構築します。

```
docker build --tag tutorial:demo --file Dockerfile  .
```

コンテナを起動して結果を見てみましょう。

```
docker stop -t 0 tutorial ;   docker container prune -f  
docker run -ti -d --name tutorial tutorial:demo /bin/sh -c 'while true; do sleep 60; done';docker ps -a; sleep .4; docker ps -a; sleep .4; docker ps -a; sleep .4; docker ps -a; sleep .4;
```

コンテナの状態を 0.4 秒ごとにチェックしていることに注意してください。

期待される出力。

```
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                                     PORTS               NAMES

1e83c476c2ee        tutorial:demo       "/bin/sh -c 'while t�"   1 second ago        Up Less than a second (health: starting)                       tutorial
```

```
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                                     PORTS               NAMES

1e83c476c2ee        tutorial:demo       "/bin/sh -c 'while t�"   2 seconds ago       Up Less than a second (health: starting)                       tutorial
```

```
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                    PORTS               NAMES

1e83c476c2ee        tutorial:demo       "/bin/sh -c 'while t�"   2 seconds ago       Up 1 second (unhealthy)                       tutorial
```

```
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                    PORTS               NAMES

1e83c476c2ee        tutorial:demo       "/bin/sh -c 'while t�"   3 seconds ago       Up 1 second (unhealthy)                       tutorial
```

0.8秒の間、健康状態は（ヘルス：開始）です。

1秒後にステータスが(異常)に変わります。

実際のprod環境に合わせてこれらの設定をいじるのは管理者であるあなた次第です。

```
--interval=DURATION (default: 30s)
--timeout=DURATION (default: 30s)
--start-period=DURATION (default: 0s)
--retries=N (default: 3)
```

管理者としても、適切なヘルスチェックコマンドを prod env で決定しなければなりません。Webサーバコンテナ、データベースコンテナ、ハプロキシコンテナは、すべて異なるヘルスチェックの要件を持っています。

ここでは、状態がどのように変化するかを素早く表示するために使用しています。

健康状態がどのように見えるかを確認するために、成功するヘルスチェックのサンプルを実行してみましょう。

これをDockerfileに追加するには

nano Dockerfile

```
FROM alpine:3.8
HEALTHCHECK --interval=.1s --timeout=.4s  --retries=1\
  CMD sleep .1 || exit 1
```

を使用して画像を構築します。

```
docker build --tag tutorial:demo --file Dockerfile  .
```

コンテナを起動して結果を見てみましょう。

```
docker stop -t 0 tutorial ;   docker container prune -f  
docker run -ti -d --name tutorial tutorial:demo /bin/sh -c 'while true; do sleep 60; done';docker ps -a; sleep .4; docker ps -a; sleep .4; docker ps -a; sleep .4; docker ps -a; sleep .4;
```

期待される出力。

```
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                                     PORTS               NAMES

c83552f66511        tutorial:demo       "/bin/sh -c 'while t�"   1 second ago        Up Less than a second (health: starting)                       tutorial
```

```
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                            PORTS               NAMES

c83552f66511        tutorial:demo       "/bin/sh -c 'while t�"   2 seconds ago       Up Less than a second (healthy)                       tutorial
```

```
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                  PORTS               NAMES

c83552f66511        tutorial:demo       "/bin/sh -c 'while t�"   2 seconds ago       Up 1 second (healthy)                       tutorial
```

```
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                   PORTS               NAMES

c83552f66511        tutorial:demo       "/bin/sh -c 'while t�"   3 seconds ago       Up 2 seconds (healthy)                       tutorial
```

sleep .1 は 10 分の 1 秒間正常にスリープし、その後ステータスのリターンコードを返します。

残念ながら、docker ps -a コマンドのステータスフィルタは健康状態によるコンテナのマッチングを行いません。フィルタリングできるのは、created, restarting, running, removing, paused, exited, dead のみです。

実行できません: docker ps --filter status=healthy

実行できません: docker ps --filter status=unhealthy

以下の
docker ps -a | grep '(healthy)'
そして
docker ps -a | grep '(unhealthy)'
を使う必要があります。


#Dockerfile EXPOSE Ports
このセクションでは、Dockerfile が EXPOSE を使ってコンテナのポートを公開する方法を学びます。

コンテナは孤立した実行プロセスです。コンテナは、他のコンテナがアクセスできるポートを明示的に指定しなければなりません。

ポートとは、プロセスが他のプロセスに連絡してコマンドを送信するための公式な方法です。

例えば、Apache のポート 80 は通常公開されています。Apache はコンテナの中に隔離されて隠れています。何かをさせる唯一の方法は、ポート 80 を通してアクセスすることです。

EXPOSE 命令はコンテナが listen するポートを宣言します。

ポートがTCPかUDPかを指定することができます。プロトコルが指定されていなければデフォルトはTCPです。

EXPOSE 命令は実際にポートを公開しません。

EXPOSE はドキュメントとしての役割を果たすだけです。これは、コンテナ内のどのポートが公開可能な状態にすることを意図しているかを宣言します。

[https://docs.docker.com/engine/reference/builder/#expose](https://docs.docker.com/engine/reference/builder/?spm=a2c65.11461447.0.0.378c2c16h9g9cw#expose) より

コンテナの実行時に実際にポートを公開するには、docker run で -p フラグを使用して 1 つ以上のポートを公開してマッピングするか、-p フラグを使用してすべての公開されたポートを公開して高次ポートにマッピングします。

デフォルトでは、expose は TCP を想定しています。UDP を指定することもできます。

EXPOSE 80/tcp

EXPOSE 80/UDP

このチュートリアルでは、ポート80、tcpとudpを公開します。

Dockerfileを以下のように編集します。

nano Dockerfile

```
FROM alpine:3.8
EXPOSE 80/tcp
EXPOSE 80/udp
```

を使用して画像を構築します。

```
docker build --tag tutorial:demo --file Dockerfile  .
```

コンテナを起動して結果を見てみましょう。

```
docker run -ti -d --name tutorial tutorial:demo /bin/sh -c 'while true; do sleep 60; done'
```

期待される出力

```
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                                     PORTS               NAMES

6269a988e1dd        tutorial:demo       "/bin/sh -c 'while t�"   1 second ago        Up Less than a second (health: starting)   80/tcp, 80/udp      tutorial
```

ports カラムには、公開されているポートが表示されていますが、使用できません。それらを公開しなければなりません。docker runコマンドの-p 30000:80/tcpを使って公開します。

-p 30000:80/tcp

30000 はホストのポート番号を指定します。80/tcpはコンテナのポート番号を指定します。

コンテナを作成して結果を見てみましょう。

```
docker stop -t 0 tutorial; ;   docker container prune -f  

docker run  -p 30000:80/tcp  -ti -d --name tutorial tutorial:demo /bin/sh -c '\''while true; do sleep 60; done'\'''
```

期待される出力。

```
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                  PORTS               NAMES

8b3e43916708        tutorial:demo       "/bin/sh -c 'while t�"   1 second ago        Up Less than a second   0.0.0.0:30000->80/tcp, 80/udp      tutorial
```

0.0.0.0.0:30000->80/tcp

localhost のポート 30000 はコンテナのポート 80 にマップされています。

これでホスト上でポート30000が開いていることが確認できます。

ss コマンドはソケットに関する情報を表示するために使用されます。ss コマンドはソケットの情報を表示するために使用します。( netstatコマンドはCentOSのデフォルトインストールでは存在しなくなりました。代わりに service コマンドを使用します。)

```
ss -t -a -n
```

オプションの短いバージョン、長いバージョン。

1、-t, --tcp は TCP ソケットのみを表示します。
2、-a, --all すべてのソケットを表示します。
3、-n, --numeric はサービス名を解決しないので、ポート番号を数値で表示します。

期待される出力

```
State       Recv-Q Send-Q Local Address:Port                Peer Address:Port
LISTEN      0      128                *:22                             *:*
ESTAB       0      0      192.168.56.44:22                 192.168.56.11:4118
ESTAB       0      64     192.168.56.44:22                 192.168.56.11:2719
LISTEN      0      128               :::30000                         :::*
LISTEN      0      128               :::22                            :::*
```

30000番ポートがホストでリッスンされていることがわかります。

30000には特別な意味はありません。ここでは簡単に見つけられるポート番号として使われているだけです。

同様に udp 80 番ポートも公開してみましょう。実行してみてください。

```
docker stop -t 0 tutorial; ;   docker container prune -f  
docker run -p 40080:80/udp 30000:80/tcp -
```

パブリッシュがうまくいったかどうかを確認します。

```
ss -u -a -n
```

期待される出力

```
State       Recv-Q Send-Q Local Address:Port                Peer Address:Port
UNCONN      0      0                 :::40080                         :::*
```

今回は -u 引数を使って udp ポートを表示していることに気がつきました。

#Dockerfile の ENV 変数
環境変数を使用して、実行中のコンテナに値を送ることができます。

環境変数はコンテナが動作する環境の一部です。
構文は以下の通りです。

構文:
ENV

ENV =

ENV 命令は、環境変数に値を設定します。

例えば

```
ENV myVar1=1
ENV myVar42=42
ENV myAlfaVar=alfa value abc
```

私たちの小さなAlpine Linuxディストロを使って、env内のenv変数を見てみましょう。

この内容でDockerfileを作成します。

```
FROM alpine:3.8
ENV myVar1 1
ENV my42 42
ENV myVar42=42
ENV myAlfaVar='alfa abc'
```

env変数の宣言には2種類の方法を使っていることに注意してください。

画像をビルドするには

```
docker build --tag tutorial:demo --file Dockerfile  .
```

実行：

```
docker stop -t 0 tutorial ;   docker container prune -f  
docker run -ti -d --name tutorial tutorial:demo /bin/sh -c 'while true; do sleep 60; done'

docker exec -it tutorial /bin/sh
```

 #(プロンプト)でprintenvコマンドを入力します。


期待される出力

```
/ # printenv
HOSTNAME=1314796592cf
SHLVL=1
HOME=/root
my42=42
TERM=xterm
myVar1=1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
myAlfaVar=alfa abc
myVar42=42
PWD=/
/ # exit
```

宣言したenv変数はすべてそこにあります。

docker runを使うときにenv変数をオーバーライドすることができます。

実行:

```
docker stop -t 0 tutorial ;   docker container prune -f  

docker run -e  'my42=44000' -ti -d --name tutorial tutorial:demo /bin/sh -c 'while true; do sleep 60; done'
```

今コンテナに入るとmy42が44000になっているのがわかります。

```
docker exec -it tutorial /bin/sh
```

期待される出力

```
/ # printenv
HOSTNAME=1190753a779e
SHLVL=1
HOME=/root
my42=44000
TERM=xterm
myVar1=1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
myAlfaVar=alfa abc
myVar42=42
PWD=/
```

これで、DockerfileでENV変数を宣言したり、docker run -e 'my-env-var-name=new value'を使ってENV変数をオーバーライドしたりする実践的な経験ができるようになりました。

また、printenv を使って env 変数の内容を調べることもできます。(シェルプロンプトで env 変数を表示するには set や env を使うこともできます)

詳細は [https://en.wikipedia.org/wiki/Environment_variable](https://en.wikipedia.org/wiki/Environment_variable?spm=a2c65.11461447.0.0.378c2c16F541o6)

[https://docs.docker.com/engine/reference/builder/#env](https://docs.docker.com/engine/reference/builder/?spm=a2c65.11461447.0.0.378c2c165NM7Uk#env)

[https://docs.docker.com/engine/reference/builder/#environment-replacement](https://docs.docker.com/engine/reference/builder/?spm=a2c65.11461447.0.0.378c2c166RJLFa#environment-replacement)

これで4のパート2は終了です: すべてのDockerfileのインストラクションを知ることができます。もっと詳しく知りたい方は、[パート3](https://www.alibabacloud.com/blog/getting-to-know-dockerfile-instructions-part-3_594332?spm=a2c65.11461447.0.0.378c2c169ihd3x)を読んでください。

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