Skip to content

Commit 88f43c8

Browse files
authored
Merge pull request #223 from UW-Macrostrat/legacy-tileserver-update
Legacy tileserver update
2 parents 0dc7db9 + b231013 commit 88f43c8

File tree

9 files changed

+152
-124
lines changed

9 files changed

+152
-124
lines changed

.idea/data_source_mapping.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

local-root/Caddyfile

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ localhost, macrostrat.local {
113113
}
114114

115115
handle_path /tiles/* {
116-
reverse_proxy tileserver:8000 {
116+
reverse_proxy tileserver_cache:8000 {
117117
header_down -Access-Control-Allow-Origin
118118
header_down -Access-Control-Allow-Credentials
119119
header_down -Access-Control-Allow-Methods
@@ -148,3 +148,21 @@ storage-ui.macrostrat.local {
148148
tls internal
149149
reverse_proxy storage:9001
150150
}
151+
152+
tiles.macrostrat.local {
153+
tls internal
154+
reverse_proxy tileserver_cache:8000 {
155+
header_down -Access-Control-Allow-Origin
156+
header_down -Access-Control-Allow-Credentials
157+
header_down -Access-Control-Allow-Methods
158+
}
159+
160+
# Local CORS headers
161+
162+
header {
163+
Access-Control-Allow-Origin *
164+
Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS"
165+
}
166+
167+
168+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
vcl 4.1;
2+
3+
backend backend-core {
4+
.host = "tileserver_core";
5+
.port = "8000";
6+
}
7+
8+
9+
backend backend-legacy {
10+
.host = "tileserver_legacy";
11+
.port = "8000";
12+
# Don't require the connection to be up at the start
13+
}
14+
15+
16+
# Bypass Varnish if tile has a cache=bypass query parameter
17+
sub vcl_recv {
18+
# Set the backend hints to route to the correct upstream
19+
# For now the index.html route is served from the legacy tileserver
20+
if (req.url ~ "^/$" || req.url ~ "^/preview$") {
21+
set req.backend_hint = backend-legacy;
22+
} else if (req.url ~ ".*\.(png|mvt)$") {
23+
# Png and mvt tiles are served from the legacy tileserver
24+
set req.backend_hint = backend-legacy;
25+
} else {
26+
# Everything else is served from the core tileserver
27+
set req.backend_hint = backend-core;
28+
# TODO: could add a v3 prefix here if needed
29+
}
30+
31+
# Bypass the cache for zoom levels greater than 14
32+
if (req.url ~ ".*\/([0-9][56789]|[0-9]{3,})\/[0-9]+\/[0-9]+(\.png|\.mvt)?") {
33+
set req.http.X-Cache = "bypass";
34+
return (pass);
35+
}
36+
37+
38+
if (req.url ~ ".*cache=bypass.*") {
39+
set req.http.X-Cache = "bypass";
40+
return (pass);
41+
}
42+
43+
# If has no-cache header, bypass Varnish
44+
# This might be redundant, I'm not quite sure what the default behavior is
45+
if (req.http.Cache-Control ~ "no-cache") {
46+
set req.http.X-Cache = "bypass";
47+
return (pass);
48+
}
49+
}
50+
51+
sub vcl_deliver {
52+
if (obj.hits > 0) {
53+
# Add debug header to see if it's a HIT/MISS and the number of hits, disable when not needed
54+
set resp.http.X-Cache = "hit";
55+
} else {
56+
set resp.http.X-Cache = "miss";
57+
}
58+
}
59+
60+
sub vcl_backend_response {
61+
# Set a long TTL for tiles
62+
if (bereq.url ~ ".*\.(png|mvt)$") {
63+
set beresp.ttl = 1d;
64+
# Allow stale content while revalidating
65+
set beresp.grace = 5m;
66+
} else {
67+
# Shorter TTL for other content
68+
set beresp.ttl = 5m;
69+
}
70+
}

local-root/docker-compose.yaml

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ services:
66
volumes:
77
- ./Caddyfile:/etc/caddy/Caddyfile
88
labels:
9-
- dev.orbstack.domains=macrostrat.local,storage.macrostrat.local,storage-ui.macrostrat.local,dev.macrostrat.local
9+
- dev.orbstack.domains=macrostrat.local,storage.macrostrat.local,storage-ui.macrostrat.local,dev.macrostrat.local,tiles.macrostrat.local
1010
database:
1111
# PostgreSQL 13 is needed in order to allow force-dropping the database
1212
# (in testing mode)
@@ -78,7 +78,13 @@ services:
7878
# Perhaps we can put this config in the database?
7979
- PGRST_DB_AGGREGATES_ENABLED=true
8080
# Tileserver
81-
tileserver:
81+
tileserver_cache:
82+
image: varnish:7.7
83+
environment:
84+
- VARNISH_HTTP_PORT=8000
85+
volumes:
86+
- ./configs/tileserver-cache.vcl:/etc/varnish/default.vcl
87+
tileserver_core:
8288
image: hub.opensciencegrid.org/macrostrat/tileserver:main
8389
build:
8490
context: ../services/tileserver
@@ -95,26 +101,25 @@ services:
95101
command: >
96102
uv run uvicorn --host 0.0.0.0 --port 8000
97103
macrostrat.tileserver:app
98-
--root-path /tiles
99104
--log-level debug
100105
--proxy-headers
101106
--forwarded-allow-ips=*
102-
legacy_tileserver:
107+
tileserver_legacy:
103108
image: hub.opensciencegrid.org/macrostrat/legacy-tileserver:main
104109
build:
105110
context: ../services/legacy-tileserver
106111
additional_contexts:
107112
py-modules: ../py-modules
108113
environment:
109114
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@database:5432/${POSTGRES_DB}
115+
- MAPNIK_POOL_SIZE=64
110116
command: >
111117
uvicorn --host 0.0.0.0 --port 8000
112118
macrostrat.legacy_tileserver:app
113-
--root-path /tiles/legacy
114119
--log-level debug
115120
--proxy-headers
116121
--forwarded-allow-ips=*
117-
# Storage
122+
# Storage system
118123
storage:
119124
image: minio/minio:RELEASE.2024-12-18T13-15-44Z-cpuv1
120125
environment:
@@ -132,7 +137,7 @@ services:
132137
build: ${MACROSTRAT_WEB_SRC:-""}
133138
environment:
134139
- VITE_MAPBOX_API_TOKEN=${MAPBOX_TOKEN}
135-
- VITE_MACROSTRAT_TILESERVER_DOMAIN=https://macrostrat.local/tiles
140+
- VITE_MACROSTRAT_TILESERVER_DOMAIN=https://tiles.macrostrat.local
136141
- VITE_MACROSTRAT_API_DOMAIN=https://macrostrat.local
137142
# Needed for server-side rendering requests to not fail on self-signed certs (which OrbStack provides)
138143
- NODE_TLS_REJECT_UNAUTHORIZED=0

services/legacy-tileserver/Dockerfile

Lines changed: 40 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,22 @@
44

55
FROM python:3.9@sha256:c0dcc146710fed0a6d62cb55b92f00bfbfc3b931fff6218f4958bab58333c37b
66

7-
ENV PIP_DISABLE_PIP_VERSION_CHECK=1 \
8-
POETRY_NO_INTERACTION=1 \
9-
POETRY_CACHE_DIR=/tmp/poetry-cache \
10-
POETRY_VIRTUALENVS_CREATE=false
11-
12-
WORKDIR /app
13-
RUN python3 -m venv /venv
14-
ENV PATH="/venv/bin:$PATH"
15-
ENV VIRTUAL_ENV=/venv
16-
17-
# MAPNIK
18-
# Install mapnik for compiling legacy image tiles
7+
# Install UV for Python package management
8+
COPY --from=ghcr.io/astral-sh/uv:0.9.9 /uv /uvx /bin/
9+
10+
ENV UV_SYSTEM_PYTHON=0
11+
ENV UV_LINK_MODE=copy
12+
ENV UV_COMPILE_BYTECODE=1
13+
14+
WORKDIR /services/main
15+
16+
# Create and enter a virtual environment
17+
RUN python3 -m venv /opt/venv
18+
ENV PATH="/opt/venv/bin:$PATH"
19+
ENV VIRTUAL_ENV="/opt/venv"
20+
21+
# Install MAPNIK
22+
# Install dependencies for compiling legacy image tiles
1923
RUN apt-get update -y && \
2024
apt-get install -y --no-install-recommends \
2125
build-essential software-properties-common curl \
@@ -32,10 +36,20 @@ RUN cd /tmp/mapnik-v${MAPNIK_VERSION} && python scons/scons.py configure
3236
RUN cd /tmp/mapnik-v${MAPNIK_VERSION} && make JOBS=4 && make install JOBS=4
3337

3438
ENV BOOST_PYTHON_LIB=boost_python39
35-
# Python bindings to mapnik
39+
# Build/install Mapnik Python bindings
3640
ARG PYTHON_MAPNIK_COMMIT=7da019cf9eb12af8f8aa88b7d75789dfcd1e901b
3741
RUN mkdir -p /opt/python-mapnik && curl -L https://github.com/mapnik/python-mapnik/archive/${PYTHON_MAPNIK_COMMIT}.tar.gz | tar xz -C /opt/python-mapnik --strip-components=1
38-
RUN cd /opt/python-mapnik && python3 setup.py install && rm -r /opt/python-mapnik/build
42+
43+
# Carto is needed for CartoCSS -> Mapnik XML conversion
44+
# Install Node.js and npm
45+
# Import the Node.js repository GPG key
46+
RUN apt-get update -y && \
47+
apt-get install -y nodejs npm && \
48+
npm install -g carto && \
49+
rm -rf /tmp/* && \
50+
rm -rf /var/lib/apt/lists/*
51+
52+
RUN uv pip install /opt/python-mapnik
3953

4054
# Remove build dependencies
4155
RUN apt-get remove -y \
@@ -44,43 +58,30 @@ RUN apt-get remove -y \
4458
libboost-regex-dev libboost-system-dev libboost-thread-dev libicu-dev libtiff5-dev \
4559
libfreetype-dev libpng-dev libxml2-dev libproj-dev libcairo-dev libharfbuzz-dev python-dev
4660

47-
# CartoCSS stylesheet generation
48-
# Install nodejs
49-
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - && \
50-
apt-get install -y nodejs && \
51-
rm -rf /var/lib/apt/lists/*
52-
53-
# Install carto
54-
RUN npm install -g carto
55-
56-
# Clear temporary files
57-
RUN rm -rf /tmp/*
58-
59-
# The rest of this (for the server itself) should be easier.
60-
61-
# Install UV
62-
COPY --from=ghcr.io/astral-sh/uv:0.9.9 /uv /uvx /bin/
63-
64-
ENV UV_LINK_MODE=copy
65-
ENV UV_COMPILE_BYTECODE=1
66-
6761
# NEED TO specify a build context for the py-modules directory
6862
COPY --from=py-modules tileserver-utils /py-modules/tileserver-utils
6963

70-
WORKDIR /services/main
71-
72-
# Install dependencies
64+
# Install dependencies. The --inexact flag allows us to keep the unmanaged mapnik installation
65+
# even though it is not specified in the lockfile.
7366
RUN --mount=type=cache,target=/root/.cache/uv \
7467
--mount=type=bind,source=uv.lock,target=uv.lock \
7568
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
76-
uv sync --locked --no-install-project --no-editable --active
69+
uv sync --inexact --locked --no-install-project --no-editable --active
70+
71+
# We've already built this but we have to reinstall it after uv sync
72+
RUN uv pip install /opt/python-mapnik && \
73+
rm -rf /opt/python-mapnik
7774

7875
# Add source files to project
7976
ADD . /services/main
8077

8178
# Sync the project
8279
RUN --mount=type=cache,target=/root/.cache/uv \
83-
uv sync --locked --no-editable --active
80+
uv sync --inexact --locked --no-editable --active
81+
82+
# Check whether Mapnik bindings are properly installed
83+
RUN python -c "import mapnik; print('mapnik version:', mapnik.mapnik_version())" && \
84+
python -c "import uvicorn; print('uvicorn version:', uvicorn.__version__)"
8485

8586
EXPOSE 8000
8687

services/legacy-tileserver/macrostrat/legacy_tileserver/__init__.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,19 @@
3232
@app.on_event("startup")
3333
async def startup_event():
3434
"""Application startup: register the database connection and create table list."""
35-
# Don't rely on poort TimVT handling of database connections
3635
setup_stderr_logs("macrostrat.legacy_tileserver")
3736

3837
url = environ["DATABASE_URL"]
38+
39+
# Tile rendering map pool size
40+
# This controls how many image tiles can be concurrently rendered.
41+
# Database access is somewhat inefficient, so we may need to adjust this.
42+
mapnik_pool_size = int(environ.get("MAPNIK_POOL_SIZE", "64"))
43+
log.info(f"Setting up Mapnik map pool with size {mapnik_pool_size}")
44+
3945
app.state.pool = await create_pool_b(url)
4046
db = Database(url)
41-
app.state.map_pool = MapnikMapPool(8)
47+
app.state.map_pool = MapnikMapPool(mapnik_pool_size)
4248
await app.state.map_pool.setup(db)
4349

4450

services/legacy-tileserver/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "macrostrat.legacy-tileserver"
3-
version = "2.3.0-beta.2"
3+
version = "2.3.0-beta.3"
44
description = "Macrostrat legacy tile server"
55
authors = [{ name = "Daven Quinn", email = "[email protected]" }]
66
requires-python = ">=3.9,<3.10"

services/legacy-tileserver/uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

services/tileserver/Dockerfile.old

Lines changed: 0 additions & 72 deletions
This file was deleted.

0 commit comments

Comments
 (0)