前回までのあらすじ
- GitHubを利用して、おじさんの成果物を公開する準備が整いつつあるよ
- 目標を立てたよ、LINE風アプリが作れるようになることを目指すよ
- 開発環境の差異を軽減することが出来ないか考えてみるよ
今回やること
- コンテナを実際に作成&起動してみるよ。
- Dockerのことを調べながら作業を進めていくよ。
Dockerでコンテナを実行するまでの流れ
- Docker overviewに概要が書いてあるよ。
- (1) Dockerfileを書く。
- Dockerfileとは・・・
- アプリの実行環境(コンテナ)を作成するための手順&指示書のようなもの。
- コンテナ内で何(アプリ等)をどのように実行するのかについても書く。
-
Dockerfile reference
- Dockerfileの書き方が書いてあるよ。
-
Best practices for writing Dockerfiles
- 効率的?最良?なDockerfileの作成方法が書かれているよ。
- このような推奨される方法をベストプラクティスなんて呼ぶらしいよ。(なんだかかっこいいね)
- 一読した方が、無駄が省けるかもしれないね。おじさんの場合、どうしてそうするべきなのか、なんて考えながら読むから大変だよ。
- Dockerfileとは・・・
- (2) Dockerfileを元にイメージを作成する。
-
イメージとは・・・
- コンテナの元。
- コンテナの実行に必要なものが梱包されたファイル。
- Dockerfileを元にイメージファイルを作成することが出来る。
- 「docker build」コマンドを使用する。
- イメージはベースイメージを元に作成する。作成元となったイメージをベースイメージと呼ぶみたい。
- ベースイメージは、Docker Hubなどのレジストリ(誰かが作成したイメージのカタログ集のようなもの)に登録されている。
- ベースイメージ自体も自分で作成することが出来るみたいだよ。
-
イメージとは・・・
- (3) イメージを元にコンテナを作成&実行する。
- 「docker run」コマンドを使用する。
Dockerfileの書き方
- コンテナを作成&実行するには、イメージが必要だってわかったよ。
- イメージを作成するには、Dockerfileが必要だってわかったよ。
- だから、おじさん、Dockerfileを書けるようになろうと思うんだ。
- イメージを作成するには、Dockerfileが必要だってわかったよ。
- 書き方
- Dockerfile referenceに書いてあるよ。
形式(フォーマット)
- Dockerfileの1行は、「命令(INSTRUCTION) 半角スペース 引数(arguments)」の形式で書くみたいだよ。
(補足) 引数とは、命令のパラメータのようなものだよ。 - 「#」の行は、コメント行として解釈するので、「#」以降は、メモや説明文など、好きに書いて良いみたいだよ。
## Comment
INSTRUCTION arguments
ベースイメージの決定
- イメージの基礎(もと)となるベースイメージを決定する必要があるみたいだよ。
- ベースイメージには、コンテナ内で使用するLinuxディストリビューション(Linuxカーネルを除く)の一部が含まれるため、想定する本番環境を見据えてベースイメージを選択するべきだと、おじさんは考えたよ。
- Linuxカーネルは互換性を考慮して開発されているらしいので、ホストOSのLinuxカーネルと、ベースイメージが想定するLinuxカーネルが異なっていたとしても、正常に動作する可能性があるかもだけど、おじさんは小心者なので、誰かが保証してくれるような組み合わせが良いと思うんだよ。
- 最終的に本番環境をどのサーバにするか考えないとね・・・
- DockerCE(無償版)の場合、公式サイトで2つのクラウド環境にインストールする解説があるよ。
- Azure
-
AWS(Amazon Web Services)
- ひとまずAWS(Amazon Web Services)を本番環境の候補として考えておくよ。
- AWSの環境に最適化されたLinuxがあるみたい。
-
Amazon Linux 2
- Amazon Linux 2に対応するベースイメージが用意されているみたい。
-
Amazon Linux 2
- AWSの環境に最適化されたLinuxがあるみたい。
- ひとまずAWS(Amazon Web Services)を本番環境の候補として考えておくよ。
- DockerCE(無償版)の場合、公式サイトで2つのクラウド環境にインストールする解説があるよ。
- ベースイメージの指定をDockerfileに書く。
- 「FROM」で指定する。
- ベースイメージを指定する。
- Dockerfileの冒頭に書く必要(ARGを除く)がある。
- ひとまず、エイヤで、AWSを本番環境にすることを見据えて、ベースイメージに「amazonlinux」を指定するよ。
- このあたりは、開発が進むにつれて、検証してみたいな。
- 「FROM」で指定する。
FROM amazonlinux:2.0.20190508
- FROM以降の「amazonlinux」が、イメージの種類を表す名前。
- 「:」(コロン)以降が、バージョン(タグと呼ぶ)を表すらしいよ。
- おじさんが、作業した時点の最新版が「2.0.20190508」だったんだ。
- 「2.0.20190508」の代わりに、「latest」と書くと、最新版を指定することになるみたいだよ。
- バージョンや更新履歴はDocker HubのWebサイトから確認することが出来たよ。
ベースイメージに関して気になること
- Amazon Linux2に対応するベースイメージを今回は使用することにしたよ。
- だけど、Docker Hub上には様々な開発者が作成&登録したベースイメージが保管されているみたいだよ。
- 小心者のおじさんの場合、誰が作成したものか不安になっちゃうよ・・・。
- おじさんの場合は、「Docker Official Images」(Docker公式イメージ)と、お墨付きのあるものだけを使用することにしたよ。
- 公式イメージの場合、セキュリティの専門家も含む、Dockerのチームがレビューするみたいだよみたいだよ。
- 公式イメージのガイドラインも用意されていて、非公式のイメージと比較すると、何だか手厚そうな気がするよ・・・。
実行するプログラム(アプリやサービス)の決定
- まだおじさんは何も開発していないから、Linuxに元から存在するコマンドをコンテナ内で起動出来るか試してみるよ。
- macOSのターミナルでも試すことが出来るけど、次のコマンドをコンテナ内で実行することにしたよ。
- 「uname」がコマンドの名前だよ。OSの種類や名前などを表示するコマンドだよ。
- 「-a」は、コマンドに指定するパラメータで、全ての情報を表示するように指示するものだよ。
uname -a
- コンテナ内で実行するプログラムを、Dockerfileに書く。
- 「CMD」で指定する。
- 書き方は次の通り。
# パラメータはカンマ区切りで複数書くことが可能だよ。不要ではれば省略も出来るよ。
CMD ["実行するプログラムの名前","パラメータ"]
- 最終的なDockerfileは次のように書く予定だよ。
FROM amazonlinux:2.0.20190508
CMD ["uname", "-a"]
実際にDockerfileを作成する
作業用のフォルダ(ディレクトリ)を作成する
mkdir ~/dockertest1
- mkdirはフォルダ(ディレクトリ)を作成するコマンドだよ。
- 「~/」はログインユーザの個人フォルダ(ホームディレクトリと呼ぶらしいよ)の場所を表す省略形だよ。
- コマンドを実行すると、ホームディレクトリ直下に「dockertest1」フォルダ(ディレクトリ)が作成されるよ。
Dockerfileを作成する
「ファイル」ー「保存」
-
Dockerfileを作成することが出来たよ。これからDockerfileを編集していくよ。
VS Codeを使用して、Dockerfileに指示を書く
- 次の通りDockerfileを編集するよ。
FROM amazonlinux:2.0.20190508
CMD ["uname", "-a"]
- VS Codeではこんな感じ。
Dockerfileからイメージを作成する
- 作成したDockerfileを元に、イメージを作成するには、「docker build」コマンドを使用するよ。
- まずはターミナルで次のコマンドを実行するよ。
- 作業するフォルダ(ディレクトリ)をホームディレクトリ直下に作成した「dockertest1」に移動。
cd ~/dockertest1
- 続けて、ターミナルで次のコマンドを実行するよ。
docker build -t ojisanimg1:1.0 .
- 「-t ojisanimg1:1.0」は、作成するイメージにつけるタグ(目印や名前のようなもの)を指定しているよ。
- タグの詳細はここに書いてあるよ。
- タグは、コンテナを作成するときなどに、どのイメージから作成するのか、イメージを特定するために利用することが出来るよ。
- タグは、「リポジトリ名:バージョン」の形式で書くよ。
- リポジトリ名は、おじさんも何を指すのかよくわかってないけど、イメージを表す名前のようなものと解釈しているよ。
- 今回、「ojisanimg1」をリポジトリ名に指定してみたよ。
- バージョンはイメージのバージョンを指定するよ。
- 「ojisanimg1:latest」のように書くことも可能だよ。
- タグは「docker build -t ojisanimg1:1.0 -t ojisanimg1:latest .」のように複数書くことも出来るよ。
- 末尾の「.」(ドット)は、あとでおじさんの理解を書くことにするよ。
- コマンドを実行すると、次のように処理が実行されるよ。
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM amazonlinux:2.0.20190508
2.0.20190508: Pulling from library/amazonlinux
72d97abdfae3: Pull complete
Digest: sha256:730fae68c6a180e8006443b0f090e56419da5ceb5d11250d96e627660ffbc674
Status: Downloaded newer image for amazonlinux:2.0.20190508
---> b94321659aca
Step 2/2 : CMD ["uname", "-a"]
---> Running in b7c713fd524a
Removing intermediate container b7c713fd524a
---> 272308db775e
Successfully built 272308db775e
Successfully tagged ojisanimg1:1.0
- 「docker build」の末尾の「.」(ドット)は、イメージの作成に必要なファイル(Dockerfileも含めて)の場所を指定するものだよ。
- macOS/Windows/Linuxなどの一般的なOSでは、「.」(ドット)は、現在作業中のフォルダ(ディレクトリ)の場所を意味するよ。
- 次のコマンドで、作業場所をホームディレクトリ直下の「dockertest1」フォルダ(ディレクトリ)に変更したので・・・
cd ~/dockertest1
-
今回の「.」は、「~/dockertest1」と同じ意味になるよ。(cdで作業場所を~/dockertest1に変更しているので)
- つまり、「~/dockertest1」以下にあるファイルを利用して、イメージを作成するように、指示したってことなんだよ。
-
詳しくはここに書いてあるよ。
- macOSにインストールしたdockerコマンドを利用して、イメージ作成を指示することが出来るよ。
- イメージの作成は、macOSのなかで実行されるのではなく、ハイパーバイザー上で動作するLinuxのなかでイメージは作成されるんだよ。
- macOSと、Linuxの仲介役が「Docker daemon」と呼ばれるプログラム(サービス)だよ。
- Docker daemonは、イメージ作成の指示の他に、イメージを作成するために必要なファイル(Dockerfileなど)を受け取り、イメージを作成するよ。
- 以上から、docker build実行時の作業場所「.」に、巨大なファイルが無数に置いてある状況の場合、処理に時間がかかる可能性があると思うよ。(おじさんは試してないけどね・・・)
イメージを作成したことを確認する
- 「docker images」コマンドを使用するよ。
- 次のコマンドを実行することで、Docker daemonに作成済みのイメージ一覧を問い合わせすることが出来るよ。
- 次の通り、ターミナル上で入力してみたよ。
docker images
- 実行結果だよ。
REPOSITORY TAG IMAGE ID CREATED SIZE
ojisanimg1 1.0 272308db775e About an hour ago 162MB
amazonlinux 2.0.20190508 b94321659aca 12 days ago 162MB
- 「amazonlinux:2.0.20190508」はベースイメージだね!
- おじさんが作成したイメージは、タグで「ojisanimg1:1.0」指定した通りに作成されていることがわかるね!
- amazonlinuxのベースイメージと、サイズが同じなので、ベースイメージを元に作成されたことが読み取れるね。
作成したイメージからコンテナを作成&実行する
- 「docker run」コマンドを使用するよ。
- 作成したイメージから、コンテナを作成&実行するために、次のコマンドをターミナルで実行してみるよ。
docker run ojisanimg1:1.0
- 実行結果だよ。
Linux 3140d1e9940c 4.9.125-linuxkit #1 SMP Fri Sep 7 08:20:28 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
- uname(OS名などの情報表示)コマンドの実行結果が表示されたよ!!!!
- Linuxと表示されている(macOSではない)ので、コンテナ内で実行されたことがわかるね! ハッピー。
コンテナの存在を確認する
- コンテナの一覧を表示するには、「docker ps」コマンドを使用するよ。
- 次のコマンドをターミナルで入力すると、Docker daemonに実行中のコンテナの一覧を問い合わせすることが出来るよ。
docker ps
- 実行結果だよ。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- CONTAINER IDなど、列名が出てきただけで、コンテナがまるで表示されていないよ・・・・
- 「-a」をつけて、「docker ps」をつけると、実行中か否かに関わらず、作成されたコンテナを確認することが出来るみたいだよ。
docker ps -a
- 実行結果だよ。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3140d1e9940c ojisanimg1:1.0 "uname -a" About a minute ago Exited (0) About a minute ago vibrant_ptolemy
- 1つのコンテナの存在を確認することが出来たよ。
- STATUS列をみると、「Exited(0)」と書いてあるよ。
- exitedはコンテナ内で実行するプログラム(メインプロセス)が終了したことを表すみたいだよ。
- つまり、今回の場合は、「uname」コマンドが(適切に実行された後に)終了したことを意味するよ。
- STATUS(状態)は、「created, restarting, running, removing, paused, exited, dead」などの状態があるみたい。
- 「docker ps」では、実行中のコンテナのみがリストアップされるけど、既にコンテナが終了していたために、何も表示されなかったんだね。
- 「docker ps -a」とすることで、停止したコンテナの存在を確認することが出来たよ。
停止したコンテナを再実行してみる
- まずは「docker ps -a」で、コンテナの一覧を確認するよ。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3140d1e9940c ojisanimg1:1.0 "uname -a" About a minute ago Exited (0) About a minute ago vibrant_ptolemy
- 停止したコンテナのコンテナID(CONTAINER ID)を確認するよ。おじさんの環境では「3140d1e9940c」だったよ。
- 「docker start」コマンドで、作成済みのコンテナを起動することが出来るよ。
docker start 3140d1e9940c
-- 実行結果だよ。
3140d1e9940c
- あれれ・・・先程のように、unameの実行結果が表示されずに、コンテナIDが表示されただけだよ・・・。
- 「docker ps -a」で、もう一度、コンテナを確認してみるよ。
docker ps -a
- STATUS(状態)をみると、「5 seconds ago」とあり、コンテナが5秒前に実行されたことがわかるよ。なので、再実行されたことは間違いないみたいだよ。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3140d1e9940c ojisanimg1:1.0 "uname -a" 2 hours ago Exited (0) 5 seconds ago vibrant_ptolemy
- docker startの資料をみると、「-a」のパラメータを指定することで、おじさんのターミナルに、コンテナが出力する結果を表示させることが出来ることがわかったよ。
docker start -a 3140d1e9940c
- 実行結果だよ。今度はちゃんと、ターミナルに実行結果が表示されたよ。
Linux 3140d1e9940c 4.9.125-linuxkit #1 SMP Fri Sep 7 08:20:28 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
再びdocker runしてみる
- おじさん、素朴な疑問として、docker runと、docker startの違いがよくわからなくなってきたんだ。
- もう一度、docker runしてみるよ。
docker run ojisanimg1:1.0
- 実行結果だよ。
Linux f84e04390638 4.9.125-linuxkit #1 SMP Fri Sep 7 08:20:28 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
- docker ps -aで、コンテナの一覧を問い合わせてみるよ。
docker ps -a
- 実行結果だよ。
- コンテナが2つに増えたことがわかるよ!!
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f84e04390638 ojisanimg1:1.0 "uname -a" 4 seconds ago Exited (0) 3 seconds ago optimistic_meninsky
3140d1e9940c ojisanimg1:1.0 "uname -a" 2 hours ago Exited (0) 9 minutes ago vibrant_ptolemy
- もう一度、docker run後に、docker ps -aしてみるよ!
docker run ojisanimg1:1.0
docker ps -a
- 実行結果だよ。
- コンテナは3つに増えたよ。このことからも、docker runは、イメージを元に新規にコンテナを作成して、そのコンテナを実行していることが読み取れるよ。
- 一方のdocker startは、作成済みのコンテナを起動するコマンドであり、コンテナの作成までは出来ないみたいだよ。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9713cd6301ac ojisanimg1:1.0 "uname -a" 4 seconds ago Exited (0) 2 seconds ago confident_lamport
f84e04390638 ojisanimg1:1.0 "uname -a" 4 minutes ago Exited (0) 4 minutes ago optimistic_meninsky
3140d1e9940c ojisanimg1:1.0 "uname -a" 2 hours ago Exited (0) 14 minutes ago vibrant_ptolemy
- docker runの説明にも書いてあるように、新規に作成したコンテナを実行するコマンドだって理解したよ。
- docker startの説明にもあるように、作成済み(停止中)のコンテナを実行するコマンドだって理解したよ。
おじさんの疑問点、コンテナは実行してもすぐに停止する
- コンテナの状態(exited)に関して書かれている記事を読むと、コンテナは、そのコンテナ内で実行されるプログラム(メインプロセス)が終了すると、コンテナは停止(exited状態になる)するものと読みとったよ。
- おじさんの妄想だけど、Dockerfile内の「CMD」で、コンテナ内で実行するプログラムを指定することが出来たけど、このプログラムが動き続けるようなものであれば、コンテナも動作し続けるのだろうと予想したよ。
- このあたりは、開発が進むにつれて、少しずつ理解・体験していこうと考えているよ。
不要になったコンテナを削除してみる
- まずは、docker ps -aで、コンテナの一覧を問い合わせするよ。
docker ps -a
- 結果だよ。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9713cd6301ac ojisanimg1:1.0 "uname -a" 25 minutes ago Exited (0) 25 minutes ago confident_lamport
f84e04390638 ojisanimg1:1.0 "uname -a" 30 minutes ago Exited (0) 30 minutes ago optimistic_meninsky
3140d1e9940c ojisanimg1:1.0 "uname -a" 3 hours ago Exited (0) 39 minutes ago vibrant_ptolemy
- コンテナを削除するには、「docker container rm」コマンドを使用するよ。
- 次のように、削除したいコンテナのコンテナIDを指定するよ。
docker container rm 9713cd6301ac
- 実行結果だよ。
9713cd6301ac
- 再び、docker ps -aしてみるよ。
docker ps -a
- 実行結果だよ。コンテナが1つ消えたことがわかるね!
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f84e04390638 ojisanimg1:1.0 "uname -a" 31 minutes ago Exited (0) 31 minutes ago optimistic_meninsky
3140d1e9940c ojisanimg1:1.0 "uname -a" 3 hours ago Exited (0) 41 minutes ago vibrant_ptolemy
- ひとつひとつ削除するのも面倒。「docker container prune」コマンドを使用すると、停止中の全てのコンテナを一括で削除することが出来るよ。
docker container prune
- 実行すると、警告の表示とともに、処理を続けるかどうか尋ねられる。
- 続行するので、「y」と入力してエンターキーを押下するよ。
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
- すると、次のように表示され、コンテナが削除されるよ。
Deleted Containers:
f84e043906380f4df6b7c756a28743370bbfd8a798f86db19a9687454f9c6683
3140d1e9940c8d942160a592dc1d86d746d10f6726383d09d5ed93053ed7ba93
Total reclaimed space: 0B
- 本当に削除されたのか、docker ps -aで確認するよ。
docker ps
- 実行結果だよ。 停止中の全てのコンテナが削除されたよ。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
不要になったイメージを削除してみる
- まずは、docker imagesで、作成済みのイメージ一覧を問い合わせするよ。
docker images
- 実行結果だよ。
REPOSITORY TAG IMAGE ID CREATED SIZE
ojisanimg1 1.0 272308db775e 4 hours ago 162MB
amazonlinux 2.0.20190508 b94321659aca 12 days ago 162MB
- イメージの削除は、「docker rmi」コマンドを使用するよ。
- 削除するイメージIDをパラメータに指定してコマンドを実行するよ。
docker rmi 272308db775e
- 実行結果だよ。
Untagged: ojisanimg1:1.0
Deleted: sha256:272308db775e4c0e34fd4a80da0162d60ccd8571fa2c79cd10f6a820a130025a
- 本当に削除出来たか、docker imagesしてみるよ。
docker images
- 実行結果だよ。 削除出来た!
REPOSITORY TAG IMAGE ID CREATED SIZE
amazonlinux 2.0.20190508 b94321659aca 12 days ago 162MB
今回のまとめだよ
- コンテナを実行するには、アプリやアプリの実行環境を梱包したイメージが必要だったよ。
- イメージを作成するには、Dockerfileにコンテナの実行環境や、実行するアプリを指定する必要があったよ。
- 実際にDockerfileを書いてみたよ。 イメージを作成するには、その元となるベースイメージが必要だったよ。
- docker buildで、Dockerfileを元にイメージを作成することに成功したよ。
- docker runで、イメージからコンテナを作成&実行することが出来たよ。
- コンテナは、コンテナ内のアプリ(メインプロセス)が終了すると、コンテナも停止するみたいだよ。
- 停止したコンテナは、docker startで再び実行することも出来たよ。
- 不要なコンテナや、イメージを削除する方法がわかったよ。
あとがき
- いよいよ、次回はWebサーバとやらの準備に入るよ! なかなかアプリの開発に到達しないね・・・。
- どこかの誰かも同じように手を動かして、アプリを開発していると思うと、おじさんも一歩前進したのかな、なんて思ったりもしたよ。
-
Best practices for writing Dockerfilesに書いていることが気になるよ。進めていくうちに、再び登場するかもしれないよ。
- 特に、この引用が気になるんだよ、おじさん。
- イメージから、コンテナ(アプリの実行環境)を増殖することが出来る点に、何だかワクワクするものを感じたよ。
参照・メモ
Docker overview
Best practices for writing Dockerfiles
Dockerfile reference
Docker CLI reference
Amazon Linux 2
Docker Official Images - amazonlinux
Twelve-Factor App