
构建 PostGIS 与 pgRouting容器镜像:打造强大的地理空间分析
PostGIS 与 pgRouting:打造强大的地理空间分析容器
背景
在现代地理信息系统 (GIS) 和基于位置的服务中,PostGIS 和 pgRouting 是两个不可或缺的开源工具。PostGIS 为 PostgreSQL 数据库提供了强大的空间数据处理能力,而 pgRouting 则在此基础上增加了高级的路径规划和网络分析功能。通过 Docker 将它们容器化,可以极大地简化部署和管理过程。本文将介绍 PostGIS 和 pgRouting 的基本概念、用途,并提供一个 Dockerfile 示例来构建一个包含这两个扩展的 PostgreSQL 镜像。
一、. PostGIS 是什么,pgRouting 又是什么?
PostGIS
PostGIS 是 PostgreSQL 对象关系数据库的一个扩展,它允许 PostgreSQL 数据库管理和查询地理对象。简而言之,PostGIS 为 PostgreSQL 增加了对空间数据类型(如点、线、面、栅格等)的支持,以及一系列用于空间分析和处理的空间函数。这使得 PostgreSQL 成为了一个功能完备的空间数据库,能够存储、索引和查询大规模的地理空间数据。
主要特性包括:
- 支持多种矢量和栅格数据类型。
- 符合 Open Geospatial Consortium (OGC) 的 SQL 实现标准。
- 提供丰富的空间操作和分析函数(例如,距离计算、缓冲区分析、几何对象关系判断等)。
- 强大的空间索引能力,优化查询性能。
pgRouting
pgRouting 是 PostGIS/PostgreSQL 的另一个扩展,它专注于网络分析和路径规划。基于 PostGIS 存储的地理网络数据(如道路网、河流网络等),pgRouting 可以执行复杂的路由算法,例如:
- Dijkstra 算法: 查找单源最短路径。
- A* 算法: 一种启发式搜索算法,用于更高效地查找最短路径。
- K-Shortest Path (KSP): 查找 K 条最短路径。
- Traveling Salesperson Problem (TSP): 旅行商问题求解。
- Driving Distance: 计算可达区域。
pgRouting 使得开发者可以在数据库层面直接进行路径计算和网络分析,而无需将数据导出到外部工具。
二. 它们的用途
PostGIS 的用途
PostGIS 的应用场景非常广泛,主要包括:
- 空间数据存储与管理: 作为企业级地理数据库,集中存储和管理各类地理空间数据。
- Web 地图服务: 为在线地图应用(如 Leaflet, OpenLayers, Mapbox GL JS)提供后端数据支持。
- 地理信息系统 (GIS) 分析: 进行复杂的空间分析,如环境影响评估、城市扩张研究、资源分布分析等。
- 位置服务 (LBS): 开发基于用户位置的应用,如“附近的餐馆”、“导航服务”等。
- 城市规划与基础设施管理: 辅助规划道路、管线、公共设施等。
- 自然资源管理: 监测森林、水资源、土地利用变化等。
pgRouting 的用途
pgRouting 主要用于解决与网络和路径相关的问题:
- 导航系统: 为汽车、行人和自行车提供最优路径规划。
- 物流与配送: 优化车辆的配送路线,提高效率,降低成本。
- 交通网络分析: 分析交通流量、瓶颈路段、可达性等。
- 应急响应: 规划消防车、救护车等紧急车辆的最佳出动路径。
- 公共交通规划: 分析公交线路覆盖范围和效率。
- 旅游路线推荐: 根据用户偏好和景点网络生成推荐游览路线。
三.如何封装 Dockerfile
编写Dockerfile 文件
以下是一个用于构建包含 PostGIS 和 pgRouting 的 PostgreSQL 镜像的 Dockerfile。这个 Dockerfile 基于 postgres:15-alpine3.18 镜像,并安装了 PostGIS 3.4.2 和 pgRouting 3.7.1
CNB代码仓库: https://cnb.cool/srebro/docker-images/-/tree/main/Middleware/postgres
参考: https://github.com/postgis/docker-postgis/blob/master/15-3.4/alpine/Dockerfile 和 https://github.com/postgis/docker-postgis/issues/399
#
# NOTE: THIS DOCKERFILE IS GENERATED VIA "make update"! PLEASE DO NOT EDIT IT DIRECTLY.
#
ARG BASE_IMAGE=postgres:15-alpine3.18
FROM ${BASE_IMAGE}
LABEL maintainer="PostGIS Project - https://postgis.net" \
org.opencontainers.image.description="PostGIS 3.4.2 spatial database extension with PostgreSQL 15 Alpine" \
org.opencontainers.image.source="https://github.com/postgis/docker-postgis"
ENV POSTGIS_VERSION 3.4.2
ENV POSTGIS_SHA256 17aa8760a5c4fcb9a1fdc750c1c9aca0198a35dd1e320628064c43f178eefed2
ENV PGROUTING_VERSION 3.7.1
RUN set -eux \
# 使用国内镜像源
# && sed -i 's/dl-cdn.alpinelinux.org/mirrors.nju.edu.cn/g' /etc/apk/repositories \
&& sed -i 's@dl-cdn.alpinelinux.org@mirrors.cloud.tencent.com@g' /etc/apk/repositories \
# 更新并安装依赖
&& apk update && apk upgrade \
&& apk add --no-cache \
boost-dev \
cmake \
ca-certificates \
openssl \
tar \
wget \
gdal-dev \
geos-dev \
proj-dev \
proj-util \
sfcgal-dev \
autoconf \
automake \
cunit-dev \
file \
g++ \
gcc \
gettext-dev \
git \
json-c-dev \
libtool \
libxml2-dev \
make \
pcre2-dev \
perl \
protobuf-c-dev \
&& apk add --no-cache --virtual .build-deps \
$DOCKER_PG_LLVM_DEPS \
# 下载pgrouting源代码
&& wget -O pgrouting.tar.gz "https://cnb.cool/srebro/docker-images/-/releases/download/V1.0.0/pgrouting-${PGROUTING_VERSION}.tar.gz" \
&& echo "Extracting pgrouting" \
&& tar -xvzf pgrouting.tar.gz \
&& cd pgrouting-* \
&& mkdir build \
&& cd build \
&& cmake -DCMAKE_CXX_FLAGS="-include cstdint" .. \
&& make -j4 \
&& make install \
&& cd ../.. \
&& rm -rf pgrouting* \
# 下载和校验 PostGIS 源代码
&& wget -O postgis.tar.gz "https://cnb.cool/srebro/docker-images/-/releases/download/V1.0.0/postgis-${POSTGIS_VERSION}.tar.gz" \
&& echo "${POSTGIS_SHA256} *postgis.tar.gz" | sha256sum -c - \
&& mkdir -p /usr/src/postgis \
&& tar --extract --file postgis.tar.gz --directory /usr/src/postgis --strip-components 1 \
&& rm postgis.tar.gz \
# 构建和安装 PostGIS
&& cd /usr/src/postgis \
&& gettextize \
&& ./autogen.sh \
&& ./configure --enable-lto \
&& make -j$(nproc) \
&& make install \
# 刷新 proj 数据并执行回归测试
&& projsync --system-directory --file ch_swisstopo_CHENyx06_ETRS \
&& projsync --system-directory --file us_noaa_eshpgn \
&& projsync --system-directory --file us_noaa_prvi \
&& projsync --system-directory --file us_noaa_wmhpgn \
&& mkdir /tempdb \
&& chown -R postgres:postgres /tempdb \
&& su postgres -c 'pg_ctl -D /tempdb init' \
&& su postgres -c 'pg_ctl -D /tempdb start -l /tmp/logfile -o "-F"' \
&& cd regress \
&& make -j$(nproc) check RUNTESTFLAGS=--extension PGUSER=postgres \
&& su postgres -c 'psql -c "CREATE EXTENSION IF NOT EXISTS postgis;"' \
&& su postgres -c 'psql -c "CREATE EXTENSION IF NOT EXISTS postgis_raster;"' \
&& su postgres -c 'psql -c "CREATE EXTENSION IF NOT EXISTS postgis_sfcgal;"' \
&& su postgres -c 'psql -c "CREATE EXTENSION IF NOT EXISTS fuzzystrmatch;"' \
&& su postgres -c 'psql -c "CREATE EXTENSION IF NOT EXISTS address_standardizer;"' \
&& su postgres -c 'psql -c "CREATE EXTENSION IF NOT EXISTS address_standardizer_data_us;"' \
&& su postgres -c 'psql -c "CREATE EXTENSION IF NOT EXISTS postgis_tiger_geocoder;"' \
&& su postgres -c 'psql -c "CREATE EXTENSION IF NOT EXISTS postgis_topology;"' \
&& su postgres -c 'psql -c "CREATE EXTENSION IF NOT EXISTS pgrouting;"' \
&& su postgres -c 'pg_ctl -D /tempdb --mode=immediate stop' \
&& rm -rf /tempdb /tmp/logfile \
# 安装运行时依赖
&& apk add --no-cache \
gdal \
geos \
proj \
sfcgal \
json-c \
libstdc++ \
pcre2 \
protobuf-c \
ca-certificates \
# 清理构建依赖
&& apk del .build-deps \
&& rm -rf /usr/src/postgis /var/cache/apk/*
COPY ./initdb-postgis.sh /docker-entrypoint-initdb.d/10_postgis.sh
COPY ./update-postgis.sh /usr/local/bin
构建镜像
docker build -t XXXX -f Dockerfile .
或者使用我构建好的镜像: docker.cnb.cool/srebro/docker-images/postgis:15.5-3.4
四.使用docker-compose 运行容器
1、创建目录
mkdir -p /home/application/Database/postgres/{data,init}
2、创建docker-compose.yaml 文件,见 docker-compose.yaml 文件
vim /home/application/Database/postgres/docker-compose.yml
version: "3"
services:
postgres:
container_name: postgres
image: docker.cnb.cool/srebro/docker-images/postgis:15.5-3.4
networks:
- srebro
environment:
POSTGRES_HOST_AUTH_METHOD: md5
POSTGRES_PASSWORD: xxxxxxx
#ALLOW_IP_RANGE: 0.0.0.0/0
volumes:
- /home/application/Database/postgres/data:/var/lib/postgresql/data
- /home/application/Database/postgres/init:/docker-entrypoint-initdb.d/ ##可初始化SQL文件
command: -c max_connections=2000
ports:
- "5432:5432"
restart: always
networks:
srebro:
external: true
4、运行docker-compose创建容器
docker-compose up -d
之后,你就可以连接到这个 PostgreSQL 实例,并开始使用 PostGIS 和 pgRouting 的强大功能了。
希望这篇文章对你有所帮助!
- 感谢你赐予我前进的力量