リポジトリとDockerfile、そしてビルド

記事タイトルとURLをコピーする

はじめに

こんにちは。孔子の80代目子孫兼技術5課の孔です。最近暑いなと思っていたら、昨日から雨が降っていて今日は朝からとても寒いですね。おかげさまで途中で起きることなくぐったり寝ることができました。

前回はDockerとは、イメージとは、そしてレイヤーとはどのようなものなのかをみてみました。こちらの知識はDockerの最も基本的な概念となりますが、Dockerを使うにあたってまだまだ必要な基礎知識があります。それが今回ご説明いたします、リポジトリとDockerfile、そしてビルドとなります。それでは、早速みていきましょう。Let's get it!

リポジトリとは

前回の記事でコンテナのベースとなるイメージというものがどのようなものなのか説明しました。このイメージをどのように管理するのかを今からみていきます。前回の記事でhttpdをダウンロードしたこと、覚えてますでしょうか。こちらのものになります。

kong@KongnoAir ~ % docker container run -d httpd
Unable to find image 'httpd:latest' locally
latest: Pulling from library/httpd
afb6ec6fdc1c: Pull complete 
5a6b409207a3: Pull complete 
41e5e22239e2: Pull complete 
9829f70a6a6b: Pull complete 
3cd774fea202: Pull complete 
Digest: sha256:db9c3bca36edb5d961d70f83b13e65e552641e00a7eb80bf435cbe9912afcb1f
Status: Downloaded newer image for httpd:latest
e29f06721a6e7593240fd73a62a429bb3dde7e63c27bb81679c6196ac5c53f99

コンテナを起動するコマンドを入力したときに、その結果をみてください。まず2行目で”Unable to find image 'httpd:latest' locally”と言われてますね。Dockerはイメージをローカルに保存し、コンテナを起動する際にイメージがローカルにあるかどうかをまずチェックします。もしなかったらイメージをリポジトリにダウンロードしにいきます。それでは、このリポジトリというものは一体何でしょう?

リポジトリはイメージを保管しているサーバとなります。デフォルトではDockerhubが指定されています。Dockerhubに入り、httpdイメージを検索してみるとhttpdというイメージが一番上に出てくるのがわかります。コンテナを起動する際に指定したイメージがローカルになかった場合、リポジトリをみに行ってhttpdがあるかどうかを検索し、あったらダウンロードしてコンテナを起動する流れとなります。

API-Driven DevOps: Spotlight on Docker | Nordic APIs |

前回使用した図となりますが、こちらのレジストリの中にhubというものがありますね。いろいろなレジストリ上にイメージを保存し、そこからイメージをダウンロードしてコンテナを立ち上げるのが基本的なコンテナ構築の流れです。

デフォルトリポジトリ(Dockerhub)以外のリポジトリを指定するときにはイメージ名の前にurlを指定するだけです。AWSのECRのドキュメントに記載されているコマンドを持ってきました。このように、amazonlinux:latestというイメージをダウンロードする際にaws_account_id.dkr.ecr.us-west-2.amazonaws.com/というurlから持ってきて!という命令になります。(原本はコマンドがdocker pullになっていますが、こちらは任意でdocker image pullに変更しました。コマンドについては次回詳細に説明します)

docker image pull aws_account_id.dkr.ecr.us-west-2.amazonaws.com/amazonlinux:latest

リポジトリを簡単に要約しますと、イメージを蓄えておいて必要なときにダウンロードできる場所、と覚えると良いかと思います。

Dockerfileとは

イメージをリポジトリからダウンロードできることがわかった今、それではこのイメージってどうやって作るんだろうという疑問がそろそろ出てくるのではないかと思います。そのイメージを作成するために必要なものがDockerfileとなります。Dockerfileはイメージをビルドするときに、このイメージがどのようなものなのかを定義したものとなります。以下の例をみてください。

FROM debian:buster-slim

ENV NGINX_VERSION   1.17.10
ENV NJS_VERSION     0.3.9
ENV PKG_RELEASE     1~buster

<中略>

RUN ln -sf /dev/stdout /var/log/nginx/access.log \
    && ln -sf /dev/stderr /var/log/nginx/error.log

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

こちらはnginxのDockerfileの一部となります。解説すると

  • FROM:ベースイメージとしてどのOSイメージを使用するか(Debianを使用する)
  • ENV:環境変数を指定する
  • RUN:イメージをビルドする際に実行するコマンドを指定する
  • EXPOSE:どのポートを開けるか
  • CMD:コンテナを作成する際に実行するコマンドを指定する

となります。もっといろいろなDockerfileのコマンドを知りたい方はこちらのドキュメントをご覧ください。このように、Dockerfileではこのイメージがどのようなイメージとなるのか、その詳細を記入しているファイルだな、ということをイメージできればいいかと思います。

ビルド

Dockerfileを作成したら、ビルドをすることでイメージを作ることができます。以下のシェルをみてください。

kong@KongnoAir ~ % docker image build -t test:latest .
Sending build context to Docker daemon  6.499MB
Step 1/2 : FROM ubuntu
 ---> 1d622ef86b13
Step 2/2 : RUN apt-get update
 ---> Running in 29924a2ea92e
Get:1 http://security.ubuntu.com/ubuntu focal-security InRelease [107 kB]
<中略>
Fetched 13.8 MB in 8s (1659 kB/s)
Reading package lists...
Removing intermediate container 29924a2ea92e
 ---> 98d48c9e8359
Successfully built 98d48c9e8359
Successfully tagged test:latest

docker image buildは、Dockerfileをビルドするためのコマンドです。-t オプションはイメージの名前をつけるもので、今回はtestというイメージ名とlatestというタグを付けました。最後の点(.)は「現在のディレクトリにあるDockerfileという名前のファイル」を指定しています。こちらはもちろんパスやファイル名を指定することも可能です。

ビルドの内容をみてみると、ベースのubuntuイメージにapt-get upudateをしているだけのイメージとなります。Dockerfileのそれぞれの命令を見て、イメージを作っていきます。

追加で、こちらのシェル画面もみてください。

kong@KongnoAir code_local % docker image build -t test:latest .                                                                         ~/Documents/code_local
Sending build context to Docker daemon  6.499MB
Step 1/2 : FROM ubuntu
 ---> 1d622ef86b13
Step 2/2 : RUN apt-get update
 ---> Using cache
 ---> 98d48c9e8359
Successfully built 98d48c9e8359
Successfully tagged test:latest
kong@KongnoAir code_local % docker image build -t test2:latest .
Sending build context to Docker daemon  6.499MB
Step 1/2 : FROM ubuntu
 ---> 1d622ef86b13
Step 2/2 : RUN apt-get update
 ---> Using cache
 ---> 98d48c9e8359
Successfully built 98d48c9e8359
Successfully tagged test2:latest
kong@KongnoAir code_local % docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
test2               latest              98d48c9e8359        2 minutes ago       95.5MB
test                latest              98d48c9e8359        2 minutes ago       95.5MB
httpd               latest              d4e60c8eb27a        4 days ago          166MB
ubuntu              latest              1d622ef86b13        3 weeks ago         73.9MB

もう一度同じ名前でビルドをしてみると、今回はStep2のところで”Using cache”と言われています。これが前回説明したレイヤーとなるものです。ビルドしたイメージはレイヤーの重なりであることを覚えていますでしょうか。一回ビルドを行っていたので、レイヤーをDockerデーモンが保持している状態となります。ですので次回もし同じレイヤーを使用するようなビルドがあったらレイヤーを共有してビルドを速度をあげています。イメージ名をtest2に変えた時も同様で、このようにレイヤーを共有することによってDockerはビルドの速度をあげることができています。

最後に

今回はリポジトリ、Dockerfile、そしてDockerfileのビルドまでみてみました。基本的な概念はこれで一通り触れることができたと思いますので、次回は重要なコマンドを一つずつ紹介し、今まで説明した内容をコマンドを使って実際やってみようと思っています。それではお楽しみに!