I wan to deploy the Django API+React+Django admin in one Google cloud run service with multiple containers, but when I do that, the django api and react frontend works ok, but I can not open django admin platform.
First I will introduce my project structure:
Frontend: React+ViteJS
Backend: Django-ninja for the api stuff
Admin Platform: Django original admin framework
Custom Domain: Google Firebase host (integrate with google cloud run), for example: the website is (URL Removed by Staff)
Right now I use the Google Cloud Run multicontainer service to deploy the whole project.
For the frontend docker Dockerfile:
FROM node:20-slim as build WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build # Use Nginx as the production server FROM nginx:alpine COPY nginx.conf /etc/nginx/conf.d/default.conf # Copy the built React app to Nginx's web server directory COPY --from=build /app/dist /usr/share/nginx/html # Expose port 80 for the Nginx server EXPOSE 8000 # Start Nginx when the container runs CMD ["nginx", "-g", "daemon off;"]
This is the nginx.conf:
server { listen 8000; # listen [::]:80; # server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location /admin/ { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } }
For the backend Dockerfile:
FROM python:3.11-buster RUN apt-get update && apt-get install -y cmake RUN pip install poetry==1.8.2 ENV POETRY_NO_INTERACTION=1 \ POETRY_VIRTUALENVS_IN_PROJECT=1 \ POETRY_VIRTUALENVS_CREATE=1 \ POETRY_CACHE_DIR=/tmp/poetry_cache ENV PORT 8080 WORKDIR /app COPY . . RUN poetry install --no-root EXPOSE 8080 CMD poetry run gunicorn mysite.wsgi:application --bind :$PORT --timeout 1000 --workers 1 --threads 8
For the django-ninja settings, the important part is here:(just follow the google tutorial)
# env setup env = environ.Env(DEBUG=(bool, False)) env_file = os.path.join(BASE_DIR, ".env") # Attempt to load the Project ID into the environment, safely failing on error. try: _, os.environ["GOOGLE_CLOUD_PROJECT"] = google.auth.default() except google.auth.exceptions.DefaultCredentialsError: pass if os.path.isfile(env_file): # Use a local secret file, if provided in local env.read_env(env_file) elif os.environ.get("GOOGLE_CLOUD_PROJECT", None): # Pull secrets from Secret Manager project_id = os.environ.get("GOOGLE_CLOUD_PROJECT") client = secretmanager.SecretManagerServiceClient() settings_name = os.environ.get("SETTINGS_NAME", "ps_plugin_settings") name = f"projects/{project_id}/secrets/{settings_name}/versions/latest" payload = client.access_secret_version(name=name).payload.data.decode("UTF-8") env.read_env(io.StringIO(payload)) else: raise Exception("No local .env or GOOGLE_CLOUD_PROJECT detected. No secrets found.") SECRET_KEY = env("SECRET_KEY") BASE_API_URL = env("BASE_API_URL") BASE_APP_URL = env("BASE_APP_URL") GOOGLE_OAUTH2_CLIENT_ID = env("GOOGLE_OAUTH2_CLIENT_ID") GOOGLE_OAUTH2_CLIENT_SECRET = env("GOOGLE_OAUTH2_CLIENT_SECRET") DEBUG = env("DEBUG") # [START cloudrun_django_csrf] # SECURITY WARNING: It's recommended that you use this when # running in production. The URL will be known once you first deploy # to Cloud Run. This code takes the URL and converts it to both these settings formats. CLOUDRUN_SERVICE_URL = env("CLOUDRUN_SERVICE_URL", default=None) if CLOUDRUN_SERVICE_URL: ALLOWED_HOSTS = [ urlparse(CLOUDRUN_SERVICE_URL).netloc, urlparse(BASE_API_URL).netloc, urlparse(BASE_APP_URL).netloc, ] CSRF_TRUSTED_ORIGINS = [CLOUDRUN_SERVICE_URL, BASE_API_URL, BASE_APP_URL] SECURE_SSL_REDIRECT = True SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") # for the custom domain cookie and session in order to login successfully # CSRF_COOKIE_DOMAIN = urlparse(BASE_APP_URL).netloc # SESSION_COOKIE_DOMAIN = urlparse(BASE_APP_URL).netloc else: ALLOWED_HOSTS = ["*"] # [END cloudrun_django_csrf]
Besides I also setup the google cloud storage, and execute the collectstatic command. So the admin platform static files have been already in the google storage for the public.
After these 2 containers were deployed, I found that the frontend and backend works find, I can open the website (URL Removed by Staff) works well.
But the django admin platform does not work, when I open (URL Removed by Staff), I can not open it. But I have already set the proxy for /admin router in the Nginx.
I also tried another thing, I deploy a totally new google cloud run service, it is just one container, just deploy the django project, no frontend, no nginx, now I can open the django admin platform with the cloud run website, like (URL Removed by Staff), but if I open the custom firebase domain, like (URL Removed by Staff), after I input the right username and password, it redirect the login page again. 🤣 I have already add the (URL Removed by Staff) into the CSRF_TRUSTED_ORIGINS
Someone help me, please.