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/