今日は、uvでパッケージ管理をしているDjangoプロジェクトを、Docker上でイメージをビルドしてコンテナを起動し、ブラウザに表示させるところまで行くことができました。
まだまだDockerをやり始めたばかりの初心者なので分からないことも多いですが、ひとまず自分用のアウトプットとしてこの記事を残しておきます。
実行した事
本日取り組んだ概要は以下の通り。
- uvでパッケージ管理したDjangoプロジェクトを作成
- dockerfileの記述
- イメージのビルドとコンテナの起動
- ブラウザで動作確認
uvでパッケージ管理したDjangoプロジェクトを作成
今後のソフトウェア開発では絶対にuvを使っていきたいので、Docker上でもuvを使う事ができるようにする方法を模索した。
dockerでuvが使えるかテストするために、Djangoプロジェクトの最小構成を作成。
uv init dockerfile_tutorial
cd dockerfile_tutorial
uv add django
uv run django-admin startproject config src
cd src
uv run manage.py startapp my_app
uv run manage.py runserver
localhost:8000にアクセスし、ロケットが飛んでいるのを確認。
dockerfileの記述
今回のテストで作成したdockerfileの内容は以下の通り。
(プロジェクトルートに作成)
# 1. 公式のuv+pythonイメージを使用
FROM ghcr.io/astral-sh/uv:0.9.2-python3.12-bookworm-slim
# 作業ディレクトリの設定
WORKDIR /app
# 依存関係のコピーとインストール
# ./は、現在の作業ディレクトリを意味する
# キャッシュを効率化するため、ソースコードより先に依存関係ファイルをコピー
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-cache
# パスを通す
ENV PATH="/app/.venv/bin:$PATH" \
PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1
# ソースコードをコピー
COPY ./src /app/src
# サーバーを起動するディレクトリへ移動
WORKDIR /app/src
# コンテナが8000番ポートを使用する事を明示
EXPOSE 8000
# コンテナ起動時にDjangoを立ち上げる
# 0.0.0.0:8000 を指定するのがポイント
CMD ["uv", "run", "python", "manage.py", "runserver", "0.0.0.0:8000"]
dockerfileを書くのも初めてだったので、各コードの意味をおさらいする。
-
FROM- 新しいステージのビルドを定義し、以降のインストラクションのベースイメージをセットする。有効なdockerfileは、全てこの
FROMから始まる。
- 新しいステージのビルドを定義し、以降のインストラクションのベースイメージをセットする。有効なdockerfileは、全てこの
-
WORKDIR- 作業ディレクトリの設定。以降で実行する
RUNやCMDといったインストラクションは、全てこのdockerコンテナ上の作業ディレクトリで行われる。指定した名前のディレクトリは、このインストラクション実行時に作成される。
- 作業ディレクトリの設定。以降で実行する
-
COPY- ファイルやディレクトリをコピーする。ここでは、
pyproject.toml,uv.lockが<src>(コピー元)、./が<dest>(コピー先)。./は現在の作業ディレクトリを指す。
- ファイルやディレクトリをコピーする。ここでは、
-
RUN- イメージを作成するビルド時に実行されるコマンド。カレントイメージの一番上に新しいレイヤーを作成する。ここでは
uv syncを実行して、ライブラリの仮想環境を作成。
- イメージを作成するビルド時に実行されるコマンド。カレントイメージの一番上に新しいレイヤーを作成する。ここでは
-
ENV- 環境変数を設定している。これによってスクリプトの実行時に
Pythonと記述するだけで済むようになる。他にも、ログ出力の設定やキャッシュの設定など。しかし今回は必要なかったのかもしれない。
- 環境変数を設定している。これによってスクリプトの実行時に
-
EXPOSE- ポート開放。このファイルでは8000とすることで、このコンテナが8000番を使う事を宣言している。
-
CMD- これはイメージのビルド時ではなく、コンテナの起動時に実行されるコマンド。ここに
"0.0.0.0:8000"、特に0.0.0.0とすることで、外部からのリクエストを全て受け付ける、という状態にする。これによって、自分のPCからのリクエストがコンテナに届くようになる。
- これはイメージのビルド時ではなく、コンテナの起動時に実行されるコマンド。ここに
イメージのビルドとコンテナの起動
docker buildコマンドでイメージをビルド。
docker build -t django-test .
-tでイメージに人間が読みやすい名前を付ける。.はカレントディレクトリにdockerfileがある事を教えている。
続いてコンテナを起動する。ここでホストPCの8000番(左)とコンテナの8000番(右)を繋いでいる(ポートフォワディング)。
docker run -p 8000:8000 django-test
これを設定することで、自分のPCのWebブラウザ上でlocalhost:8000にアクセスすると、docker側が、「これはコンテナの8000番へのリクエストだな」と判断して繋いでくれる。
ブラウザで動作確認
最後に、Webブラウザでhttp://localhost:8000にアクセスして動作確認。
ローカルホストの8000番にアクセスすると、それがコンテナの8000番に繋がって、そこで動いているdjangoのサーバーに繋がり、ロケットが表示される。