添加docker部署代码

This commit is contained in:
龙澳
2026-02-25 09:28:37 +08:00
parent 9c9f968d5a
commit 5d2785eea7
5 changed files with 209 additions and 0 deletions

35
.dockerignore Normal file
View File

@@ -0,0 +1,35 @@
# Git
.git
.gitignore
# Python
__pycache__
*.py[cod]
*$py.class
*.so
.Python
build/
dist/
*.egg-info/
# IDE
.vscode
.claude
# Environment
.venv
venv/
.env
# Documentation
README.md
CLAUDE.md
# Docker
Dockerfile
docker-compose.yml
.dockerignore
# UV
.python-version
uv.lock

126
CLAUDE.md Normal file
View File

@@ -0,0 +1,126 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
This is a collection of FastAPI-based tile servers that use rio-tiler to serve COG (Cloud Optimized GeoTIFF) files as dynamic map tiles. The project serves imagery from different planetary bodies:
- **app.py** - NJ 2020 aerial imagery (I7D16.tif) - UInt16 data with per-band rescaling
- **app_world.py** - Natural Earth global basemap (HYP_HR_SR_OB_DR_cog.tif) - uint8 RGB
- **app_mars.py** - Mars MGS MOLA global basemap - Uses custom Mars CRS in equidistant cylindrical projection
## Running the Servers
Each app is an independent FastAPI application. Run with uvicorn:
```bash
# Run NJ imagery server (default port 8000)
uvicorn app:app --reload
# Run world basemap server
uvicorn app_world:app --port 8001 --reload
# Run Mars basemap server
uvicorn app_mars:app --port 8002 --reload
```
## Architecture
### Common Pattern (app.py, app_world.py)
All apps follow the same pattern using `rio_tiler.io.Reader`:
1. **Tile endpoint** (`/tiles/{z}/{x}/{y}.png`) - Reads COG tiles and returns PNG
2. **TileJSON endpoint** (`/tilejson.json`) - Returns TileJSON 2.2.0 metadata
3. **Optional viewer** (`/`) - app.py includes a Leaflet.js viewer
Key rio-tiler concepts:
- `Reader(DATA_PATH)` context manager for reading COGs
- `cog.tile(x, y, z)` to extract tiles
- `img.render()` with `img_profiles` for output formatting
- `cog.get_geographic_bounds()` for bounds in geographic CRS
- `cog.minzoom`/`cog.maxzoom` for zoom levels
### Mars CRS (app_mars.py)
The Mars server uses a **custom TileMatrixSet** to handle Mars-specific coordinate system:
- **CRS**: Simple Cylindrical Mars (equidistant cylindrical, meters)
- **Sphere radius**: 3,396,190 m (vs Earth's ~6,378,137 m)
- **Extent**: ±πR in x, ±πR/2 in y (calculated from Mars radius)
- **matrix_scale=[2, 1]**: 2×1 tiles at zoom 0, matching Cesium's GeographicTilingScheme
**Critical design decision**: TMS and TIF both use the same Mars CRS (eqc meters). Avoid using longlat (degrees) because PROJ would attempt datum transformation through WGS84, causing "PROJ: eqc: Invalid latitude" errors due to the large sphere radius difference.
```python
MARS_CRS = CRS.from_proj4(
"+proj=eqc +lat_ts=0 +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +a=3396190 +b=3396190 +units=m +no_defs"
)
MARS_TMS = TileMatrixSet.custom(
crs=MARS_CRS,
extent=(-_MAX_X, -_MAX_Y, _MAX_X, _MAX_Y),
matrix_scale=[2, 1],
)
```
Pass custom TMS to Reader: `Reader(DATA_PATH, tms=MARS_TMS)`
## Data Handling
### Rescaling (app.py)
For UInt16 imagery, use per-band rescaling based on p2/p98 statistics:
```python
RESCALE = [
(6130, 40453), # Red
(10641, 41211), # Green
(12482, 36323), # Blue
]
img.render(img_format="PNG", rescale=RESCALE, **img_profiles.get("png", {}))
```
### uint8 Data (app_world.py, app_mars.py)
No rescaling needed for pre-scaled uint8 imagery:
```python
img.render(img_format="PNG", **img_profiles.get("png", {}))
```
## Dependencies
Managed via uv with `pyproject.toml`:
- fastapi - Web framework
- rio-tiler - COG tiling engine
- rasterio - GeoTIFF I/O
- uvicorn - ASGI server
- pyproj, morecantile - CRS and TMS handling (for Mars app)
## Adding New Tile Servers
To add a new COG tile server:
1. Copy the appropriate template (app.py for UInt16, app_world.py/app_mars.py for uint8)
2. Update `DATA_PATH` to point to your COG file in `data/`
3. For non-Earth data, create a custom CRS/TMS following app_mars.py pattern
4. Adjust rescaling if needed for UInt16 data
5. Update app metadata (title, description)
6. Run with uvicorn on a unique port
## File Structure
```
data/ # COG files (gitignored)
├── I7D16.tif
├── HYP_HR_SR_OB_DR_cog.tif
└── Mars_MGS_MOLA_...tif
app.py # NJ imagery server
app_world.py # World basemap server
app_mars.py # Mars basemap server
pyproject.toml # uv dependencies
```

26
Dockerfile Normal file
View File

@@ -0,0 +1,26 @@
FROM python:3.12-slim
WORKDIR /app
RUN apt-get update && apt-get install -y \
gcc \
libssl-dev \
libffi-dev \
curl \
libexpat1 \
gdal-bin \
libgdal-dev \
&& rm -rf /var/lib/apt/lists/*
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
COPY pyproject.toml ./
COPY app_mars.py ./
RUN uv pip install --system -e .
RUN mkdir -p /app/data
EXPOSE 8002
CMD ["uv", "run", "uvicorn", "app_mars:app", "--host", "0.0.0.0", "--port", "8000"]

View File

@@ -1,2 +1,9 @@
# rio-tiler-tms
## 手动构建镜像
sudo docker build -t rio-tiler-mars:latest .
## 启动服务
sudo docker compose up -d

15
docker-compose.yml Normal file
View File

@@ -0,0 +1,15 @@
services:
mars:
image: rio-tiler-mars:latest
container_name: rio-tiler-mars
ports:
- "8002:8000"
volumes:
- ./data:/app/data:ro
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8002/tilejson.json"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s