Docker Compose : Flask, Redis, DynamoDB and Python
Docker Compose を使って環境構築を行う。
今回使うのは、Flask, Redis, DynamoDB, Python である。
Python で作成したコードを Flask で動かし、Redis をキャッシュとして利用し、DynamoDB にデータを永続化する。
導入環境
- CentOS 7.7
- Docker 19.03.7
- Docker Compose 1.25.4
事前準備
# mkdir docker-app
Flask のディレクトリを作成する。
# cd docker-app/ # mkdir flask
Flask
Dockerfile
Dockerfile を作成する。
# touch flask/Dockerfile
Dockerfile に下記を追加する。
FROM python:3.8-alpine WORKDIR /code ENV FLASK_APP app.py ENV FLASK_RUN_HOST 0.0.0.0 RUN apk add --no-cache gcc musl-dev linux-headers COPY ./requirements.txt ./requirements.txt RUN pip install -r requirements.txt COPY ./app.py ./app.py CMD ["flask", "run"]
requirements.txt
requirements.txt を作成する。
# touch flask/requirements.txt
requirements.txt に下記を追加する。
flask redis boto3
app.py
app.py を作成する。
# touch flask/app.py
app.py に下記を追加する。
import time import datetime import redis import boto3 from flask import Flask app = Flask(__name__) cache = redis.Redis(host='redis', port=6379) cache_ttl = 5 db = boto3.resource( 'dynamodb', endpoint_url='http://dynamodb:8000', region_name='localhost', aws_access_key_id='fakeId', aws_secret_access_key='fakeKey') def get_hit_count_redis(): retries = 5 while True: try: hits:str = cache.get('hits') if not hits: hits = get_hit_count_dynamodb() new_value = int(hits) + 1 # Update Redis pipe = cache.pipeline() pipe.set('hits', new_value) pipe.expire('hits', cache_ttl) pipe.execute() # Update DynamoDB table = db.Table('hits') response = table.put_item( Item={ 'hits_id': '1', 'value': {'S': new_value} } ) return cache.get('hits') except redis.exceptions.ConnectionError as exc: if retries == 0: raise exc retries -= 1 time.sleep(0.5) def get_hit_count_dynamodb(): ret_val = '0' retries = 5 while True: table = db.Table('hits') try: response = table.get_item( Key={ 'hits_id':'1' } ) if ('Item' in response): ret_val = response['Item']['value']['S'] return ret_val except botocore.exceptions.ClientError as ex: if retries == 0: raise ex retries -= 1 time.sleep(0.5) @app.route('/') def hello(): count = get_hit_count_redis() return 'Hello World! I have been seen {0} times. Access time is {1}.'.format(int(count), datetime.datetime.now())
docker-compose
docker-compose.yml を作成する。
# touch docker-compose.yml
docker-compose.yml
docker-compose.yml に下記を追記する。
version: '3' services: flask: build: ./flask container_name: flask links: - "redis" - "dynamodb" ports: - "5000:5000" redis: image: redis:5.0-alpine container_name: redis expose: - 6379 dynamodb: image: amazon/dynamodb-local:1.12.0 command: -jar DynamoDBLocal.jar -inMemory -sharedDb container_name: dynamodb expose: - 8000 ports: - "8000:8000"
コンテナ起動
コンテナを起動する。
# docker-compose up -d
AWS-CLI のインストール
DynamoDB を操作するために、AWS-CLI をインストールする。
# curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" # unzip awscliv2.zip # ./aws/install
インストールを確認する。
# aws --version
初期設定を行う。
# aws configure
DynamoDB の設定
テーブルを作成する。
# aws dynamodb create-table \ --table-name hits \ --attribute-definitions AttributeName=hits_id,AttributeType=S \ --key-schema AttributeName=hits_id,KeyType=HASH \ --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1 \ --endpoint-url http://localhost:8000
テーブルが作成されたことを確認する。
# aws dynamodb list-tables --endpoint-url http://localhost:8000
動作確認
ブラウザでhttp://localhost:5000/
へアクセスし、アプリケーションが稼働しているかを確認する。
5秒以上経ったあとに、http://localhost:5000/
へ再アクセスする。アクセスしたときに、数値がカウントアップされていることを確認する。
終わりに
Flask, Redis, DynamoDB, Python を連携して、簡単なアプリケーションを作成することができた。
注意する点としては、DynamoDB をインメモリデータベースとして稼働しているため、コンテナを削除するとデータも消える(インメモリデータベースとして起動しなければ永続化もできる)。
また、このプログラムのうち DynamoDB を呼び出す部分を削除すれば、Redis のみで5秒ごとに値がリセットされるアプリケーションにもできる。
参考サイト
https://github.com/aws-samples/aws-sam-java-rest
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2-linux.html
https://symfoware.blog.fc2.com/blog-entry-2208.html
https://michimani.net/post/aws-put-get-item-dynamodb-by-lambda-python/