プロジェクトディレクトリ作成
mkdir django-project && cd django-project
ディレクトリ構成
❯ tree
.
├── app
│ ├── Dockerfile
│ ├── manage.py
│ ├── config
│ │ ├── asgi.py
│ │ ├── __init__.py
│ │ ├── settings.py
│ │ ├── urls.py
│ │ └── wsgi.py
│ ├── Pipfile
│ ├── Pipfile.lock
│ └── requirements.txt
├── compose.yml
└── db
.gitignore 準備
こちらのお世話になる。
https://djangowaves.com/tips-tricks/gitignore-for-a-django-project/
その上で以下を追加
# Pipenv
Pipfile.lock
appディレクトリ作成、移動
mkdir app && cd app
requirements.txt 作成
Django==5.2
psycopg2-binary
Djangoアプリ作成
# アプリ作成用コンテナ起動
docker container run --rm -it -w "/app" -v "${PWD}":/app python:3.11-slim /bin/bash
# pip関連実行
python -m pip install --upgrade pip \
&& pip install pipenv \
&& pipenv install -r requirements.txt --skip-lock \
&& pipenv lock
# djangoアプリ作成
pipenv shell
django-admin startproject config .
django開発用Dockerfile
FROM python:3.11-slim
# 環境変数で .venv をプロジェクト直下に作らせる
ENV PIPENV_VENV_IN_PROJECT=1
# 必要なパッケージやツールをインストール(pipenv と依存関係のインストール)
RUN apt-get update && apt-get install -y sudo \
&& rm -rf /var/lib/apt/lists/* \
&& pip install --upgrade pip \
&& pip install pipenv
# vscode ユーザーの作成(UID=1000はVS Codeと一致させる)
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID
RUN groupadd --gid $USER_GID $USERNAME \
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \
&& echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/$USERNAME \
&& chmod 0440 /etc/sudoers.d/$USERNAME
# 作業ディレクトリの設定
WORKDIR /app
# 必要なファイルをコピー
COPY Pipfile Pipfile.lock /app/
# 権限変更(pipenv installをvscodeユーザーで行うため)
RUN chown -R $USERNAME:$USERNAME /app
# vscodeユーザーに切り替え
USER $USERNAME
# pipenvを使って依存関係をインストール(ロックファイルを基にインストール)
RUN pipenv install --deploy --ignore-pipfile
# アプリケーションの全体をコピー(vscodeユーザーの権限で)
COPY --chown=vscode:vscode . /app/
# ポート明示(任意)
EXPOSE 8000
# コンテナ起動時に実行するコマンドを設定
CMD ["pipenv", "run", "python", "manage.py", "runserver", "0.0.0.0:8000"]
.dockerignore 作成
# 仮想環境などビルド不要なもの
.venv/
__pycache__/
*.pyc
*.pyo
*.pyd
# エディタ関連
.vscode/
.idea/
# 本番で不要なファイル
.env
db.sqlite3
*.log
コンテナ起動
## イメージ作成
docker image build -t django-app .
## コンテナ起動
docker container run -p 8000:8000 django-app:latest
http://localhost:8080にブラウザでアクセスし起動確認
compose.yml作成
services:
app:
build: ./app
container_name: django-app
command: pipenv run python manage.py runserver 0.0.0.0:8000
volumes:
- ./app:/app
- venv_data:/app/.venv
ports:
- "8000:8000"
environment:
DEBUG: "${DEBUG}"
SECRET_KEY: "${SECRET_KEY}"
ALLOWED_HOSTS: "${ALLOWED_HOSTS}"
TIME_ZONE: "${TIME_ZONE}"
POSTGRES_DB: "${POSTGRES_DB}"
POSTGRES_USER: "${POSTGRES_USER}"
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
POSTGRES_HOST: "${POSTGRES_HOST}"
POSTGRES_PORT: "${POSTGRES_PORT}"
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10s
db:
image: postgres:15-alpine
container_name: django-db
volumes:
- db_data:/var/lib/postgresql/data/
environment:
POSTGRES_DB: "${POSTGRES_DB}"
POSTGRES_USER: "${POSTGRES_USER}"
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
ports:
- "5432:5432"
healthcheck:
test: ["CMD", "pg_isready", "-U", "${POSTGRES_USER}", "-d", "${POSTGRES_DB}"]
interval: 5s
timeout: 3s
retries: 5
start_period: 5s
volumes:
db_data:
venv_data:
.envファイル作成
DEBUG=True
SECRET_KEY=your_very_secret_key_here
ALLOWED_HOSTS=*
TIME_ZONE=Asia/Tokyo
POSTGRES_DB=myproject
POSTGRES_USER=django
POSTGRES_PASSWORD=your_password_here
POSTGRES_HOST=django-db
POSTGRES_PORT=5432
Django settings.py
import os
DEBUG = os.getenv('DEBUG', 'False').lower() == 'true'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('POSTGRES_DB', 'myproject'),
'USER': os.environ.get('POSTGRES_USER', 'django'),
'PASSWORD': os.environ.get('POSTGRES_PASSWORD', 'your_password'),
'HOST': os.environ.get('POSTGRES_HOST', 'db'),
'PORT': int(os.environ.get('POSTGRES_PORT', 5432)),
}
}
TIME_ZONE = os.environ.get('TIME_ZONE', 'UTC')
devcontainer.json
{
"name": "Django Dev",
"dockerComposeFile": ["../compose.yml"],
"service": "app",
"workspaceFolder": "/app",
"forwardPorts": [8000],
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"charliermarsh.ruff",
"batisteo.vscode-django",
"oderwat.indent-rainbow",
"ms-ceintl.vscode-language-pack-ja"
],
"settings": {
"python.defaultInterpreterPath": "/app/.venv/bin/python",
"python.languageServer": "Pylance",
"python.formatting.provider": "none", // Ruff を使うため、他のフォーマッタは無効化
"python.linting.enabled": true,
"python.linting.pylintEnabled": false,
// Ruffをデフォルトのフォーマッタとして設定
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit", // Ruffがisortの機能を含むため、これで対応
"source.fixAll": "explicit" // RuffのLint修正も保存時に実行
}
},
// 日本語パックを有効にするための設定
"locale": "ja"
}
}
},
"remoteUser": "vscode",
"features": {}
}
pyproject.toml(appディレクトリ直下)
[tool.ruff]
exclude = [
"migrations",
"venv",
".venv",
]
line-length = 88
target-version = "py311"
[tool.ruff.lint]
select = [
"F", # Flake8
"B", # Black
"I", # isort
"E", # error
"W" # warning
]
ignore = []
fixable = ["E", "W", "I"]