Python初学者向け：FlaskとDockerでWebアプリを簡単に構築する方法

## はじめに
今回は、PythonのWebフレームワークであるFlaskをDockerコンテナで実行する方法について解説します。

Dockerを使うことで、ローカル環境やサーバー環境に依存せず、簡単にFlaskアプリケーションを構築・実行できるようになります。

この記事では、DockerとFlaskの基礎を整理した後、具体的な手順を紹介していきます。

## 知識整理
### Dockerとは
Dockerは、アプリケーションをコンテナという単位でパッケージ化して実行するためのプラットフォームです。

コンテナを使うことで、開発環境や依存関係を含めたアプリケーションを一つの単位にまとめることができ、どの環境でも同じように動作させることができます。

これにより、ローカル環境で動いたアプリケーションが本番環境でもそのまま動作することを保証できます。

https://knowledge.sakura.ad.jp/13265/

### Dockerfileとは
Dockerfileは、Dockerイメージを作成するための設定ファイルです。Dockerfileには、ベースイメージの指定やアプリケーションの依存関係、コンテナ起動時のコマンドなどを記述します。

これにより、簡単にアプリケーションの動作環境を再現できます。

https://aiacademy.jp/media/?p=1386

### Flaskとは
Flaskは、Pythonで作成された軽量なWebフレームワークです。シンプルで学習コストが低く、柔軟性が高いため、初心者からプロフェッショナルまで幅広く利用されています。

FlaskはAPIや小規模なWebアプリケーションの開発に適しており、テンプレートエンジンを使った動的なWebページの作成も容易に行えます。

https://aiacademy.jp/media/?p=57

## プロジェクト構成
今回作成するFlaskアプリケーションのディレクトリ構成は以下のようになります。

```bash
/flask-app/
├── Dockerfile         # Dockerイメージを構築する設定ファイル
├── requirements.txt   # FlaskなどのPythonライブラリの依存関係を記述
├── app.py             # Flaskアプリケーションのメインファイル
└── /templates/        # HTMLテンプレートを格納するディレクトリ
    └── index.html
```

:::note warn
この記事では、Docker環境がローカル端末で動かせることを前提として、Flaskアプリケーションのコンテナ化について解説します。
:::


## 各ファイルの作成手順
### 1. Dockerfileの作成
以下の内容でDockerfileを作成します。このファイルにより、Pythonベースのイメージを使用してFlaskアプリケーションを実行するコンテナを構築します。

```dockerfile
# ベースイメージとして公式のPythonイメージを使用
FROM python:3.9-slim

# 作業ディレクトリを設定
WORKDIR /app

# 必要なパッケージをインストール
RUN apt-get update && apt-get install -y \
    build-essential \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# ローカルのrequirements.txtをコンテナにコピー
COPY requirements.txt .

# Pythonの依存関係をインストール
RUN pip install --no-cache-dir -r requirements.txt

# アプリケーションのソースコードをコンテナにコピー
COPY . .

# 環境変数の設定（Flaskアプリを起動するため）
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0

# コンテナのポート5000を公開
EXPOSE 5000

# Flaskアプリケーションを起動
CMD ["flask", "run"]
```

### 2. requirements.txtの作成
Flaskアプリケーションの依存関係を管理するrequirements.txtを作成します。Flaskをインストールするため、以下の内容を記載します。

```requirements.txt
Flask==2.3.2
```

### 3. app.pyの作成
Flaskアプリケーションのメインファイルapp.pyを作成し、以下の内容を記述します。このファイルでは、ルートURLにアクセスしたときにindex.htmlを表示します。

```app.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def home():
    return render_template('index.html')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
```

### 4. templates/index.htmlの作成
HTMLテンプレートを保存するtemplatesディレクトリを作成し、その中にindex.htmlを配置します。以下はそのサンプルです。

```templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Flask App</title>
</head>
<body>
    <h1>仕事終わりに頑張って偉い！自分！！👏</h1>
    <p>明日も朝早いから今日はゆっくり休んでね〜</p>
</body>
</html>
```

## Dockerのビルドと実行
プロジェクトの準備ができたら、次にDockerイメージをビルドして、コンテナを起動します。以下のコマンドを実行してください。

```bash
# Dockerイメージをビルド
docker build -t flask-app .
```

ビルド中の状況は、ターミナルやDocker Desktopアプリから確認できます。

![スクリーンショット 2024-10-16 21.16.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/6a2498ec-3778-d86b-cb94-a7d44d189f57.png)

次に、以下のコマンドでコンテナを起動します。

```bash
# コンテナを起動
docker run -p 5001:5000 flask-app
```

私の環境では、Flaskを使った個人開発を行っており、すでに5000番ポートが使用中です。そのため、コンテナ内部ではポート5000でFlaskを動作させつつ、ホスト側からはポート5001でアクセスできるように設定しました。

![スクリーンショット 2024-10-16 21.23.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/f04f27a1-cca3-0a7a-5013-43813fc7107d.png)


docker run コマンドでポート5001を公開しているため、ブラウザで「http://localhost:5001」 にアクセスすると、Flaskアプリケーションが表示されます。

![スクリーンショット 2024-10-16 21.25.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/9dcf9e95-5a15-39e5-816d-517590a0043e.png)


Flaskアプリケーションのログには、以下のようにページをリロードする際にGET（ページの取得）リクエストが確認でき、正常に動作していることがわかります。

```bash
192.168.65.1 - - [16/Oct/2024 12:23:42] "GET / HTTP/1.1" 200 -
```


## まとめ
この記事では、FlaskをDockerコンテナで実行する方法について解説しました。Dockerを使うことで、アプリケーションの動作環境を一つのコンテナとして管理でき、環境依存の問題を解消しながら、開発とデプロイの効率を大幅に向上させることができます。

Flaskの軽量さと柔軟性を活かして、小規模なWebアプリケーションやAPIの開発を行いたい場合、Dockerとの組み合わせは非常に効果的です。

ぜひ今回の手順を参考に、Dockerを使ったアプリケーション開発の参考にしてみてください！

## 参考文献

https://qiita.com/RyutoYoda/items/c260d3a1067ff853b18e