とあるお兄さんの雑記

基本的に技術系の内容を書きますが、何を書くかは私の気分です。

Dockerを学ぶ第4回~Dockerfileを作成する~

HTC Advent Calendar 202020日目を担当します、kurasherです。

第4回はDockerfileです。

環境

Windows 10 Pro バージョン 1903
Docker Toolbox
Dockerバージョン: 18.09.1
VirtualBox: 6.1.16

Dockerfileとは

Docker Hubにはたくさんの既存イメージがあります。これらをベースイメージとしたとき、ベースイメージに対して実行する操作を記述する設定ファイルのことをDockerfileと言います。

一言で言ってしまえば、カスタマイズみたいなもんです。
今まではDocker Hubにある既存イメージを取得してコンテナを起動してきました。これは非常に便利ではあるのですが、一方で細かい設定が出来ませんでした。そこで、Docker Hubにある既存イメージをベースにして、我々ユーザーが自由にカスタマイズすることで新しいイメージを作り出す道具がDockerfileというファイルです。

ちなみに、ベースとなるイメージに対し、何らかの機能を加えて、ユーザイメージ(自分独自のイメージ)を作成することをDocker イメージビルドというらしいです。

コンテナ内でFlaskを起動するDockerfileを作成する

実際に動かしてみましょう。以下、3つのファイルを用意します。

Dockerfile

拡張子はつきません。気を付けましょう。

FROM python:latest

COPY requirements.txt /usr/src/app/

RUN pip install --upgrade pip

RUN pip install -r /usr/src/app/requirements.txt

COPY hello.py /usr/src/app/

CMD ["python", "/usr/src/app/hello.py"]

requirements.txt

click==6.6
Flask==0.11.1
itsdangerous==0.24
Jinja2==2.8
MarkupSafe==0.23
Werkzeug==0.11.10

hello.py

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World! from Docker"

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=8000, debug=True)

実行方法:イメージ作成

先ほどのDockerfileに書いた内容を基に、オリジナルイメージを作成します。イメージ名はflaskimgとしています。最後の.も忘れずに!

$ docker build -t flaskimg .

これで、オリジナルのイメージを作成することが出来ました。確認してみましょう。

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
flaskimg            latest              42fb6c5bcc58        9 seconds ago       896MB
python              latest              0611cf846c85        22 hours ago        885MB

出来ていれば、上記のようにflaskimgという名前があるはずです。

実行方法:コンテナ起動

先ほど作ったイメージのコンテナを起動してみます。

Docker Desktopの場合

実行は以下のようにします。

$  docker run -d --name flaskcon -p 5000:8000 flaskimg

これで、localhost:5000からアクセスできるはずです。Docker Desktopを持っていないため、確かめられていませんが...。

Play with Dockerの場合

Play with Dockerからも確かめることが出来ます。

Play with Dockerの画面を開いたら、先ほどの3ファイルすべてをPlay with Dockerのターミナル上にドラッグ&ドロップし、アップロードします。

アップロードし終わったらイメージを作成します。

$ docker build -t flaskimg .


イメージの作成が終わったらdocker runでコンテナを起動します。

$ docker run --name flaskcon -p 5000:8000 flaskimg
 * Running on http://0.0.0.0:8000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger pin code: 326-429-724

コンテナの起動が終わったら、下記の図の5000の部分をクリックします。
f:id:kurasher:20201214190837p:plain

クリック後は以下の画面が表示されればOKです。
f:id:kurasher:20201214191013p:plain

Docker Toolboxの場合

Docker Toolboxの場合、ポートフォワーディングがうまくいきません。実際に私が以下の記事で四苦八苦していることが分かります。

Docker Toolboxでポートフォワーディングできない!場合の対処法

Docker Toolboxでポートフォワーディングする場合は他の記事も参考にしながら行うようにしてください。

設定方法ですが、VirtualBoxを起動し、
default > 設定 > ネットワーク > アダプター1 > 高度(D)
まで順番にクリックしてください。すると、以下の画面まで行きつくかと思います。
f:id:kurasher:20201213211432p:plain

上図のポートフォワーディング(P)をクリックし、「ポートフォワーディングルール」という新しい画面が出てきたら以下のように設定してください。
f:id:kurasher:20201213211630p:plain

これで一応準備完了です。

(途中のポートフォワーディングルールの部分で、ホストポートを8000、ゲストポートを5000と別々にしていますが、一緒の値にしても問題ありません。ただし、hello.pyで設定したポート番号に合わせる必要があります。今回の場合、8000にしているので、ホストポートとゲストポート、どちらも8000にします。)

実行は以下のようにします。

$  docker run -d --name flaskcon -p 5000:8000 flaskimg



これで、localhost:8000からアクセスすると、以下の画面が見れると思います。
f:id:kurasher:20201213212501p:plain

Dockerfile解説

FROM python:latest

COPY requirements.txt /usr/src/app/

RUN pip install --upgrade pip

RUN pip install -r /usr/src/app/requirements.txt

COPY hello.py /usr/src/app/

CMD ["python", "/usr/src/app/hello.py"]

ここではFROMCOPYRUNCMDに焦点を当てて解説します。他のコマンドもあるので、公式等で確認するようにしてください。

コマンド 意味
FROM ベースとなるイメージを指定。必須です。
COPY [A] [B] ディレクトリパスAにあるものをコンテナ内部Bのディレクトリにコピー
RUN イメージビルド時に実行するコマンド
CMD コンテナ作成時に実行するコマンド

ここで気になるのはRUNCMDの違いですが、
RUNは、イメージビルド中
CMDは、コンテナを作成するとき
という違いがあります。下記の記事が分かりやすいです。

DockerのRUNとCMDの違い

また、Dockerfileでよく使うコマンドの一覧については下記を参照してください。
Docker超入門⑦〜よく使うDockerfileコマンド一覧〜【初心者向け】

Dockerコマンド解説

とは言っても今回は一つしかないんですが...。

$ docker build -t flaskimg .

-t イメージ名:タグ名で、イメージを作成しています。タグもつけることができ、

$ docker build -t flaskimg:v1.0 .

とすれば、TAGv1.0flaskimgのイメージが出来上がります。タグをつけた際はdocker imagesで確認してみるといいでしょう。
省略した場合、TAGは自動でlatestとなります。

また、一番最後に書かれている.ですが、これは作成したDockerfileのパスを指定しています。今回はbuildするディレクトリと同じ配下にあるため、.だけで済みます。Dockerfileを別のパスに置く必要が無ければ、buildするディレクトリに置いておいた方が間違いは少ないと思われます。

まとめ

今回学んだことです。次回、docker-composeを学びます。

やること Dockerコマンド
イメージの作成 docker build -t イメージ名:タグ名 .
Dockerfileコマンド 意味
FROM ベースとなるイメージを指定。必須です。
COPY A B ディレクトリパスAにあるものをコンテナ内部Bの位置にコピー
RUN イメージビルド時に実行するコマンド
CMD コンテナ作成時に実行するコマンド

参考

Docker Toolboxでポートフォワーディングできない!

DockerのRUNとCMDの違い

Docker超入門⑦〜よく使うDockerfileコマンド一覧〜【初心者向け】