我正在尝试使用
docker compose watch
配置 Django 项目,以将代码更改同步到容器化 Django 应用程序中。
撰写文件如下:
include:
- compose-db-dev.yaml
services:
webapp:
environment:
- DJANGO_SETTINGS_MODULE=app.settings.dev
build: .
ports:
- 3000:8080
develop:
watch:
- action: sync
path: .
target: /app
depends_on:
db:
condition: service_healthy
将操作设置为“同步”时,出现以下错误:
Syncing webapp after changes were detected:
- /home/jb/myapp/main/views.py
itar: app/main/views.py: Cannot open: File exists
tar: Exiting with failure status due to previous errors
WARN[0023] Error handling changed files for service webapp: 1 error occurred:
* copying files to 47b692a96cf0e7b8edd3922f27aaa05fd63d511176cfe1362126828a28d9f030: exit code 2
将手表操作设置为
rebuild
时不会出现此错误。一切正常,正在更新应用程序。然而,重建图像需要几秒钟的时间,这不是理想的工作流程资源。
据我所知,更改 Django 应用程序中的视图不需要“重建”服务,因此我认为同步操作是更好的选择。预计“文件存在”(同步的是现有文件),那么为什么我会收到此错误?
它看起来像是 compose watch 中的一个错误,要解决此问题,您需要以 root 身份运行容器,错误问题:https://github.com/docker/compose/issues/11304
因此,不要直接使用
USER myappuser
,但最好在 Dockerfile 中创建一个“dev”阶段,并仅在其中使用 root,这样在生产中运行的“prod”阶段仍然可以使用非 root “应用程序用户”。USER root
为了在 compose.yaml 中反映这一点,您需要为构建设置设置
# syntax=docker/dockerfile:1
ARG PYTHON_VERSION=3.10.12
FROM python:${PYTHON_VERSION}-slim as prod
# Prevents Python from writing pyc files.
ENV PYTHONDONTWRITEBYTECODE=1
# Keeps Python from buffering stdout and stderr to avoid situations where
# the application crashes without emitting any logs due to buffering.
ENV PYTHONUNBUFFERED=1
WORKDIR /app
# Create a non-privileged user that the app will run under.
# See https://docs.docker.com/go/dockerfile-user-best-practices/
ARG UID=10001
RUN adduser \
--disabled-password \
--gecos "" \
--home "/nonexistent" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
appuser
# Download dependencies as a separate step to take advantage of Docker's caching.
# Leverage a cache mount to /root/.cache/pip to speed up subsequent builds.
# Leverage a bind mount to requirements.txt to avoid having to copy them into
# into this layer.
RUN --mount=type=cache,target=/root/.cache/pip \
--mount=type=bind,source=requirements.txt,target=requirements.txt \
python -m pip install -r requirements.txt
# Switch to the non-privileged user to run the application.
USER appuser
# Copy the source code into the container.
COPY ./mydjangoapi .
# Expose the port that the application listens on.
EXPOSE 8000
# Run the application.
# CMD gunicorn 'myapp:app' --bind=0.0.0.0:8000
CMD gunicorn mydjangoapi.wsgi:application --bind=0.0.0.0:8000
FROM prod as dev
# switch to root because docker compose watch bug
USER root
CMD gunicorn mydjangoapi.wsgi:application --bind=0.0.0.0:8000
:
target: dev