既存のPythonコンソールアプリをDockerに移行する

既存のPythonコンソールアプリをDockerに移行する

Clock Icon2024.08.30

はじめに

Pythonで作成したコンソールアプリをPythonがインストールされていないPCでも引き続き開発できるようにするために、Docker環境に移行したいと思います。

環境

  • アプリを作成した環境
    • Windows 10
    • Python 3.12.1
  • PythonのないPCの環境
    • Windows 11
    • Dockerインストール済み

移行するアプリ

今回はシンプルなPythonコンソールアプリを移行します。内容はtiktokenというライブラリを使ってOpenAIのトークン数を計算するというものです。

import tiktoken

prompt = """You are an American English conversation instructor whose native language is English.
Please provide feedback on English diaries written by students.
"""

def num_tokens_from_string(string: str, encoding_name: str) -> int:
    """Returns the number of tokens in a text string."""
    encoding = tiktoken.encoding_for_model(encoding_name)
    num_tokens = len(encoding.encode(string))
    return num_tokens

if __name__ == "__main__":
    tokens = num_tokens_from_string(prompt, "gpt-4")
    print(f"Number of tokens: {tokens}")

フォルダ構成は以下の通りです。

┌─ .venv/
├─ .gitignore
├─ main_original.py
└─ requirements.txt

Dockerfileの作成

まずはDockerfileを作成します。DockerfileはDockerイメージをビルドするための手順を定義したファイルです。

ベースイメージとは、Dockerイメージの元となる環境で、OSや特定の言語のランタイム、フレームワークなどが含まれています。ベースイメージは公式から提供されているイメージを使うこともできますが、独自で環境をカスタマイズしたイメージを使うこともできます。今回はPython公式のイメージをベースとして使用します。このイメージにはPythonのランタイムや標準ライブラリが含まれているため、Pythonアプリを簡単に構築することができます。

WORKDIR でコンテナ内の作業ディレクトリを設定します。この設定により、その後のすべてのコマンドが指定されたディレクトリ内で実行されます。

# ベースイメージ
FROM python:3.12

WORKDIR /app

# requirements.txtを元にパッケージをインストール
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY main_original.py .

CMD ["python", "main_original.py"]

Dockerfileを追加後のフォルダ構成です。

┌─ .venv/
├─ .gitignore
├─ Dockerfile
├─ main_original.py
└─ requirements.txt

以下のコマンドでビルドを行います。-t オプションは、Dockerイメージにタグ(名前)をつけるためのものです。タグをつけることで、Dockerイメージの管理がしやすくなります。

コマンドの最後の . は、現在の作業ディレクトリを示しています。作業ディレクトリにあるすべてのファイルとサブディレクトリがビルドプロセス中にDockerデーモンによって参照されるようになります。

参考:https://docs.docker.com/build/concepts/context/

docker build -t calc_token .

Rancher Desktopなどのコンテナ管理ツールで確認すると、Dockerイメージが追加されています。

20240830_dk_01

作成したDockerイメージからコンテナを作成して実行します。

-itオプションは-iオプションと-tオプションの組み合わせです。

-iオプションはインタラクティブモードであり、シェルやプログラムと対話できるようになります。

-tオプションはコマンド入力や実行といった端末機能を使えるようになります。

この2つを組み合わせることにより、インタラクティブなシェルを使ってコンテナを操作できる環境が実現できます。

ただしコンテナが実行するコマンドpython main_original.pyが終了するとコンテナ自体も終了するので、今回は対話できるような画面にはなりません。

docker run -it calc_token

コマンドを実行するとコンソールにトークン数が表示され、アプリが実行されたことがわかります。

20240830_dk_02

複数のファイルを含める

これでコンテナ起動と同時にmain_original.pyファイルを実行させることができましたが、特定のファイルを実行するのではなく、pythonコマンドでファイルを指定して実行するようにしたいと思います。

2つ目のpyファイルを作成します。

print("This is a second file.")

second_file.pyを追加後のフォルダ構成です。

┌─ .venv/
├─ .gitignore
├─ Dockerfile
├─ main_original.py
├─ requirements.txt
└─ second_file.py

Dockerfileを以下のように修正します。

main_original.pyのみコピーしていたのを全ファイルコピーするようにし、最後にpythonコマンドでmain_original.pyを実行していた行を削除しました。

# ベースイメージ
FROM python:3.12

WORKDIR /app

# requirements.txtを元にパッケージをインストール
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

再度ビルドします。

docker build -t calc_token .

作成したDockerイメージからコンテナを作成して実行します。このときDocker内のbashを起動します。

docker run -it calc_token /bin/bash

ファイルを選択して実行します。

python second_file.py

実行できました。

20240830_dk_03

次にPython環境のないPCで動作確認をするため、ここまでをGitHub等にコミットしておきます。

Python環境のないPCで実行

PythonがインストールされていないPCで、GitHubからリポジトリをクローンします。

上記と同じコマンドでビルドします。イメージ名は少し変えてみました。

docker build -t python_scripts .

ビルドできました。

20240830_dk_04

続いてコンテナを起動します。

初めは上記と同じコマンドを実行しました。

docker run -it python_scripts /bin/bash

このコマンドを実行すると、新環境では以下のようなエラーになりました。

docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "C:/Program Files/Git/usr/bin/sh": stat C:/Program Files/Git/usr/bin/sh: no such file or directory: unknown.

色々試行錯誤した結果、以下のコマンドなら動くことがわかりました。(なぜ/bin/bashで動かないのかまで調べられていません)

docker run -it python_scripts bash

何はともあれ、無事にPythonアプリを実行することができました。

20240830_dk_05

おわりに

シンプルなアプリをDockerに移行してみました。引き続きWebアプリやマイクロサービスもDocker化していきたいと思います。

この記事がどなたかの参考になれば幸いです。

この記事をシェアする

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.