本連載では、Dockerに興味はありつつも、まだ触ったことのない方向けに、実際に触ってDockerについて理解していただくための記事を提供します。第1回では、Dockerの概要および最も基本であるイメージとコンテナの管理について実際の操作方法をステップごとに紹介しました。第1回では、公開されているイメージを利用しましたが、自分で開発しているアプリケーションをDockerイメージとして配布するためには、自分でイメージを作成できる必要があります。そこで第2回の本記事では、自分でイメージを作成し、コンテナを起動する方法について紹介します。なお、本記事のサンプルは、Docker社が公開している初心者向けチュートリアルの内容をベースにしています。ご興味あれば、こちらも参照ください。
Dockerイメージビルドの仕組み
最初にDockerでイメージを作成する際の仕組みについて紹介します。
Dockerイメージのビルドとは、ベースとなるイメージに対して、何らかの機能を加えて、ユーザイメージ(自分独自のイメージ)を作り出すことを指します。
ベースイメージは、通常、Docker社またはDockerコミュニティが提供するOSのイメージになることが多いです。そのイメージに対して各種依存ライブラリやミドルウェアをインストールしたり、自分のアプリケーションをインストール・設定したりすることで、ユーザイメージを作ります。このユーザイメージを第3者に配布することで、ライブラリ・ミドルウェア・アプリケーションなどを全て包含した形で配布することが可能になります。
このとき、ベースイメージに対して実行する操作を記述する設定ファイルが「Dockerfile」です。Dockerfileは、Docker社によって記述方法が規定されています。詳細はドキュメントを参照ください。
サンプルイメージのビルド
本記事では、flaskというPython用のWebアプリケーションフレームワークを使ったWebアプリケーションを配布するためのDockerイメージを構築します。アプリケーションは、ランダムに猫のGIF画像を表示するというものです。なお、本記事では、flask自体の詳細な説明は割愛します。
ビルドに必要なファイルの準備
ディレクトリを作成し、以下の手順でイメージのビルドに必要な4つのファイルを取得してください。
mkdir flask-app cd flask-app wget https://raw.githubusercontent.com/docker/labs/master/beginner/flask-app/app.py wget https://raw.githubusercontent.com/docker/labs/master/beginner/flask-app/requirements.txt wget https://raw.githubusercontent.com/docker/labs/master/beginner/flask-app/templates/index.html -P templates wget https://raw.githubusercontent.com/docker/labs/master/beginner/flask-app/Dockerfile
次に、各ファイルの内容について紹介します。
app.pyはWebアプリケーションのエントリーポイントとなるソースコードです。Web上のGIF画像を取得して、ランダムにそのURLを返すという処理を行います。
from flask import Flask, render_template import random app = Flask(__name__) # list of cat images images = [ "https://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr05/15/9/anigif_enhanced-buzz-26388-1381844103-11.gif", "https://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr01/15/9/anigif_enhanced-buzz-31540-1381844535-8.gif", "https://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr05/15/9/anigif_enhanced-buzz-26390-1381844163-18.gif", "https://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr06/15/10/anigif_enhanced-buzz-1376-1381846217-0.gif", "https://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr03/15/9/anigif_enhanced-buzz-3391-1381844336-26.gif", "https://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr06/15/10/anigif_enhanced-buzz-29111-1381845968-0.gif", "https://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr03/15/9/anigif_enhanced-buzz-3409-1381844582-13.gif", "https://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr02/15/9/anigif_enhanced-buzz-19667-1381844937-10.gif", "https://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr05/15/9/anigif_enhanced-buzz-26358-1381845043-13.gif", "https://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr06/15/9/anigif_enhanced-buzz-18774-1381844645-6.gif", "https://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr06/15/9/anigif_enhanced-buzz-25158-1381844793-0.gif", "https://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr03/15/10/anigif_enhanced-buzz-11980-1381846269-1.gif" ] @app.route('/') def index(): url = random.choice(images) return render_template('index.html', url=url) if __name__ == "__main__": app.run(host="0.0.0.0")
requirements.txtは、必要なPythonモジュール記載したファイルです。pip(パッケージマネジャー)を使い、flaskをインストールする際に利用します。
Flask==0.10.1
templates/index.htmlは、Webアプリケーションで出力するHTMLのテンプレートです。猫画像の表示のみ行います。
<html> <head> <style type="text/css"> body { background: black; color: white; } div.container { max-width: 500px; margin: 100px auto; border: 20px solid white; padding: 10px; text-align: center; } h4 { text-transform: uppercase; } </style> </head> <body> <div class="container"> <h4>Cat Gif of the day</h4> <img src="{{url}}" /> <p><small>Courtesy: <a href="https://www.buzzfeed.com/copyranter/the-best-cat-gif-post-in-the-history-of-cat-gifs">Buzzfeed</a></small></p> </div> </body> </html>
Dockerfileは、Dockerデーモンがイメージを作成する際に実行するコマンド群をまとめたファイルです。サンプルのDockerfileでは、以下の内容の処理を行っています。Dockerfileの文法については後述します。
- ベースイメージとしてAlpine Linux(Docker用に開発されている軽量なLinuxディストリビューション)を指定する。
- Pythonとpip(パッケージマネジャー)をインストールする。
- pipでアプリに必要なPythonモジュールをインストールする。
- app.pyとindex.htmlを所定の位置にコピーする。
- ポート5000番を外部に公開する。
- Web アプリケーションを実行する。
# our base imag FROM alpine:latest # Install python and pip RUN apk add --update py-pip # install Python modules needed by the Python app COPY requirements.txt /usr/src/app/ RUN pip install --no-cache-dir -r /usr/src/app/requirements.txt # copy files required for the app to run COPY app.py /usr/src/app/ COPY templates/index.html /usr/src/app/templates/ # tell the port number the container should expose EXPOSE 5000 # run the application CMD ["python", "/usr/src/app/app.py"]
(補足)Dockerfileで使われているコマンド
Dockerfileを見ると、一見、shellスクリプトのように見えますが、実際にはDockerfile特有のコマンドが使われています。サンプルのDockerfileで使われているコマンドは、以下の表に示すとおりです。文法の詳細はマニュアルに記載されていますので、参照ください。
コマンド | 意味 | 補足 |
---|---|---|
FROM | ベースイメージとなるイメージを指定する | |
RUN | イメージをビルドするためのコマンドを指定する | 「RUN apk add –update py-pip」の場合、実際には「apk add –update py-pip」の部分が実行される |
COPY | ホストからコンテナ内にファイルをコピーする | |
EXPOSE | 外部に公開するコンテナのポートを指定する | デフォルトではコンテナのポートが閉じている |
CMD | イメージからコンテナを起動するときに実行するコマンドを指定する | Dockerfile内でCMDは1個だけ指定できる |
その他、Dockerfileの書き方のベストプラクティスについては「Best practices for writing Dockerfiles」にまとめられていますので、こちらも参照ください。
イメージのビルド
Dockerデーモンが起動していないと、ビルドもできません。事前にデーモンを起動してください。
カレントディレクトリにDockerfileがある状況で、以下のコマンドを実行して下さい。Dockerfileの内容が順に実行されていることがお分かりいただけると思います。
(注)サンプルにプロキシ設定は用意されていません。HTTPプロキシがない環境で実行してください。
$ docker build -t myfirstapp . Sending build context to Docker daemon 8.192 kB Step 1 : FROM alpine:latest ---> baa5d63471ea Step 2 : RUN apk add --update py-pip ---> Using cache ---> e4c871e20ff7 Step 3 : RUN pip install --upgrade pip ---> Using cache ---> 8fcac0a6d7bb Step 4 : COPY requirements.txt /usr/src/app/ ---> Using cache ---> 873379a81443 Step 5 : RUN pip install --no-cache-dir -r /usr/src/app/requirements.txt ---> Using cache ---> 1bd8d8164130 Step 6 : COPY app.py /usr/src/app/ ---> Using cache ---> 4189ffe25189 Step 7 : COPY templates/index.html /usr/src/app/templates/ ---> Using cache ---> 88d15ee40a45 Step 8 : EXPOSE 5000 ---> Using cache ---> dfe12126ea1d Step 9 : CMD python /usr/src/app/app.py ---> Using cache ---> c35d0a17de36 Successfully built c35d0a17de36
コンテナの起動
イメージのビルドが完了したら、以下のコマンドでイメージからコンテナを起動します。
docker run -p 8888:5000 --name myfirstapp myfirstapp * Running on https://0.0.0.0:5000/ (Press CTRL+C to quit)
上記のコマンドの場合、オプションにより、コンテナ内のポート5000番をホストの8888番に指定しています。Webブラウザを開き、https://localhost:8888 にアクセスしてください。冒頭で紹介したWebアプリケーションが表示されます。
コンテナの停止・削除
起動したコンテナを停止するには、以下のコマンドを実行してください。
docker stop myfirstapp
さらに、停止したコンテナを削除するには、以下のコマンドを実行してください。
docker rm myfirstapp
まとめ
第2回となる本記事では、具体的なサンプルアプリケーションを通して、Dockerfileを使ってイメージをビルドし、イメージからコンテナを起動する方法を紹介しました。今回の記事でイメージのビルドの基礎的な部分はカバーしているため、イメージビルドの概要は把握していただけたと思います。Dockerの公式ドキュメントは非常に充実しているので、ドキュメントも合わせて参照していただければ、様々なシーンにも対応できるはずです。
今回の記事では、ローカルでビルドし、ローカルでコンテナを起動する作業を行いましたが、自分以外の人にイメージを利用してもらうには、イメージを第3者が利用できる形で公開する必要があります。次回はイメージの公開方法についてご紹介します。