Развертывание приложения Django с помощью Docker

Я пытаюсь развернуть свое приложение django с помощью docker. Но когда я запускаю свой скрипт, чтобы убедиться, что база данных (postgres) готова, я всегда получаю эту ошибку: chmod: /app/scripts/wait-for-it.sh: В разрешении отказано, а затем контейнер перестает работать.

Это мой файл 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"]

Это мой api-сервис в моем yml-файле :

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/scripts/wait-for-it.sh установлены разрешения на выполнение только вашим пользователем на вашем локальном компьютере (не в Docker), и поэтому, когда пользователь docker пытается запустить его, вы получаете сообщение об ошибке permission denied. Чтобы проверить эту теорию, вы можете попробовать следующее на своем локальном компьютере:

sudo chmod 777 /app/scripts/wait-for-it.sh

Это позволит установить права доступа для выполнения этого скрипта всеми пользователями. (Обратите внимание, что это не идеально и не должно оставаться постоянной настройкой, только в качестве теста.) Если вы по-прежнему получаете сообщение об ошибке с правами доступа, вы можете быть немного более жестким, установив разрешить все разрешения для всего каталога и всех файлов, содержащихся в:

sudo chmod -R 777 /app/

Но это ДЕЙСТВИТЕЛЬНО открыто и довольно небезопасно, поэтому я был бы осторожен, используя это, и обязательно верните разрешения на минимальный доступ, как только ваш контейнер docker заработает.

Может оказаться полезным создать пользователя внутри контейнера docker, а затем вы сможете изменить права доступа к своим папкам / файлам, чтобы разрешить этому пользователю выполнять скрипты только из них, что значительно подробнее безопаснее, чем оставлять все с полными разрешениями для всех. На этой странице содержится некоторая полезная информация о команде chmod, о том, как читать обозначения для предоставления разрешений и как вы можете предоставить определенные разрешения только определенному пользователю или группе пользователей.

Хотя ваша текущая ошибка, скорее всего, связана с проблемой с правами доступа, она, вероятно, не приведет к желаемому результату. Стандартный и простой способ удовлетворить ваши требования - использовать healthcheck и dependecy в вашем docker compose.

Вот минимальный пример, показывающий, как следует использовать эти ключевые слова:

services:

  database:
    image: postgres
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "pg_isready", "--dbname=app", "--username=app"]
      interval: 5s
      timeout: 2s
      retries: 5

  app:
    image: app/app:1.0
    restart: unless-stopped
    depends_on:
      database:
        condition: service_healthy

Вы переключаетесь на app_user перед запуском chmod, и у этого пользователя, скорее всего, нет прав на запуск скрипта. Попробуйте запустить chmod +x перед

USER app_user
Вернуться на верх