はじめに
Dockerを勉強するにあたり、素晴らしいチュートリアル動画があったのでそれを元に自分で手を動かして見ました。リンク先の動画は英語ですので、日本語で少し補足をしながら進めていきます。初心者のため認識の誤りがあるかもしれませんので、その際はコメント頂けると幸いです。
事前にdocker、docker-composeのインストールが必要です。
元動画
productディレクトリにはjsonを返すAPIをpythonで用意します。
websiteディレクトリには画面を描画するphpを用意します。
product
まずはdocker_tutorial配下にproductディレクトリを作成します。
$ mkdir product
そしてシンプルなPythonコードを作成します。flaskとflask_restfulというライブラリを使用します。
from flask import Flask
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class Product(Resource):
def get(self):
return{
'products': [
'Ice cream',
'Chocolate',
'Fruit'
]
}
api.add_resource(Product, '/')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80, debug=True)
ローカル環境にpythonをインストールしている場合は、pip installなどでライブラリをインストールしますが、Dockerを使用した場合は個別にインストールする必要はありません。その代わりにコンテナ起動時に必要となるライブラリなどを以下のテキストファイルに記載するか、後述のDockerfile内にpip installのコマンドを記載します。バージョンはライブラリの公式サイトなどを参照して使用したいバージョンを記載します。
Flask==0.12
flask-restful==0.3.5
次にDockerfileを作成します。
DockerfileはDocker上で動作させるコンテナの構成情報を記述するためのファイルです。
FROM python:3-onbuild
COPY . /usr/src/app
CMD ["python", "api.py"]
FROM
FROMにはベースとするDockerイメージを指定します。また「onbuild」を記載することで、Dockerfile を使って docker build をするとき、Dockerfile 内で pip install を書かなくても Dockerfile と同じディレクトリに requirements.txt があると自動的にインストールをするようになっています。
COPY
COPYにはローカルファイルをDockerイメージのどこにコピーするかを記載します。今回の場合はproductディレクトリをDocker上の/usr/src/app内にコピーします。
CMD
CMDにはコンテナ起動時に実行するコマンドを記載します。
次にdocker-compose.ymlを作成します。docker-composeには
- Dockerイメージをビルドするための情報(使用するDockerfile、イメージ名など)
- コンテナ起動するための情報(ホストとの共有ディレクトリ設定やポートフォワードなどの起動オプションなど)
- 使用するDockerネットワーク
などを記載します。
version: '3'
services:
product-service:
build: ./product
volumes:
- ./product:/usr/src/app
ports:
- 5001:80
version
docker-composeで使用するバージョンを記載します。現在はバージョン3が最新ですので、3を指定します。
services
アプリケーションを動かすための各要素をServiceと読んでいます。各サービスをネストしてこちらに記載します。今回の場合は「product-service」というサービスを起動します。
build
指定したディレクトリにあるDockerfileでコンテナを起動します。今回の場合はproductディレクトリのDockerfileでコンテナを起動します。
volumes
ローカリのディレクトをコンテナのディレクトにマウントします。今回の場合はproductディレクトリをコンテナ上の/usr/src/appディレクトリにマウントします。
ports
Dockerを立ち上げるポート番号を記載します。今回は5001番ポートで立ち上げます。
それではDockerを起動
$ docker-compose up
起動が完了したら、localhost:5001にアクセスします。
以下のような画面が表示されたら問題なく起動しています。
ここまでで、簡単にPython、Flaskの環境ができることが分かります。
この状態でapi.pyを以下のように変更し、保存します。
class Product(Resource):
def get(self):
return{
'products': [
'Ice cream',
'Chocolate',
'Fruit',
'Eggs'
]
}
再読み込みを行うと、表示内容も更新されます。コンテナを再起動しなくてもマウントしてくれます。
ここまできたらコンソール上で「control+C」を押して、dockerを一旦停止します。
website
次はdocker_tutorial配下にwebsiteというディレクトリを作成します。こちらにはphpのファイルを作成します。
http://product-serviceの結果をループして表示する処理です。
ここでいうproduct-serviceはdocker-composeに記載したサービス名が該当します。
<html>
<head>
<title>My Shop</title>
</head>
<body>
<h1>Welcome to my shop</h1>
<ul>
<?php
$json = file_get_contents('http://product-service');
$obj = json_decode($json);
$products = $obj->products;
foreach($products as $product) {
echo "<li>$product</li>";
}
?>
</ul>
</body>
次にdocker-compose.ymlを以下のように変更します。
version: '3'
services:
product-service:
build: ./product
volumes:
- ./product:/usr/src/app
ports:
- 5001:80
website:
image: php:apache
volumes:
- ./website:/var/www/html
ports:
- 5000:80
depends_on:
- product-service
website
servicesにwebsiteというサービスを追加します。
image
imageを記載することで、Docker Hub上に用意されている既存のイメージを使用することができます。buildとimageは同時に指定することはできません。
depends_on
サービス同士の依存関係を記載します。今回の場合、websiteが実行されるより前にproduct-serviceが実行されるようになります。docker-compose.ymlにproduct-serviceがない場合はエラーになります。
再度Dockerを起動します。
$ docker-compose up
起動が完了したらlocalhost:5000にアクセスします。
以下のような画面が表示されていれば成功です。
さいごに
Dockerを使用することで、簡単にPython+phpの環境を作ることができました。私もDocker初心者のためこれからも引き続き学習していきたいと思います。
おまけ
-dをつけることでバックグラウンドでコンテナを立ち上げることができます。
$ docker-compose up -d
Starting docker_tutorial_product-service_1 ... done
Starting docker_tutorial_website_1 ... done
psコマンドで起動中のコンテナの一覧が確認できます。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
24de043f94d9 php:apache "docker-php-entrypoi…" 10 minutes ago Up About a minute 0.0.0.0:5000->80/tcp docker_tutorial_website_1
da62924c1154 docker_tutorial_product-service "python api.py" 32 minutes ago Up About a minute 0.0.0.0:5001->80/tcp docker_tutorial_product-service_1
stopでコンテナを停止することができます。
$ docker-compose stop
Stopping docker_tutorial_website_1 ... done
Stopping docker_tutorial_product-service_1 ... done
$ docker ps
ONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES