Docker部署Django应用时wait-for-it.sh脚本权限拒绝问题求助
Docker部署Django应用时wait-for-it.sh脚本权限拒绝问题求助
各位好,我现在在用Docker部署Django应用,但是执行检查PostgreSQL是否就绪的wait-for-it.sh脚本时,一直碰到权限拒绝的错误:chmod: /api/config/scripts/wait-for-it.sh: Permission denied,然后容器就直接停止运行了。
先贴一下我的相关配置文件:
Dockerfile内容
# Stage 1: Base build stage FROM python:3.13-slim AS builder # Create the app directory RUN mkdir /api # Set the working directory WORKDIR /api # Set environment variables to optimize Python ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ libpcre3-dev \ libssl-dev \ python3-dev \ libpango1.0-dev \ libcairo2-dev \ libpq-dev \ bash \ fontconfig \ fonts-dejavu-core \ fonts-droid-fallback \ fonts-freefont-ttf \ fonts-liberation \ && rm -rf /var/lib/apt/lists/* # Install dependencies first for caching benefit RUN pip install --upgrade pip RUN mkdir /requirements COPY ./requirements/. ./requirements/. RUN set -e; \ pip3 install --upgrade pip && \ pip3 install uwsgi && \ pip3 install --default-timeout=100 --no-cache-dir -r ./requirements/stage.txt # Stage 2: Production stage FROM python:3.13-slim RUN useradd -m -r -g www-data app_user && \ mkdir /api && \ chown -R app_user /api # Copy the Python dependencies from the builder stage COPY --from=builder /usr/local/lib/python3.13/site-packages/ /usr/local/lib/python3.13/site-packages/ COPY --from=builder /usr/local/bin/ /usr/local/bin/ # Set the working directory WORKDIR /api # Copy application code COPY --chown=app_user:app_user . . RUN chown -R app_user:www-data /api # Set environment variables to optimize Python ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 RUN chown app_user:www-data ./config/uwsgi && \ mkdir -p /run/uwsgi && \ chown app_user:www-data /run/uwsgi # Switch to non-root user USER app_user # Expose the application port EXPOSE 8000 # Make entry file executable RUN chmod +x /api/config/scripts/wait-for-it.sh # Verify if postgress ready ! CMD ["/api/config/scripts/wait-for-it.sh"]
docker-compose.yml中api服务的配置
services: api: image: "${MY_API_IMAGE_FROM_ENV}" restart: always command: > sh -c "/api/config/scripts/wait-for-it.sh db:5432 && python /api/project/manage.py makemigrations && python /api/project/manage.py migrate && uwsgi --ini /api/config/uwsgi/uwsgi.stage.ini" volumes: - .:/api - uwsgi_socket:/run/uwsgi - /var/log/project:/api/logs environment: - DJANGO_SETTINGS_MODULE=project.settings.stage - POSTGRES_USER=${BACKEND_USER_DB} - POSTGRES_PASSWORD=${BACKEND_PASSWORD_DB} - POSTGRES_DB=${BACKEND_DB_NAME} - POSTGRES_PORT= ${BACKEND_PORT_DB} env_file: - .env depends_on: - db networks: - app_network container_name: api
我本来以为是用户权限的问题,所以特意创建了app_user,并尝试给它赋予脚本的执行权限,但还是碰到这个错误。有没有大佬能帮我看看问题出在哪?
针对这个问题的解决方案分析
我帮你梳理了几个可能的问题点和对应的解决办法:
- 权限修改时机错误
你在Dockerfile里是先切换到app_user非root用户,再执行chmod +x给脚本加执行权限,但此时app_user可能没有修改文件权限的权限——哪怕文件的所有者是自己,修改权限也需要额外的权限(比如文件的写权限)。更稳妥的方式是在切换到非root用户之前,就以root身份给脚本加上执行权限,root用户拥有最高权限,肯定能修改成功。
修改Dockerfile的顺序:
# 先在root身份下给脚本加执行权限 RUN chmod +x /api/config/scripts/wait-for-it.sh # 再切换到非root用户 USER app_user # Expose the application port EXPOSE 8000 # Verify if postgress ready ! CMD ["/api/config/scripts/wait-for-it.sh"]
- 本地挂载覆盖了容器内的文件权限
你在docker-compose里配置了volumes: - .:/api,把本地代码目录直接挂载到容器的/api目录下,这会直接覆盖Dockerfile里复制进去的文件。如果本地的wait-for-it.sh本身没有执行权限(比如本地权限是644),那挂载到容器后,即使Dockerfile里加了权限,也会被本地的无权限文件覆盖。
对应解决办法:
- 先在本地给脚本加上执行权限:
chmod +x config/scripts/wait-for-it.sh,然后再启动容器。 - 或者在docker-compose的command里,先临时给脚本加权限再执行:
command: > sh -c "chmod +x /api/config/scripts/wait-for-it.sh && /api/config/scripts/wait-for-it.sh db:5432 && python /api/project/manage.py makemigrations && python /api/project/manage.py migrate && uwsgi --ini /api/config/uwsgi/uwsgi.stage.ini"
- 挂载目录的权限冲突
因为本地目录挂载到容器后,容器内/api目录的权限会被本地目录的权限覆盖,app_user可能没有权限访问或修改挂载进来的wait-for-it.sh。可以先检查本地目录的权限,确保app_user对应的UID/GID能访问,不过优先解决前两个问题,大概率就能解决你的报错了。
内容来源于stack exchange
相关产品推荐
相关产品推荐

