feat:支持纯离线部署
This commit is contained in:
@@ -6,5 +6,4 @@ RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
|
|||||||
FROM python:3.13-slim-bookworm
|
FROM python:3.13-slim-bookworm
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=builder /install /usr/local
|
COPY --from=builder /install /usr/local
|
||||||
COPY app/ ./app/
|
|
||||||
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "7000", "--workers", "4"]
|
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "7000", "--workers", "4"]
|
||||||
|
|||||||
82
README.md
82
README.md
@@ -195,7 +195,80 @@ If you prefer the repository root entrypoint, `uv run main.py` now starts the sa
|
|||||||
## Dependency Management
|
## Dependency Management
|
||||||
|
|
||||||
- Local Python development uses `uv` via [`pyproject.toml`](/d:/project/sentinel/pyproject.toml).
|
- Local Python development uses `uv` via [`pyproject.toml`](/d:/project/sentinel/pyproject.toml).
|
||||||
- Container builds still use [`requirements.txt`](/d:/project/sentinel/requirements.txt) because the Dockerfile is intentionally minimal and matches the delivery requirements.
|
- The container runtime image uses [`requirements.txt`](/d:/project/sentinel/requirements.txt) and intentionally installs only Python dependencies.
|
||||||
|
- Application source code is mounted by Compose at runtime, so the offline host does not need to rebuild the image just to load the current backend code.
|
||||||
|
|
||||||
|
## Offline Deployment Model
|
||||||
|
|
||||||
|
If your production machine has no internet access, the current repository should be used in this way:
|
||||||
|
|
||||||
|
1. Build the `key-ip-sentinel:latest` image on a machine with internet access.
|
||||||
|
2. Export that image as a tar archive.
|
||||||
|
3. Import the archive on the offline machine.
|
||||||
|
4. Place the repository files on the offline machine.
|
||||||
|
5. Start the stack with `docker compose up -d`, not `docker compose up --build -d`.
|
||||||
|
|
||||||
|
This works because:
|
||||||
|
|
||||||
|
- `Dockerfile` installs only Python dependencies into the image.
|
||||||
|
- `docker-compose.yml` mounts `./app` into the running `sentinel-app` container.
|
||||||
|
- The offline machine only needs the prebuilt image plus the repository files.
|
||||||
|
|
||||||
|
Important limitation:
|
||||||
|
|
||||||
|
- If you change Python dependencies in `requirements.txt`, you must rebuild and re-export the image on a connected machine.
|
||||||
|
- If you only change backend application code under `app/`, you do not need to rebuild the image; restarting the container is enough.
|
||||||
|
- `frontend/dist` must already exist before deployment, because Nginx serves the built frontend directly from the repository.
|
||||||
|
- The base images used by this stack, such as `nginx:alpine`, `redis:7-alpine`, and `postgres:16`, must also be available on the offline host in advance.
|
||||||
|
|
||||||
|
### Prepare images on a connected machine
|
||||||
|
|
||||||
|
Build and export the Sentinel runtime image:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -t key-ip-sentinel:latest .
|
||||||
|
docker save -o key-ip-sentinel-latest.tar key-ip-sentinel:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
Also export the public images used by Compose if the offline machine cannot pull them:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker pull nginx:alpine
|
||||||
|
docker pull redis:7-alpine
|
||||||
|
docker pull postgres:16
|
||||||
|
|
||||||
|
docker save -o sentinel-support-images.tar nginx:alpine redis:7-alpine postgres:16
|
||||||
|
```
|
||||||
|
|
||||||
|
If the admin frontend is not already built, build it on the connected machine too:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd frontend
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
cd ..
|
||||||
|
```
|
||||||
|
|
||||||
|
Then copy these items to the offline machine:
|
||||||
|
|
||||||
|
- the full repository working tree
|
||||||
|
- `key-ip-sentinel-latest.tar`
|
||||||
|
- `sentinel-support-images.tar` if needed
|
||||||
|
|
||||||
|
### Import images on the offline machine
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker load -i key-ip-sentinel-latest.tar
|
||||||
|
docker load -i sentinel-support-images.tar
|
||||||
|
```
|
||||||
|
|
||||||
|
### Start on the offline machine
|
||||||
|
|
||||||
|
After `.env`, `frontend/dist`, and `shared_network` are ready:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
## Production Deployment
|
## Production Deployment
|
||||||
|
|
||||||
@@ -278,17 +351,22 @@ cd ..
|
|||||||
|
|
||||||
This produces `frontend/dist`, which Nginx serves at `/admin/ui/`.
|
This produces `frontend/dist`, which Nginx serves at `/admin/ui/`.
|
||||||
|
|
||||||
|
If the target host is offline, do this on a connected machine first and copy the resulting `frontend/dist` directory with the repository.
|
||||||
|
|
||||||
### 5. Confirm Sentinel compose prerequisites
|
### 5. Confirm Sentinel compose prerequisites
|
||||||
|
|
||||||
- Build the frontend first. If `frontend/dist` is missing, `/admin/ui/` cannot be served by Nginx.
|
- Build the frontend first. If `frontend/dist` is missing, `/admin/ui/` cannot be served by Nginx.
|
||||||
- Ensure the external Docker network `shared_network` already exists before starting Sentinel.
|
- Ensure the external Docker network `shared_network` already exists before starting Sentinel.
|
||||||
|
- Ensure `key-ip-sentinel:latest`, `nginx:alpine`, `redis:7-alpine`, and `postgres:16` are already present on the host if the host cannot access the internet.
|
||||||
|
|
||||||
### 6. Start the Sentinel stack
|
### 6. Start the Sentinel stack
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose up --build -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Use `docker compose up --build -d` only on a connected machine where rebuilding the Sentinel image is actually intended.
|
||||||
|
|
||||||
Services:
|
Services:
|
||||||
|
|
||||||
- `http://<host>/` forwards model API traffic through Sentinel.
|
- `http://<host>/` forwards model API traffic through Sentinel.
|
||||||
|
|||||||
@@ -14,14 +14,13 @@ services:
|
|||||||
- sentinel-net
|
- sentinel-net
|
||||||
|
|
||||||
sentinel-app:
|
sentinel-app:
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
image: key-ip-sentinel:latest
|
image: key-ip-sentinel:latest
|
||||||
container_name: sentinel-app
|
container_name: sentinel-app
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
|
volumes:
|
||||||
|
- ./app:/app/app:ro
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis
|
- redis
|
||||||
- postgres
|
- postgres
|
||||||
|
|||||||
Reference in New Issue
Block a user