2022年10月8日土曜日

fly.io に Python Flask アプリをデプロイするためのローカルの作業及び開発環境を作成

はじめに

PaaS である fly.io で Python Flaskアプリ (DB は Postgres を利用) をデプロイするためのローカルの作業及び開発のための環境を Docker コンテナで構築してみたので以下にまとめています。

なお本記事はローカル環境の構築までについて記載しており、その先の fly.io の操作や fly.io へのアプリのデプロイについては別途記事にする予定です。

Docker コンテナ準備

ベースとなる ubuntu:22.04 docker イメージをローカルに取り込み

$ docker image pull ubuntu:22.04

コンテナを作成して起動

$ docker run \
  --publish 5001:5000 \
  --name fly-work \
  --interactive \
  --tty \
  ubuntu:22.04
  • コンテナ内で実行する開発環境の Python Flask アプリは 5000番ポートをリッスンするので --publish 5001:5000 によりホスト側の 5001番ポートに紐づけます。
  • 後述する通り、ホストのブラウザーからコンテナ内の Python Flask アプリにアクセスする場合は URL として http://localhost:5001/ を指定することになります。

なお次回以降の PC 起動時等、停止しているコンテナを開始する場合は上述の docker run ではなく、以下の通り docker start となります。

$ docker start --interactive fly-work

コンテナ内のシェルが起動するので、まずは作業用の worker ユーザーを作成しパスワードも worker に設定

# useradd \
  --create-home \
  --groups sudo \
  --shell /bin/bash \
  worker

# echo 'worker:worker' | chpasswd

worker ユーザーで個別にインストールが必要なツールをインストール

# apt update && apt -y install sudo net-tools tree

worker ユーザーに su

# su - worker

以降はこのコンテナ内の worker ユーザーでの作業となります。

Ubuntu の基本的な設定

パッケージを最新化

$ sudo apt update && sudo apt -y upgrade

よく使うコマンドを使えるようにするための基本的なパッケージをインストール

$ sudo apt install -y \
  ubuntu-minimal \
  ubuntu-standard \
  ubuntu-server
  • geographic area を聞いてくるので Asia - Tokyo を指定
  • Encoding を聞いてくるので UTF-8 を指定
  • character set を聞いてくるので Guess optimal character set を指定

以降のパッケージインストールで Failed to retrieve available kernel versions. 等のメッセージが出ないようにするためのおまじない

$ sudo apt purge -y needrestart

不要なパッケージを削除

$ sudo apt autoremove -y

日本語環境の設定

$ sudo apt install -y \
  language-pack-ja-base \
  language-pack-ja \
  locales

$ sudo locale-gen ja_JP.UTF-8
$ echo "export LANG=ja_JP.UTF-8" >> ~/.bashrc
$ source ~/.bashrc

ロケールの確認

$ locale
LANG=ja_JP.UTF-8
LANGUAGE=
LC_CTYPE="ja_JP.UTF-8"
LC_NUMERIC="ja_JP.UTF-8"
LC_TIME="ja_JP.UTF-8"
LC_COLLATE="ja_JP.UTF-8"
LC_MONETARY="ja_JP.UTF-8"
LC_MESSAGES="ja_JP.UTF-8"
LC_PAPER="ja_JP.UTF-8"
LC_NAME="ja_JP.UTF-8"
LC_ADDRESS="ja_JP.UTF-8"
LC_TELEPHONE="ja_JP.UTF-8"
LC_MEASUREMENT="ja_JP.UTF-8"
LC_IDENTIFICATION="ja_JP.UTF-8"
LC_ALL=

Postgres DB をインストール

Python Flask アプリをローカルの開発環境で実行する場合にアプリがアクセスする Postgres をインストールします。

Postgres DB をインストール

$ sudo apt install -y postgresql

Postgres DB を起動

$ sudo service postgresql start

$ sudo service postgresql status
14/main (port 5432): online

postgres ユーザーのパスワードを変更

$ sudo su - postgres --command "
    psql --command \"
      alter
        user postgres
        with encrypted password 'pgpass';
    \"
  "

なお、直接 psql コマンドで接続する場合は以下のいずれでもいけました。

  • $ sudo su - postgres --command "psql --dbname postgres"
  • $ psql postgres://postgres:pgpass@localhost/postgres

Python Flask のサンプルアプリを起動

Ubuntu パッケージをインストール

$ sudo apt install -y python3-pip

アプリ用のディレクトリを作成して移動

$ mkdir ~/work
$ cd ~/work/

requirements.txt を配置

$ cat <<EOF > requirements.txt
Flask
Flask-SQLAlchemy
psycopg2-binary
EOF

Python パッケージをインストール

$ sudo pip install -r requirements.txt

スクリプトを配置

$ cat <<EOF > testapp.py
#!/usr/bin/env python3

import os
import re
from flask import (
  Flask,
  Response
)
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = re.sub(
  '^postgres://',
  'postgresql://',
  os.environ['DATABASE_URL']
)

app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

class TestRecord(db.Model):
  test_col = db.Column(db.Text, primary_key=True)

@app.route('/')
def root():
  query = db.session.query(TestRecord)
  record = query.one()

  return Response(record.test_col)
EOF

アプリがアクセスする Postgres のデータベースを作成

$ sudo su - postgres --command "
    psql --command \"
      create database testdb;
    \"
  "

テーブルを作成しデータをインサート

$ DATABASE_URL=postgres://postgres:pgpass@localhost/testdb python3

>>> from testapp import db, TestRecord

>>> db.create_all()

>>> test_record = TestRecord()
>>> test_record.test_col = 'hello world'

>>> db.session.add(test_record)
>>> db.session.commit()

>>> exit()

アプリを起動

$ DATABASE_URL=postgres://postgres:pgpass@localhost/testdb FLASK_APP=testapp flask run --host=0.0.0.0

ブラウザで http://localhost:5001/ にアクセス

参考

0 件のコメント:

コメントを投稿