skip to Main Content

I’m making a Django app and I’m using Docker por production deployment, the application almost runs fine on the VPS(Ubuntu 20.04) except that when I try to run collectstatic with this command:

sudo docker-compose -f docker-compose.prod.yml exec web python manage.py collectstatic --no-input

Always throws this error:

PermissionError: [Errno 13] Permission denied: '/home/app/web/staticfiles/img/app_logo.png'

This is my docker-compose:

version: '3'
services:
  db:
    restart: unless-stopped
    image: "postgres:13.2-alpine"
    container_name: db
    ports:
      - "5432:5432" # HOST:CONTAINER
    env_file:
      - ./.env.prod
    volumes:
      - ./pgdata:/var/lib/postgresql/data
  web:
    container_name: web
    restart: unless-stopped
    build:
      context: .
      dockerfile: ./docker/production/Dockerfile
    environment:
      DJANGO_SETTINGS_MODULE: MyApp.app_settings.production
    command: gunicorn MyApp.wsgi:application --bind 0.0.0.0:8000
    expose:
      - "8000"
    env_file:
      - ./.env.prod
    volumes:
      - .:/app # Enable code reload
      - ./run/static:/home/app/web/staticfiles
      - ./run/media:/home/app/web/mediafiles
    depends_on:
      - db
  nginx:
    container_name: nginx
    restart: unless-stopped
    build: docker/production/nginx
    volumes:
      - ./run/static:/home/app/web/staticfiles
      - ./run/media:/home/app/web/mediafiles
    ports:
      - "80:80"
      - "443:443"
    depends_on:
      - web

and this is my Dockerfile:

# pull official base image
FROM python:3.8

# create directory for the app user
RUN mkdir -p /home/app

# create the app user
#RUN addgroup -S app && adduser -S app -G app
RUN adduser --system --group app

# create the appropriate directories
ENV HOME=/home/app
ENV APP_HOME=/home/app/web
RUN mkdir $APP_HOME
RUN mkdir $APP_HOME/staticfiles
RUN mkdir $APP_HOME/mediafiles
WORKDIR $APP_HOME

# Own home directory
RUN chown -R app:app $HOME

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# install dependencies
#RUN apk update && apk add libpq
#COPY --from=builder /usr/src/app/wheels /wheels
#COPY --from=builder /usr/src/app/requirements.txt .
#RUN pip install --no-cache /wheels/*

COPY ./requirements.txt $APP_HOME
RUN pip install --no-cache-dir -r requirements.txt

RUN apt-get clean
RUN apt-get update
# Install netcat
RUN apt install -y netcat
# Install wkhtml2pdf
RUN wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.buster_amd64.deb
RUN DEBIAN_FRONTEND=noninteractive apt install -y -q ./wkhtmltox_0.12.6-1.buster_amd64.deb

# copy entrypoint-prod.sh
COPY ./docker/prod/ep.prod.sh $APP_HOME

# execution permissions
RUN ["chmod", "+x", "/home/app/web/ep.prod.sh"]

# copy project
#COPY . $APP_HOME
COPY --chown=app:app . $APP_HOME


# chown all the files to the app user
#RUN chown -R app:app $APP_HOME

# change to the app user
USER app

# run entrypoint.prod.sh
ENTRYPOINT ["/home/app/web/ep.prod.sh"]

I believe that my Dockerfile should have something wrong, but I don’t know exactly what. Anyone can help me?

Edit:
With the answer below, they suggest to run it this way and works fine:

docker exec -it -u 0 [CONTAINER_NAME] python manage.py collectstatic --no-input

Also I found this solution, but I believe that this is not safe, any other suggestion?

chmod a+rwx -R run/

I followed this tutorial: https://testdriven.io/blog/dockerizing-django-with-postgres-gunicorn-and-nginx/

3

Answers


  1. You must add -u 0 to your command for run as root user:

    docker exec -it -u 0 [CONTAINER_NAME] python manage.py collectstatic --no-input
    
    Login or Signup to reply.
  2. I have been stuck for a few hours on this issue. After making sure all the static directory and Django config are in place and proper privileges via shell onto the container. I was with no success.

    After searching for a few hours, came to this document
    which says you need to manually collect static after demonizing the container.

    Commands:

    docker-compose up -d --build
    docker-compose exec <your-web-service> python manage.py collectstatic --no-input --clear
    

    The answer may long be solved but reference to future users, who would be in the same issue.

    Login or Signup to reply.
  3. Had the same issue. To avoid docker-compose exec, you can collect the static files while you’re the root user in the DOCKERFILE. The DOCKERFILE should look like :

    # pull official base image
    FROM python:3.8
    
    # create directory for the app user
    RUN mkdir -p /home/app
    
    # create the app user
    #RUN addgroup -S app && adduser -S app -G app
    RUN adduser --system --group app
    
    # create the appropriate directories
    ENV HOME=/home/app
    ENV APP_HOME=/home/app/web
    RUN mkdir $APP_HOME
    RUN mkdir $APP_HOME/staticfiles
    RUN mkdir $APP_HOME/mediafiles
    WORKDIR $APP_HOME
    
    # Own home directory
    RUN chown -R app:app $HOME
    
    # set environment variables
    ENV PYTHONDONTWRITEBYTECODE 1
    ENV PYTHONUNBUFFERED 1
    
    # install dependencies
    #RUN apk update && apk add libpq
    #COPY --from=builder /usr/src/app/wheels /wheels
    #COPY --from=builder /usr/src/app/requirements.txt .
    #RUN pip install --no-cache /wheels/*
    
    COPY ./requirements.txt $APP_HOME
    RUN pip install --no-cache-dir -r requirements.txt
    
    RUN apt-get clean
    RUN apt-get update
    # Install netcat
    RUN apt install -y netcat
    # Install wkhtml2pdf
    RUN wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.buster_amd64.deb
    RUN DEBIAN_FRONTEND=noninteractive apt install -y -q ./wkhtmltox_0.12.6-1.buster_amd64.deb
    
    # copy entrypoint-prod.sh
    COPY ./docker/prod/ep.prod.sh $APP_HOME
    
    # execution permissions
    RUN ["chmod", "+x", "/home/app/web/ep.prod.sh"]
    
    # copy project
    COPY . $APP_HOME # <<<----- ADDED LINE
    RUN python3 manage.py collectstatic --noinput # <<<----- ADDED LINE
    
    
    # chown all the files to the app user
    #RUN chown -R app:app $APP_HOME
    
    # change to the app user
    USER app
    
    # run entrypoint.prod.sh
    ENTRYPOINT ["/home/app/web/ep.prod.sh"]
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search