記事を書いた背景
今月で現職のSIerを退職することになり、心機一転インフラまわりの技術者になろうと思ってます。
近年のパブリッククラウドを駆使したインフラ、CI/CD環境構築にあたって、様々な言語でアプリをビルドしたり、疎通確認用のアプリを作ったりすることは、私のようなレガシーエンジニアであっても避けては通れなくなってきていると感じるこの頃です。
いろいろな言語のビルドとちょっとしたWebアプリぐらいを作れるように頑張ろうと思って、今回はPython、PipenvでFlaskのアプリ(ほんとに触り程度)を作ってDockerコンテナ化するまでの手順を記載しました。
Pipenvのインストール
近年のPythonの環境構築はPipenvというツールを使って構築するっぽいので使ってみました。
JavaScriptのnpmみたいで使いやすいです。
pip install pipenv
アプリプロジェクトの作成
mkdir flask-app
cd flask-app
今回はPython3.8を使うことにします。
pipenv --python 3.8
pipenv install flask
pipenv install --dev autopep8
これから作成するファイルを空で作成しておきます。
mkdir src
touch src/main.py
touch Dockerfile
touch .dockerignore
Pipfile
のscripts
セクションに追記します。
[scripts]
start = "python src/main.py"
Flaskアプリケーションのコーディング
Python素人が書いたコードになってしまいますが、以下のような感じで作成しました。
import sqlite3
import flask
app = flask.Flask(__name__)
def get_db():
db = getattr(flask.g, '_database', None)
if db is None:
db = flask.g._database = sqlite3.connect('mydb.sqlite')
return db
@app.teardown_appcontext
def close_conn(exception):
db = getattr(flask.g, '_database', None)
if db is not None:
db.close()
@app.route('/todos/<id>', methods=['GET'])
@app.route('/todos', methods=['GET', 'POST'])
def todos(id=None):
db = get_db()
# リクエストをもらったらテーブル作成
curs = db.cursor()
curs.execute(
'create table if not exists todos('
'id integer primary key autoincrement, title string)'
)
id = flask.request.values.get('id', id)
if flask.request.method == 'GET' and id is not None:
curs.execute('select * from todos where id = {}'.format(id))
response = curs.fetchone()
if response is not None:
id, title = response
return flask.jsonify(todo={"id": id, "title": title}), 200
return flask.jsonify(message='resource not found'), 400
if flask.request.method == 'GET':
curs.execute('select * from todos')
response = curs.fetchall()
todos = []
for todo in response:
id, title = todo
todos.append({"id": id, "title": title})
return flask.jsonify(todos=todos), 200
if flask.request.method == 'POST':
title = flask.request.json['title']
curs.execute('insert into todos(title) values("{}")'.format(title))
db.commit()
return flask.jsonify(message='created new toto')
def main():
app.debug = True
app.run(host='0.0.0.0', port=5000)
if __name__ == "__main__":
main()
ここまででローカル環境で動作するようになるはずです。
pipenv run start
* Serving Flask app "main" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 208-926-045
curlコマンド叩いて確認します。
curl -XPOST -H 'Content-Type: application/json' localhost:5000/todos -d '{"title": "new task1"}'
curl -XPOST -H 'Content-Type: application/json' localhost:5000/todos -d '{"title": "new task2"}'
curl localhost:5000/todos
curl localhost:5000/todos/1
Dockerfileの作成とビルド
Pipenvと組み合わせた場合のプラクティスがわかってないのですが、シンプルイズベストで作ってみました。
FROM python:3.8
ENV LC_ALL=C.UTF-8 \
LANG=C.UTF-8
WORKDIR /app
COPY . .
RUN pip install pipenv
RUN pipenv install
CMD ["pipenv", "run", "start"]
EXPOSE 5000
.dockerignore
ファイルも作成しておきます。
*.sqlite
.git
ビルドします。
docker image build -t flaskapp:latest .
コンテナを起動します(ローカル側のポートを15000番として起動しています)。
docker container run -it -p 15000:5000 --rm flaskapp:latest
* Serving Flask app "main" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 954-331-726
curlコマンド叩いて確認できればOKです。
curl -XPOST -H 'Content-Type: application/json' localhost:15000/todos -d '{"title": "new task1"}'
curl -XPOST -H 'Content-Type: application/json' localhost:15000/todos -d '{"title": "new task2"}'
curl localhost:15000/todos
curl localhost:15000/todos/1
おわりに
nodejsでのnpm、yarnに慣れきった生活を送っていたこともあり、pythonの環境構築を避けていたのですが、Pipenvが便利だなと感じました。Pipenv知らなかったので今まで損していた気分になりました。
とりあえず、インフラエンジニア目線(主観)ではここまでで出来たので満足です。
アプリエンジニアの手を煩わせずに環境をご提供できるように今後努力いたします。
しかし、5年ぐらい前までは覚えることそんなになかったのに、昨今のIT技術を取り巻く環境変化はすごいスピードです。置いていかれてるのですが、すこしでも追いつけるように必死こいてます。