SOLVED!
Ken, thank yout for your help. There are two solutions:
- keep the file start as is
#!/bin/bash
set -o errexit
set -o pipefail
set -o nounset
python manage.py migrate
exec python manage.py runserver_plus 0.0.0.0:8000
and change overrideCommand
to True
in devcontainer.json
- this is how I did it
// Tells devcontainer.json supporting services / tools whether they should run
// /bin/sh -c "while sleep 1000; do :; done" when starting the container instead of the containerâs default command
"overrideCommand": true,
OR
- keep
overrideCommand
set to false
and change the file start
start
#!/bin/bash
set -o errexit
set -o pipefail
set -o nounset
exec /bin/bash -c "trap : TERM INT; sleep infinity & wait"
# python manage.py migrate
# exec python manage.py runserver_plus 0.0.0.0:8000
So now, when I reopen the project in dev container, which VS Code proposes me to do, it works, VS Code opens terminal in dev container directly and I can run Django command, e.g. â/manage.py runserver_plus 0.0.0.0:8000â
PostgreSQL is available
Agent pid 452
dev-user@e43bdabb2e9d:/app$ './manage.py runserver_plus 0.0.0.0:8000'
bash: ./manage.py runserver_plus 0.0.0.0:8000: No such file or directory
dev-user@e43bdabb2e9d:/app$ ./manage.py runserver_plus 0.0.0.0:8000
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:8000
* Running on http://172.20.0.3:8000
Press CTRL+C to quit
* Restarting with watchdog (inotify)
Performing system checks...
System check identified no issues (0 silenced).
Django version 5.1, using settings 'config.settings.local'
Development server is running at http://0.0.0.0:8000/
Using the Werkzeug debugger (https://werkzeug.palletsprojects.com/)
Quit the server with CONTROL-C.
* Debugger is active!
* Debugger PIN: 264-407-905
For the reference my final configuration is:
Dockerfile
# define an alias for the specific python version used in this file.
FROM docker.io/python:3.12.5-slim-bookworm AS python
# Python build stage
FROM python AS python-build-stage
ARG BUILD_ENVIRONMENT=local
# Install apt packages
RUN apt-get update && apt-get install --no-install-recommends -y \
# dependencies for building Python packages
build-essential \
# psycopg dependencies
libpq-dev
# Requirements are installed here to ensure they will be cached.
COPY ./requirements .
# Create Python Dependency and Sub-Dependency Wheels.
RUN pip wheel --wheel-dir /usr/src/app/wheels \
-r ${BUILD_ENVIRONMENT}.txt
# Python 'run' stage
FROM python AS python-run-stage
ARG BUILD_ENVIRONMENT=local
ARG APP_HOME=/app
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
ENV BUILD_ENV=${BUILD_ENVIRONMENT}
WORKDIR ${APP_HOME}
# devcontainer dependencies and utils
RUN apt-get update && apt-get install --no-install-recommends -y \
sudo git bash-completion nano ssh
# Create devcontainer user and add it to sudoers
RUN groupadd --gid 1000 dev-user \
&& useradd --uid 1000 --gid dev-user --shell /bin/bash --create-home dev-user \
&& echo dev-user ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/dev-user \
&& chmod 0440 /etc/sudoers.d/dev-user
# Install required system dependencies
RUN apt-get update && apt-get install --no-install-recommends -y \
# psycopg dependencies
libpq-dev \
# Translations dependencies
gettext \
# cleaning up unused files
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
&& rm -rf /var/lib/apt/lists/*
# All absolute dir copies ignore workdir instruction. All relative dir copies are wrt to the workdir instruction
# copy python dependency wheels from python-build-stage
COPY --from=python-build-stage /usr/src/app/wheels /wheels/
# use wheels to install python dependencies
RUN pip install --no-cache-dir --no-index --find-links=/wheels/ /wheels/* \
&& rm -rf /wheels/
COPY ./compose/production/django/entrypoint /entrypoint
RUN sed -i 's/\r$//g' /entrypoint
RUN chmod +x /entrypoint
COPY ./compose/local/django/start /start
RUN sed -i 's/\r$//g' /start
RUN chmod +x /start
# copy application code to WORKDIR
COPY . ${APP_HOME}
ENTRYPOINT ["/entrypoint"]
docker-compose.local
volumes:
findacoach_local_postgres_data: {}
findacoach_local_postgres_data_backups: {}
services:
django:
build:
context: .
dockerfile: ./compose/local/django/Dockerfile
image: findacoach_local_django
container_name: findacoach_local_django
depends_on:
- postgres
volumes:
- .:/app:z
env_file:
- ./.envs/.local/.django
- ./.envs/.local/.postgres
ports:
- '8000:8000'
command: /start
postgres:
build:
context: .
dockerfile: ./compose/production/postgres/Dockerfile
image: findacoach_production_postgres
container_name: findacoach_local_postgres
volumes:
- findacoach_local_postgres_data:/var/lib/postgresql/data
- findacoach_local_postgres_data_backups:/backups
env_file:
- ./.envs/.local/.postgres
and dev container.json
// For format details, see https://containers.dev/implementors/json_reference/
{
"name": "findacoach_dev",
"dockerComposeFile": [
"../docker-compose.local.yml"
],
"init": true,
"mounts": [
{
"source": "./.devcontainer/bash_history",
"target": "/home/dev-user/.bash_history",
"type": "bind"
},
{
"source": "~/.ssh",
"target": "/home/dev-user/.ssh",
"type": "bind"
}
],
// Tells devcontainer.json supporting services / tools whether they should run
// /bin/sh -c "while sleep 1000; do :; done" when starting the container instead of the containerâs default command
"overrideCommand": true,
"service": "django",
// "remoteEnv": {"PATH": "/home/dev-user/.local/bin:${containerEnv:PATH}"},
"remoteUser": "dev-user",
"workspaceFolder": "/app",
// Set *default* container specific settings.json values on container create.
"customizations": {
"vscode": {
"settings": {
"editor.formatOnSave": true,
"[python]": {
"analysis.autoImportCompletions": true,
"analysis.typeCheckingMode": "basic",
"defaultInterpreterPath": "/usr/local/bin/python",
"editor.codeActionsOnSave": {
"source.organizeImports": "always"
},
"editor.defaultFormatter": "charliermarsh.ruff",
"languageServer": "Pylance",
"linting.enabled": true,
"linting.mypyEnabled": true,
"linting.mypyPath": "/usr/local/bin/mypy"
}
},
// https://code.visualstudio.com/docs/remote/devcontainerjson-reference#_vs-code-specific-properties
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"davidanson.vscode-markdownlint",
"mrmlnc.vscode-duplicate",
"visualstudioexptteam.vscodeintellicode",
"visualstudioexptteam.intellicode-api-usage-examples",
// python
"ms-python.python",
"ms-python.vscode-pylance",
"charliermarsh.ruff",
// django
"batisteo.vscode-django"
]
}
},
// Uncomment the next line if you want start specific services in your Docker Compose config.
// "runServices": [],
// Uncomment the next line if you want to keep your containers running after VS Code shuts down.
// "shutdownAction": "none",
// Uncomment the next line to run commands after the container is created.
"postCreateCommand": "git config --global --add safe.directory ${containerWorkspaceFolder} && cat .devcontainer/bashrc.override.sh >> ~/.bashrc"
}