diff --git a/.env.example b/.env.example index 4a001ba..9dd71d2 100644 --- a/.env.example +++ b/.env.example @@ -19,6 +19,8 @@ S3_SECRET_KEY=change-me-minio-password S3_BUCKET=ciyuan-viewfinder # Server +SERVER_BASE_IMAGE=python:3.12-slim +SERVER_INTERNAL_PORT=8000 PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple PIP_TRUSTED_HOST=pypi.tuna.tsinghua.edu.cn PIP_DEFAULT_TIMEOUT=120 @@ -34,9 +36,23 @@ LOG_LEVEL=INFO LOG_JSON=false # Frontend build +ADMIN_WEB_NODE_IMAGE=node:20-alpine +ADMIN_WEB_NGINX_IMAGE=nginx:1.27-alpine +ADMIN_WEB_INTERNAL_PORT=80 VITE_API_BASE=/api/v1 +CLIENTS_NODE_IMAGE=node:20-alpine +CLIENTS_NGINX_IMAGE=nginx:1.27-alpine +CLIENTS_INTERNAL_PORT=80 +VITE_CLIENT_H5_API_BASE=/api/v1 +VITE_CLIENT_H5_SERVER_ORIGIN= +VITE_CLIENT_NATIVE_API_BASE=http://10.0.10.11:8000/api/v1 +VITE_CLIENT_NATIVE_SERVER_ORIGIN=http://10.0.10.11:8000 # Nginx host ports NGINX_IMAGE=nginx:1.27-alpine +NGINX_CLIENT_INTERNAL_PORT=80 +NGINX_ADMIN_INTERNAL_PORT=81 +NGINX_SERVER_INTERNAL_PORT=82 CLIENT_WEB_PORT=5173 ADMIN_WEB_PORT=5174 +SERVER_WEB_PORT=8000 diff --git a/admin-web/Dockerfile b/admin-web/Dockerfile index c3b7e13..548b0ce 100644 --- a/admin-web/Dockerfile +++ b/admin-web/Dockerfile @@ -1,4 +1,7 @@ -FROM node:20-alpine AS build +ARG ADMIN_WEB_NODE_IMAGE=node:20-alpine +ARG ADMIN_WEB_NGINX_IMAGE=nginx:1.27-alpine + +FROM ${ADMIN_WEB_NODE_IMAGE} AS build WORKDIR /app @@ -11,7 +14,7 @@ RUN npm ci COPY . . RUN npm run build -FROM nginx:1.27-alpine +FROM ${ADMIN_WEB_NGINX_IMAGE} COPY nginx.conf /etc/nginx/conf.d/default.conf COPY --from=build /app/dist /usr/share/nginx/html diff --git a/clients/Dockerfile b/clients/Dockerfile index 4291d7a..8676509 100644 --- a/clients/Dockerfile +++ b/clients/Dockerfile @@ -1,15 +1,28 @@ -FROM node:20-alpine AS build +ARG CLIENTS_NODE_IMAGE=node:20-alpine +ARG CLIENTS_NGINX_IMAGE=nginx:1.27-alpine + +FROM ${CLIENTS_NODE_IMAGE} AS build WORKDIR /app ENV UNI_INPUT_DIR=/app +ARG VITE_CLIENT_H5_API_BASE=/api/v1 +ARG VITE_CLIENT_H5_SERVER_ORIGIN= +ARG VITE_CLIENT_NATIVE_API_BASE=http://10.0.10.11:8000/api/v1 +ARG VITE_CLIENT_NATIVE_SERVER_ORIGIN=http://10.0.10.11:8000 + +ENV VITE_CLIENT_H5_API_BASE=${VITE_CLIENT_H5_API_BASE} \ + VITE_CLIENT_H5_SERVER_ORIGIN=${VITE_CLIENT_H5_SERVER_ORIGIN} \ + VITE_CLIENT_NATIVE_API_BASE=${VITE_CLIENT_NATIVE_API_BASE} \ + VITE_CLIENT_NATIVE_SERVER_ORIGIN=${VITE_CLIENT_NATIVE_SERVER_ORIGIN} + COPY package.json package-lock.json* ./ RUN npm install --legacy-peer-deps COPY . . RUN npm run build:h5 -FROM nginx:1.27-alpine +FROM ${CLIENTS_NGINX_IMAGE} COPY nginx.conf /etc/nginx/conf.d/default.conf COPY --from=build /app/dist/build/h5 /usr/share/nginx/html diff --git a/clients/utils/config.js b/clients/utils/config.js index e9c1f14..aaa3060 100644 --- a/clients/utils/config.js +++ b/clients/utils/config.js @@ -1,11 +1,14 @@ // #ifdef H5 -const API_BASE = "/api/v1"; -const SERVER_ORIGIN = window.location.origin; +const API_BASE = import.meta.env.VITE_CLIENT_H5_API_BASE || "/api/v1"; +const SERVER_ORIGIN = + import.meta.env.VITE_CLIENT_H5_SERVER_ORIGIN || window.location.origin; // #endif // #ifndef H5 -const API_BASE = "http://10.0.10.11:8000/api/v1"; -const SERVER_ORIGIN = "http://10.0.10.11:8000"; +const API_BASE = + import.meta.env.VITE_CLIENT_NATIVE_API_BASE || "http://10.0.10.11:8000/api/v1"; +const SERVER_ORIGIN = + import.meta.env.VITE_CLIENT_NATIVE_SERVER_ORIGIN || "http://10.0.10.11:8000"; // #endif export { API_BASE, SERVER_ORIGIN }; diff --git a/docker-compose.yml b/docker-compose.yml index b4ab8d3..6c0b994 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -60,11 +60,14 @@ services: build: context: ./server args: + SERVER_BASE_IMAGE: "${SERVER_BASE_IMAGE}" PIP_INDEX_URL: "${PIP_INDEX_URL}" PIP_TRUSTED_HOST: "${PIP_TRUSTED_HOST}" PIP_DEFAULT_TIMEOUT: "${PIP_DEFAULT_TIMEOUT}" + SERVER_INTERNAL_PORT: "${SERVER_INTERNAL_PORT}" container_name: ciyuan-server environment: + SERVER_INTERNAL_PORT: "${SERVER_INTERNAL_PORT}" DATABASE_URL: "${DATABASE_URL}" DATABASE_URL_SYNC: "${DATABASE_URL_SYNC}" REDIS_URL: "${REDIS_URL}" @@ -81,7 +84,7 @@ services: LOG_LEVEL: "${LOG_LEVEL}" LOG_JSON: "${LOG_JSON}" expose: - - "8000" + - "${SERVER_INTERNAL_PORT}" volumes: - server_uploads:/app/uploads depends_on: @@ -97,7 +100,7 @@ services: "CMD", "python", "-c", - "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/', timeout=5)", + "import urllib.request; urllib.request.urlopen('http://127.0.0.1:${SERVER_INTERNAL_PORT}/', timeout=5)", ] interval: 15s timeout: 10s @@ -111,10 +114,12 @@ services: build: context: ./admin-web args: + ADMIN_WEB_NODE_IMAGE: "${ADMIN_WEB_NODE_IMAGE}" + ADMIN_WEB_NGINX_IMAGE: "${ADMIN_WEB_NGINX_IMAGE}" VITE_API_BASE: "${VITE_API_BASE}" container_name: ciyuan-admin-web expose: - - "80" + - "${ADMIN_WEB_INTERNAL_PORT}" depends_on: server: condition: service_healthy @@ -125,9 +130,16 @@ services: clients: build: context: ./clients + args: + CLIENTS_NODE_IMAGE: "${CLIENTS_NODE_IMAGE}" + CLIENTS_NGINX_IMAGE: "${CLIENTS_NGINX_IMAGE}" + VITE_CLIENT_H5_API_BASE: "${VITE_CLIENT_H5_API_BASE}" + VITE_CLIENT_H5_SERVER_ORIGIN: "${VITE_CLIENT_H5_SERVER_ORIGIN}" + VITE_CLIENT_NATIVE_API_BASE: "${VITE_CLIENT_NATIVE_API_BASE}" + VITE_CLIENT_NATIVE_SERVER_ORIGIN: "${VITE_CLIENT_NATIVE_SERVER_ORIGIN}" container_name: ciyuan-clients expose: - - "80" + - "${CLIENTS_INTERNAL_PORT}" depends_on: server: condition: service_healthy @@ -138,11 +150,19 @@ services: nginx: image: "${NGINX_IMAGE}" container_name: ciyuan-nginx + environment: + NGINX_CLIENT_INTERNAL_PORT: "${NGINX_CLIENT_INTERNAL_PORT}" + NGINX_ADMIN_INTERNAL_PORT: "${NGINX_ADMIN_INTERNAL_PORT}" + NGINX_SERVER_INTERNAL_PORT: "${NGINX_SERVER_INTERNAL_PORT}" + SERVER_INTERNAL_PORT: "${SERVER_INTERNAL_PORT}" + CLIENTS_INTERNAL_PORT: "${CLIENTS_INTERNAL_PORT}" + ADMIN_WEB_INTERNAL_PORT: "${ADMIN_WEB_INTERNAL_PORT}" ports: - - "${CLIENT_WEB_PORT}:80" - - "${ADMIN_WEB_PORT}:81" + - "${CLIENT_WEB_PORT}:${NGINX_CLIENT_INTERNAL_PORT}" + - "${ADMIN_WEB_PORT}:${NGINX_ADMIN_INTERNAL_PORT}" + - "${SERVER_WEB_PORT}:${NGINX_SERVER_INTERNAL_PORT}" volumes: - - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro + - ./docker/nginx/default.conf:/etc/nginx/templates/default.conf.template:ro depends_on: server: condition: service_healthy diff --git a/docker/nginx/default.conf b/docker/nginx/default.conf index ab266af..6eff4a9 100644 --- a/docker/nginx/default.conf +++ b/docker/nginx/default.conf @@ -1,9 +1,9 @@ server { - listen 80; + listen ${NGINX_CLIENT_INTERNAL_PORT}; server_name _; location /api/ { - proxy_pass http://server:8000/api/; + proxy_pass http://server:${SERVER_INTERNAL_PORT}/api/; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; @@ -12,13 +12,13 @@ server { } location /uploads/ { - proxy_pass http://server:8000/uploads/; + proxy_pass http://server:${SERVER_INTERNAL_PORT}/uploads/; proxy_http_version 1.1; proxy_set_header Host $host; } location = /docs { - proxy_pass http://server:8000/docs; + proxy_pass http://server:${SERVER_INTERNAL_PORT}/docs; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; @@ -27,7 +27,7 @@ server { } location = /redoc { - proxy_pass http://server:8000/redoc; + proxy_pass http://server:${SERVER_INTERNAL_PORT}/redoc; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; @@ -36,7 +36,7 @@ server { } location = /openapi.json { - proxy_pass http://server:8000/openapi.json; + proxy_pass http://server:${SERVER_INTERNAL_PORT}/openapi.json; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; @@ -45,7 +45,7 @@ server { } location / { - proxy_pass http://clients:80; + proxy_pass http://clients:${CLIENTS_INTERNAL_PORT}; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; @@ -55,11 +55,11 @@ server { } server { - listen 81; + listen ${NGINX_ADMIN_INTERNAL_PORT}; server_name _; location /api/ { - proxy_pass http://server:8000/api/; + proxy_pass http://server:${SERVER_INTERNAL_PORT}/api/; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; @@ -68,13 +68,13 @@ server { } location /uploads/ { - proxy_pass http://server:8000/uploads/; + proxy_pass http://server:${SERVER_INTERNAL_PORT}/uploads/; proxy_http_version 1.1; proxy_set_header Host $host; } location = /docs { - proxy_pass http://server:8000/docs; + proxy_pass http://server:${SERVER_INTERNAL_PORT}/docs; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; @@ -83,7 +83,7 @@ server { } location = /redoc { - proxy_pass http://server:8000/redoc; + proxy_pass http://server:${SERVER_INTERNAL_PORT}/redoc; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; @@ -92,7 +92,7 @@ server { } location = /openapi.json { - proxy_pass http://server:8000/openapi.json; + proxy_pass http://server:${SERVER_INTERNAL_PORT}/openapi.json; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; @@ -101,7 +101,21 @@ server { } location / { - proxy_pass http://admin-web:80; + proxy_pass http://admin-web:${ADMIN_WEB_INTERNAL_PORT}; + proxy_http_version 1.1; + 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; + } +} + +server { + listen ${NGINX_SERVER_INTERNAL_PORT}; + server_name _; + + location / { + proxy_pass http://server:${SERVER_INTERNAL_PORT}; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; diff --git a/server/Dockerfile b/server/Dockerfile index 9d0d9ed..30bb2c3 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -1,4 +1,5 @@ -FROM python:3.12-slim +ARG SERVER_BASE_IMAGE=python:3.12-slim +FROM ${SERVER_BASE_IMAGE} ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ @@ -7,10 +8,12 @@ ENV PYTHONDONTWRITEBYTECODE=1 \ ARG PIP_INDEX_URL ARG PIP_TRUSTED_HOST ARG PIP_DEFAULT_TIMEOUT=120 +ARG SERVER_INTERNAL_PORT=8000 ENV PIP_INDEX_URL=${PIP_INDEX_URL} \ PIP_TRUSTED_HOST=${PIP_TRUSTED_HOST} \ - PIP_DEFAULT_TIMEOUT=${PIP_DEFAULT_TIMEOUT} + PIP_DEFAULT_TIMEOUT=${PIP_DEFAULT_TIMEOUT} \ + SERVER_INTERNAL_PORT=${SERVER_INTERNAL_PORT} WORKDIR /app @@ -19,6 +22,6 @@ RUN pip install -r requirements.txt COPY . . -EXPOSE 8000 +EXPOSE ${SERVER_INTERNAL_PORT} -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] +CMD ["sh", "-c", "uvicorn app.main:app --host 0.0.0.0 --port ${SERVER_INTERNAL_PORT}"]