React, Django. Gunicorn, nginx, docker setup for production ready and not ablet to server static files for both frontend and backend
Это текущий директор моего проекта на данный момент
Project/
│── .env
├── docker-compose.yml # Docker Compose configuration file
│
├── Frontend/ # React Frontend (Client-side)
│ ├── Dockerfile # Dockerfile for React app build
│ ├── package.json # React package file
│ ├── public/ # Public assets for React
│ ├── src/ # React source code
│ ├── build/ # React build output (this is where `npm run build`
│ ├── nginx.conf
└── Backend/ # Django Backend (Server-side)
├── Dockerfile # Dockerfile for Django app build
├── manage.py # Django manage.py file
├── Backend/ # Django application code (models, views, etc.)
├── requirements.txt
├── static/ # Static files (collected by `collectstatic`)
├── media/ # Media files (user-uploaded files)
└── .dockerignore # Docker ignore file
У меня есть такая структура каталогов, где у меня есть 2 папки для backend и front end, в каждой из которых собраны Django и react соответственно, и у меня есть файл nginx в директории frontend, чтобы скопировать первую сборку в контейнер frontend, но дело в том, что я также разделяю тот же том с django, но nginx не ablet для сервера sttic файлов в django, а также получить 404 не найдена ошибка с nginx, поскольку файлы не в контейнерах, но они смонтированы с томами папки backend.
Ниже приведен yml-файл, который я использую, чтобы использовать общий том с бэкендом и сборку react
version: "3.8"
services:
st_mysql_db:
image: mysql:8.0
container_name: st_mysql_db
env_file:
- .env
environment:
MYSQL_ROOT_PASSWORD: '${MYSQL_DB_ROOT_PASSWORD}'
MYSQL_DATABASE: '${MYSQL_DATABASE_NAME}'
volumes:
- st_mysql_data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- st_network
restart: always
healthcheck:
test: [
"CMD",
"mysqladmin", "ping",
"-h", "localhost",
"-u", "root",
"-p${MYSQL_DB_ROOT_PASSWORD}",
"--silent"
]
interval: 10s
retries: 5
start_period: 30s
timeout: 5s
command: ["docker-entrypoint.sh", "mysqld"]
st_backend:
build:
context: ./Backend
dockerfile: Dockerfile
container_name: st_backend
volumes:
- ./Backend:/app
- ./Backend/media:/app/media
- ./Backend/static:/app/static
env_file:
- .env
#environment:
#- DATABASE_URL=mysql://root:${MYSQL_DB_ROOT_PASSWORD}@steno_mysql_db:3306/st_db
ports:
- "8000:8000"
depends_on:
- st_mysql_db
networks:
- st_network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/admin/"]
interval: 10s
retries: 5
start_period: 30s
timeout: 5s
command: >
bash -c "
/wait-for-it.sh st_mysql_db:3306 --timeout=60 -- \
# Run makemigrations for the accounts app first
python manage.py makemigrations accounts && \
# Run migrations for any other apps
python manage.py migrate --noinput && \
# Run migrations for any other apps
python manage.py collectstatic --noinput && \
# Start the gunicorn server
gunicorn --bind 0.0.0.0:8000 Backend.wsgi:application"
restart: always
stfrontend:
build:
context: ./Frontend
dockerfile: Dockerfile
container_name: st_frontend
env_file:
- .env
depends_on:
- st_backend
networks:
- st_network
volumes:
- ./Backend/static:/usr/share/nginx/html/static # Map Django static files to NGINX
- ./Backend/media:/usr/share/nginx/html/media # Map Django media files to NGINX
restart: always
ports:
- "80:80" # NGINX will serve frontend on port 80
command: ["nginx", "-g", "daemon off;"] # Directly run NGINX in the container
networks:
st_network:
driver: bridge
volumes:
st_mysql_data:
st_backend_data:
Это файл докера для фронтэнда и бэкэнда
frontend
# Stage 1: Build the React app
FROM node:14-slim AS builder
WORKDIR /app
# Copy package.json and package-lock.json
COPY package.json package-lock.json ./
# Install dependencies
RUN npm install
# Copy all files to the working directory
COPY . .
# Build the React app for production
RUN npm run build
# Stage 2: Serve the React app with NGINX
FROM nginx:alpine
# Copy custom NGINX configuration file from the parent directory
COPY ./nginx.conf /etc/nginx/nginx.conf
# Copy the React build output to NGINX's HTML directory
COPY --from=builder /app/build /usr/share/nginx/html
# Set the correct permissions for NGINX to access files
RUN chown -R nginx:nginx /usr/share/nginx/html
RUN chmod -R 755 /usr/share/nginx/html
# Set the correct ownership for other NGINX critical files
RUN chown -R nginx:nginx /var/cache/nginx /var/log/nginx /etc/nginx/conf.d
# Ensure that NGINX serves the index.html file
# In the NGINX configuration file, the directory index needs to be set correctly.
# The default NGINX configuration should already include this, but we can enforce it.
RUN echo 'server { listen 80; location / { root /usr/share/nginx/html; index index.html index.htm; } }' > /etc/nginx/conf.d/default.conf
# Expose port 80
EXPOSE 80
это файл docker для backend
# Stage 1: Build stage using a full Python image
FROM python:3.9 as builder
# Set the working directory in the container
WORKDIR /app
# Copy the requirements file into the container
COPY requirements.txt ./
# Install dependencies and set up virtual environment
RUN apt-get update && apt-get install -y libmariadb-dev curl bash \
&& python -m venv /opt/venv \
&& /opt/venv/bin/pip install --no-cache-dir -r requirements.txt
# Stage 2: Final slim image
FROM python:3.9-slim
# Install dependencies needed for mysqlclient, bash, and curl
RUN apt-get update && apt-get install -y libmariadb-dev curl bash
# Set the working directory in the container
WORKDIR /app
# Copy the virtual environment from the builder stage
COPY --from=builder /opt/venv /opt/venv
# Copy the application code into the container
COPY . .
# Download the wait-for-it.sh script directly from GitHub
RUN curl -sSL https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh -o /wait-for-it.sh && chmod +x /wait-for-it.sh
# Ensure the PATH includes the virtual environment
ENV PATH="/opt/venv/bin:$PATH"
# Expose the application port (adjust as necessary)
EXPOSE 8000
# Command to run the server with wait-for-it.sh to ensure DB is ready
#CMD ["/wait-for-it.sh", "steno_mysql_db:3306", "--timeout=60", "--", "bash", "-c", "python manage.py makemigrations && python manage.py migrate && gunicorn --bind 0.0.0.0:8000 app.wsgi:application"]
и это конфигурация для nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
# Main NGINX configuration block
http {
# Include any additional configurations (if needed)
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Log configuration
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# Server block for handling HTTP requests
server {
listen 80;
server_name localhost; # This will match any domain, acting as a catch-all
# These directives should be outside the location block
root /usr/share/nginx/html; # Define the root directory for all requests
index index.html;
# Frontend
location / {
try_files $uri /index.html; # Rewrites any missing route to index.html
}
location /static/ {
alias /usr/share/nginx/html/static/;
autoindex on;
}
# Serve media files for Django (if you use them)
location /media/ {
alias /usr/share/nginx/html/media/; # Serve media files from shared volume
autoindex on;
}
# Backend API
location /api/ {
proxy_pass http://steno_backend:8000/; # Proxy to Django backend
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Serve static files for Django from the shared volume
}
}
вот мой файл настроек для медиа и статики, когда отладка равна False
STATIC_URL = 'static/'
STATIC_ROOT=os.path.join(BASE_DIR,'static')
# Media files (uploads)
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
При такой конфигурации я хочу сделать то, что когда я делаю сбор статического в контейнере backend, то файлы хранятся в каталоге, но так как объем общий, то nginx не может обслуживать эти файлы, а также не может обслуживать даже файлы react, которые находятся в папке html nginx. и еще одна вещь, когда я делаю миграцию и миграцию, я использую модель customuser и я добавил ссылку в файл настроек, но когда я напрямую использую
python manage.py make migrations
он показывает, что все в порядке, а затем мигрировать он показывает не в состоянии ссылаться на вещи, так что это идет не так, так что из-за этого я должен сделать отдельные миграции для учетных записей, а затем мигрировать, чтобы применить все другие миграции. как я могу решить эту проблему, когда я должен использовать R2 Service от Cloudflare и rds от aws так что, пожалуйста, помогите мне с этим .
Если вы обнаружите какую-либо проблему с yml или любой конфигурацией, пожалуйста, укажите на нее для лучшего использования, а также предложите готовую к производству установку для вышеуказанных конфигураций.