1. Webアプリケーションコンテナの作成¶
目的¶
Webアプリケーションコンテナを構築します。
対象¶
- S3サービス
事前作業¶
Docker Composeのインストール¶
コマンド:
which docker-compose
結果(例):
/usr/bin/which: no docker-compose in (/home/ec2-user/.nvm/versions/node/v6.14.4/bin:/usr/local/rvm/gems/ruby-2.4.1/bin:/usr/local/rvm/gems/ruby-2.4.1@global/bin:/usr/local/rvm/rubies/ruby-2.4.1/bin:/usr/local/bin:/bin:/usr/bin:/home/ec2-user/.local/bin:/home/ec2-user/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/aws/bin:/usr/local/rvm/bin:/home/ec2-user/.local/bin:/home/ec2-user/bin:/home/ec2-user/.local/bin:/home/ec2-user/bin)
変数の設定:
DOCKER_COMPOSE_VERSION='1.22.0'
コマンド:
sudo curl -L \ "https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" \ -o /usr/local/bin/docker-compose
結果(例):
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 617 0 617 0 0 2419 0 --:--:-- --:--:-- --:--:-- 2429 100 11.2M 100 11.2M 0 0 1512k 0 0:00:07 0:00:07 --:--:-- 2293k
コマンド:
sudo chmod +x /usr/local/bin/docker-compose
コマンド:
which docker-compose
結果(例):
/usr/local/bin/docker-compose
パラメータ¶
パラメータの指定¶
パラメータの確認¶
変数の確認:
cat << ECHO # 0.1. DIR_DEVELOP:"/home/ec2-user/environment" DIR_DEVELOP="${DIR_DEVELOP}" # 0.2. APP_NAME:"handson-cli-container-flask" APP_NAME="${APP_NAME}" ECHO
実施¶
変数の設定:
DIR_APP="${HOME}/environment/${APP_NAME}" \ && echo ${DIR_APP}
結果(例):
/home/ec2-user/environment/handson-cli-container-flask
コマンド:
mkdir -p ${DIR_APP} \ && cd ${DIR_APP}
アプリケーションコンテナの作成¶
https://qiita.com/paperlefthand/items/82ab6df4a348f6070a55 のアプリケーションを作成してみます。
コマンド:
mkdir -p app
Flaskアプリケーションの作成
- コマンド:
cat << EOF > ${DIR_APP}/app/reply.py from flask import Flask, jsonify, request import json app = Flask(__name__) @app.route("/", methods=['GET']) def hello(): return "Hello World!" @app.route('/reply', methods=['POST']) def reply(): data = json.loads(request.data) answer = "Yes, it is %s!\n" % data["keyword"] result = { "Content-Type": "application/json", "Answer":{"Text": answer} } # return answer return jsonify(result) if __name__ == "__main__": app.run(host='0.0.0.0',port=5000,debug=True) EOF cat ${DIR_APP}/app/reply.py
結果(例):
from flask import Flask, jsonify, request import json app = Flask(__name__) @app.route("/", methods=['GET']) def hello(): return "Hello World!" @app.route('/reply', methods=['POST']) def reply(): data = json.loads(request.data) answer = "Yes, it is %s!\n" % data["keyword"] result = { "Content-Type": "application/json", "Answer":{"Text": answer} } # return answer return jsonify(result) if __name__ == "__main__": app.run(host='0.0.0.0',port=5000,debug=True)
アプリケーションコンテナの作成
コマンド:
cat << EOF > ${DIR_APP}/app/Dockerfile FROM python:3.6 ARG project_dir=/app/ # ADD requirements.txt \$project_dir ADD reply.py \$project_dir WORKDIR \$project_dir RUN pip install flask # RUN pip install -r requirements.txt CMD ["python", "reply.py"] EOF cat ${DIR_APP}/app/Dockerfile
結果(例):
FROM python:3.6 ARG project_dir=/app/ # ADD requirements.txt $project_dir ADD reply.py $project_dir WORKDIR $project_dir RUN pip install flask # RUN pip install -r requirements.txt CMD ["python", "reply.py"]
Dockerイメージの作成
コマンド:
cd ./app/
変数の設定:
CONTAINER_IMAGE_NAME="handson-cli-app"
変数の設定:
CONTAINER_IMAGE_TAG="0.0.1"
コマンド:
docker build -t ${CONTAINER_IMAGE_NAME}:${CONTAINER_IMAGE_TAG} .
結果(例):
Successfully built 190143166695 Successfully tagged handson-cli-app:0.0.1
アプリケーションコンテナの起動
変数の設定:
CONTAINER_RUN_NAME="handson-cli-app"
コマンド:
docker run \ -p 5000:5000 \ --name ${CONTAINER_RUN_NAME} \ ${CONTAINER_IMAGE_NAME}:${CONTAINER_IMAGE_TAG}
アプリケーションの動作確認
別ターミナルでPOSTしてみます。
コマンド:
curl http://localhost:5000/reply \ -X POST \ -H "Content-Type: application/json" \ -d '{"keyword": "Keffia"}'
結果(例):
{ "Answer": { "Text": "Yes, it is Keffia!" }, "Content-Type": "application/json" }
アプリケーションのログ確認
アプリケーションを起動したターミナルでアクセスログを確認します。
ログ(例):
127.0.0.1 - - [16/Sep/2018 05:11:15] "POST /reply HTTP/1.1" 200 -
アプリケーションコンテナの停止
ログを確認したら、CtrlキーとCキーを同時に押して、アプリケーションコンテナを停止します。
コマンド:
docker rm $(docker ps -a --filter name=${CONTAINER_RUN_NAME} -q )
結果(例):
xxxxxxxxxxxx
コマンド:
cd ${DIR_APP}
Webサーバコンテナの作成¶
コマンド:
mkdir -p nginx
nginx設定ファイルの作成
- コマンド:
cat << EOF > ${DIR_APP}/nginx/nginx.conf events { worker_connections 768; } http { # Nginx will handle gzip compression of responses from the app server gzip on; gzip_proxied any; gzip_types text/plain application/json; gzip_min_length 1000; server { listen 80; # Nginx will reject anything not matching / location / { # Reject requests with unsupported HTTP method if (\$request_method !~ ^(GET|POST|HEAD|OPTIONS|PUT|DELETE)\$) { return 405; } # Only requests matching the whitelist expectations will # get sent to the application server proxy_pass http://app:5000; proxy_http_version 1.1; proxy_set_header Upgrade \$http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host \$host; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; proxy_cache_bypass \$http_upgrade; } } } EOF cat ${DIR_APP}/nginx/nginx.conf
結果(例):
events { worker_connections 768; } http { # Nginx will handle gzip compression of responses from the app server gzip on; gzip_proxied any; gzip_types text/plain application/json; gzip_min_length 1000; server { listen 80; # Nginx will reject anything not matching / location / { # Reject requests with unsupported HTTP method if ($request_method !~ ^(GET|POST|HEAD|OPTIONS|PUT|DELETE)$) { return 405; } # Only requests matching the whitelist expectations will # get sent to the application server proxy_pass http://app:5000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_cache_bypass $http_upgrade; } } }
nginxコンテナの作成
コマンド:
cat << EOF > ${DIR_APP}/nginx/Dockerfile FROM nginx COPY nginx.conf /etc/nginx/nginx.conf EOF cat ${DIR_APP}/nginx/Dockerfile
結果(例):
FROM nginx COPY nginx.conf /etc/nginx/nginx.conf
Dockerイメージの作成
変数の設定:
CONTAINER_IMAGE_NAME='handson-cli-reverse-proxy'
変数の設定:
CONTAINER_IMAGE_TAG='0.0.1'
コマンド:
docker build -t ${CONTAINER_IMAGE_NAME}:${CONTAINER_IMAGE_TAG} ./nginx/
結果(例):
(略) Successfully built 35d1eb8be276 Successfully tagged handson-cli-reverse-proxy0.0.1
compose設定ファイルの作成¶
docker-compose.yml
コマンド:
cat << EOF > ${DIR_APP}/docker-compose.yml version: '2' services: nginx: build: context: ./nginx ports: - 8080:80 links: - app app: build: context: ./app ports: - 5000:5000 EOF cat ${DIR_APP}/docker-compose.yml
結果(例):
version: '2' services: nginx: build: context: ./nginx ports: - 80:80 links: - app app: build: context: ./app
docker-composeの起動
コマンド:
docker-compose build
結果(例):
(略) Successfully built xxxxxxxxxxxx Successfully tagged simple_nginx:latest
コマンド:
docker-compose up
結果(例):
Creating network "simple_default" with the default driver Creating simple_app_1 ... done Creating simple_nginx_1 ... done Attaching to simple_app_1, simple_nginx_1 app_1 | * Serving Flask app "reply" (lazy loading) app_1 | * Environment: production app_1 | WARNING: Do not use the development server in a production environment. app_1 | Use a production WSGI server instead. app_1 | * Debug mode: on app_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) app_1 | * Restarting with stat app_1 | * Debugger is active! app_1 | * Debugger PIN: 138-652-460
アプリケーションの動作確認
別ターミナルでPOSTしてみます。
コマンド:
curl http://localhost:8080/reply \ -X POST \ -H "Content-Type: application/json" \ -d '{"keyword": "Keffia"}'
結果(例):
{ "Answer": { "Text": "Yes, it is Keffia!" }, "Content-Type": "application/json" }
アプリケーションのログ確認
アプリケーションを起動したターミナルでアクセスログを確認します。
ログ(例):
nginx_1 | 172.20.0.1 - - [18/Sep/2018:21:47:03 +0000] "POST /reply HTTP/1.1" 200 96 "-" "curl/7.59.0"
アプリケーションコンテナの停止
ログを確認したら、CtrlキーとCキーを同時に押して、アプリケーションコンテナを停止します。
コマンド:
docker rm $(docker ps -a --filter name=handson-cli-container-flask -q )
結果(例):
xxxxxxxxxxxx xxxxxxxxxxxx