LoginSignup
2
0
お題は不問!Qiita Engineer Festa 2024で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

③1日10分で理解するコンテナ技術入門 - シンプルなWebアプリのDocker化 -

Last updated at Posted at 2024-06-12

前回の記事では、Dockerfileの基本的な書き方を紹介しました。
今回は、シンプルなWebアプリをコンテナで起動してみて、Dockerの使われ方をイメージしていただければと思います。

今回使用するWebアプリ

今回使用するWebアプリは、下のようなシンプルな記事投稿サイトです。
image.png
ホームページに記事一覧が表示され、記事のタイトルをクリックすると、以下の様に記事が表示されます。
image.png

実装にはFlaskとmysqlを使っています。コードはここにあります。

Flask側のコンテナ化

Flask側のDockerfileは以下のようになっています。

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

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

# 必要なファイルをコンテナにコピー
COPY requirements.txt requirements.txt
COPY app.py app.py
COPY custom_markdown.py custom_markdown.py
COPY templates/ templates/
COPY static/ static/
COPY uploads/ uploads/

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

# アップロードディレクトリのパーミッションを設定
RUN chmod -R 777 /app/uploads

# コンテナの起動時に実行されるコマンド
CMD ["python", "app.py"]

前回の記事で紹介した基本的なコマンドのみ使用しています。

MySQLのコンテナ化

MySQLは公式で配布されているイメージをそのまま使用します。そのため、Dockerfileは不要です。

それぞれのコンテナをビルドして起動

コンテナとして動かすには、以下の手順を踏む必要があります。

  1. コンテナ同士が通信できるように、ネットワークを作成
  2. MySQLのコンテナを作成
  3. Flaskのコンテナを作成

docker networkの作成

FlaskのコンテナとMySQLのコンテナは通信する必要があるので、そのためのネットワークを作成し、それぞれのコンテナをそのネットワークに配置します。
まずは、ネットワークをdocker networkコマンドで作成します。

docker network create flask-net

このコマンドでネットワークが作成されました。コンテナをdocker networkに配置するのは、docker run時に行うため、この後説明します。

MySQLのコンテナを起動

MySQLありきでFlask側は実装されているので、MySQLのコンテナから起動します。MySQLのコンテナは、以下のコマンドで起動します。

docker run --name mysql -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=flask_app --network flask-net -d mysql:8.0

MySQLのコンテナは、データベースのパスワードなどを環境変数に設定して使用するので、docker run時に指定しています。また、--network flask-netをオプションとして加えて、先ほど作成したdocker networkに配置します。

Flaskのコンテナを起動

以下のコマンドでDockerfileからFlaskアプリのイメージをビルドし、実行します。

docker build -t simple-knowledge-sharing-platform .
docker run -d -p 8080:5000 --network flask-net -v $(pwd)/uploads:/app/uploads simple-knowledge-sharing-platform

flaskアプリはポート5000で待ち受けているので、-p 8080:5000オプションを使って、ホストの8080にポートフォワーディングします。また、MySQLのコンテナと同様に、--network flask-netオプションを使って作成したdocker networkにコンテナを配置します。

今回のWebアプリは画像のアップロードにも対応しています。画像の保存はとりあえずFlaskのコンテナ側に保存するので、-v $(pwd)/uploads:/app/uploadsオプションを用いて、コンテナの/app/uploadsをホストの$(pwd)/uploadsにマウントしています。この設定によって、flaskアプリ側では/app/uploadsに画像を保存しますが、その実態はホストの$(pwd)/uploadsに保存されています。

コンテナ同士の通信について

同じdocker networkに所属しているコンテナ同士は、コンテナ名をホスト名として通信することができます。そのため、Flask側では以下のようにDBのホスト名をmysqlとして指定していますが、これで通信ができるのはMySQLのコンテナを作成する際にコンテナ名をmysqlとしているためです。

app.pyの一部
# データベースの初期化
def init_db():
    conn = mysql.connector.connect(
        host='mysql',
        port=3306,
        user='root',
        password='password',
        database='flask_app'
    )
    cursor = conn.cursor()
    cursor.execute('CREATE TABLE IF NOT EXISTS articles (id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(255), content TEXT)')
    conn.commit()
    cursor.close()
    conn.close()

また、ポート番号はコンテナのポート番号を指定して通信します。そのため、MySQLのコンテナを作成する際にポートフォワーディングをする必要はなく、MySQLのコンテナでデフォルトで待ち受けている3306番を使用して通信が可能です。

まとめ

以上の手順を踏むことで、簡単にウェブアプリをデプロイすることができます。ただし、コンテナの作成順序を考慮して起動しないといけないなど、多少手間になる部分が見えたと思います。こういった部分を解決するために、docker composeというものがあるのですが、それはまた後日紹介します。

現状では、ローカルにウェブアプリが立ち上がっただけの状態です。インターネット上に公開するためには、リモートのレポジトリにコンテナイメージをプッシュして、インターネット上にウェブアプリを公開する必要があります。次回の記事で、その手順を説明したいと思います。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0