Dockerコンテナ内でDjangoの開発をする
経緯
Pythonの開発環境では、venvやpyenvやらで仮想環境を作り、パッケージをプロジェクトごとに分けて開発します。
しかし、これでは問題がありました。
- VScodeの拡張機能を動かすためにコンテナ内部とホストOS側の両方でPythonのパッケージをインストールしなければいけない
- aptはほかのプロジェクトと全部共通になってしまう
- venvやpyenvのインストールや管理が大変(個人の感想です)
じゃあ、どうせ動かしているし、Dockerコンテナ内で開発しちゃおうと思ったわけです。
ただし、これがいいやり方かといわれると自身はありません。
前半はuvでのDjangoプロジェクトの立ち上げの記事ですので、わかる人はコンテナ内で開発するときに発生する問題とその解決方法から読んでください。
要件
環境
- Windows 11
- Docker Desktop
- WSL
今回の目標
Djangoのサーバーを立ち上げ、ロケットを飛ばす
Dockerコンテナを立ち上げる
今回はパッケージを管理するためにuvを使います。
Pythonパッケージをインストール
以下のDockerfileを作業ディレクトリに作成します。
FROM python:3.13-slim
ENV PYTHONUNBUFFERED=1
# uvをインストール
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
# uvで仮想環境を作らない設定
ENV UV_PROJECT_ENVIRONMENT=/usr/local
RUN apt-get update && apt-get install -y \
# Pythonイメージではlessなどがなく、作業がしにくいので入れる(なくても動く)
less \
vim \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# コードをコンテナ内に移動
WORKDIR /apps
COPY . /apps
※uvはpipでインストールすることもできますが、pipを使わないという一貫性がなくなってしまうため、このようにインストールしています。
まずはbuildします。
docker build . -t django-dev
次にuvの初期化コマンドをたたき、pyproject.tomlファイルを作ります。
docker run -v .:/apps --rm django-dev uv init --app .
-
django-dev:buildの時に指定したイメージ名 -
-v .:/apps:これがないとコンテナ内の変更がホストOS側に反映されない -
--rm:runをすると動き終わったコンテナが大量にごみとして出るので実行後に削除するためのオプション -
--app:今回の例ではアプリケーションとして作成(任意) -
.:最後のドットは平たく言うと、pyproject.tomlを今のディレクトリに作成するというオプション
結果は以下のようになります。
$ ls -a
. .. .python-version Dockerfile README.md main.py pyproject.toml
Djangoをはじめとするパッケージをインストールしていきます。
docker run -v .:/apps --rm django-dev uv add django
ロケットを飛ばす(Djangoの設定)
Djangoのプロジェクトを作成します。
docker run -v .:/apps --rm django-dev uv run django-admin startproject django_dev .
今回のプロジェクト名はdjango_devです。Djangoのプロジェクト名には「-」が使えないので注意してください。
最後の「.」はmanage.pyを.(現在のディレクトリ)に置きます。というオプションです。
uv initで作成されたmain.pyはいらないので消してしまいましょう。
rm main.py
DockerfileにDjangoの設定を追加していきます。
FROM python:3.13-slim
ENV PYTHONUNBUFFERED=1
# uvをインストール
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
# uvで仮想環境を作らない設定
ENV UV_PROJECT_ENVIRONMENT=/usr/local
RUN apt-get update && apt-get install -y \
# Pythonイメージではlessなどがなく、作業がしにくいので入れる(なくても動く)
less \
vim \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# コードをコンテナ内に移動
WORKDIR /apps
COPY . /apps
+
+ # 依存関係をインストール
+ RUN uv sync --frozen
+
+ # アプリケーションを実行
+ CMD ["uv", "run", "python", "manage.py", "runserver", "0.0.0.0:8000"]
いよいよDockerコンテナを動かします。
Dockerfileを更新したのでbuildをし直しましょう。
docker build . -t django-dev
その後にコンテナを立ち上げます。
docker run --rm -v .:/apps -p 8000:8000 django-dev
おめでとうございます。ロケットが飛びました。

コンテナ内で開発する
開発にはVSCodeを使います。
コンテナ内部に入る
初めにDockerコンテナの拡張機能を入れましょう。

下の画像のようにCONTAINERSからdjango-devを探し、右クリックをして項目を開きます。
Visual Studio Codeをアタッチするを選択します。

※画像ではCtrl+'が割り当てられていますが、これは私が割り当てたものです。
その後、一番上にこのようなセレクタが出てくるのでdjango-devを選択します。

新しくVSCodeが立ち上がります。これはすでにコンテナの中です。
後は、「フォルダーを開く」から/appsを選択して作業してください。
また、VSCodeのターミナルからコマンドを打つことができます。
例えば、python manage.py --helpなどのように普通にpythonのコマンドが使えます。
これで最低限の環境は整いましたが、何個か問題があります。
コンテナ内で開発するときに発生する問題とその解決方法
Gitを使おうとすると問題が出てきますのでその解消方法を示したいと思います。
まずはgitをDockerfileに追加してbuildし直してください。
...
RUN apt-get update && apt-get install -y \
less \
vim \
+ # GitHub
+ git \
+ ssh \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# プロジェクトをコピー
WORKDIR /apps
COPY . /apps
+ # gitの設定
+ RUN git config --global --add safe.directory /apps
# 依存関係をインストール
RUN uv sync --frozen
...
git commitで日本語が入力できない
git commit -m '初期化'
とやろうとすると日本語が表示されません。
これはaptでパッケージを入れて、環境変数を設定すると解決できます。
RUN apt-get update && apt-get install -y \
less \
vim \
+ # 日本語対応
+ locales \
+ locales-all \
# GitHub
git \
ssh \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
+ # 日本語の設定
+ RUN locale-gen ja_JP.UTF-8
+ ENV LANG=ja_JP.UTF-8
buildし直してください。
これでコミットメッセージに日本語が使えるようになりました。
git pullなどGitHubへつなげられない
# git pull
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
GitHubへのSSHをしてpullなどをしているのですが、GitHub側からはこれが誰かわからないわけです。
これをHostOSと同じ設定でpullをしたいと思うわけです。
そこでssh-agentを使います。
# ssh-agentを起動する
eval "$(ssh-agent -s)"
# 秘密鍵を追加
ssh-add ~/.ssh/id_ed25519
そして、Volumeで鍵情報をホストOSと共有するようにしましょう。
これにより、ホストOS側のSSH認証情報をそのままコンテナで利用できるようになります。
docker run --rm -v .:/apps -v ${SSH_AUTH_SOCK}:/ssh-agent -v ${HOME}/.gitconfig:/root/.gitconfig:ro -e SSH_AUTH_SOCK=/ssh-agent -p 8000:8000 django-dev
これでコンテナ内でgit pullができるようになります。
コンテナ内で開発するときの注意
コンテナ内ではroot権限になる
特に設定をしていない場合はコンテナ内部にいるときはrootになりますので、コンテナ内部でファイルを作成するとホストOS(WSL上)では編集できない場合があります。また、権限がないとホストOS側でgit addなどもできません。
なので、ファイルの操作をするときはコンテナ内部に入るか、
docker run -v .:/apps --rm django-dev git add .
のようにdocker runを使ってコンテナ内部で行うようにしましょう。
まとめ
最終的なDockerfileは以下のようになりました。
FROM python:3.13-slim
ENV PYTHONUNBUFFERED=1
# uvをインストール
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
# uvで仮想環境を作らない設定
ENV UV_PROJECT_ENVIRONMENT=/usr/local
RUN apt-get update && apt-get install -y \
less \
vim \
# 日本語対応
locales \
locales-all \
# GitHub
git \
ssh \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# 日本語の設定
RUN locale-gen ja_JP.UTF-8
ENV LANG=ja_JP.UTF-8
# プロジェクトをコピー
WORKDIR /apps
COPY . /apps
# gitの設定
RUN git config --global --add safe.directory /apps
# 依存関係をインストール
RUN uv sync --frozen
# アプリケーションを実行
CMD ["uv", "run", "python", "manage.py", "runserver", "0.0.0.0:8000"]
そして、一日の初めに
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
を打ち、コンテナを起動するときは
docker run --rm -v .:/apps -v ${SSH_AUTH_SOCK}:/ssh-agent -v ${HOME}/.gitconfig:/root/.gitconfig:ro -e SSH_AUTH_SOCK=/ssh-agent -p 8000:8000 django-dev
を使います。
これでコンテナ内での開発ができるようになりました。
毎日たたくコマンドをシェルスクリプトにまとめたり、docker-compose.ymlを使ったりとまだまだ改善できるところはたくさんあると思います。記事を読んだ人が理想の開発環境づくりの手助けになれたら幸いです。
Discussion