Docker composeでPostGIS-pgAdmin 開発環境を作成してみた

GIS初心者のKCSCです。
GIS研究によく使われるPostGIS及びpgAdminのdocker imageを（docker composeを使い）最速で作成することを試みて、そして感想です。

## docker composeファイルの用意と実行
docker コンテナを作成するため、docker-compose.ymlファイルが必要です。
docker-compose.ymlは以下の通りです。
```yaml
services:
  ser_postgis:
    image: postgis/postgis:latest
    container_name: con_postgis
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: osm_kyushu
    ports:
     - "5438:5432"
    volumes:
     - ./postgis_data:/var/lib/postgresql/data
     - ./:/work

  ser_pgadmin:
    image: dpage/pgadmin4:latest
    container_name: con_pgadmin
    ports:
     - "8088:80"
    volumes:
     - ./pgadmin_data:/var/lib/pgadmin
    environment:
     PGADMIN_DEFAULT_EMAIL: postgis@example.com
     PGADMIN_DEFAULT_PASSWORD: postgis_pw
    depends_on:
     - ser_postgis
```
注意が必要なところ：
image: docker サーバに請求するimageの名前となります。latestのところがバージョンで、ニーズに応じて調整できます。
```yaml
image: postgis/postgis:latest

image: dpage/pgadmin4:latest
```
imageの名前として使われます。わかりやすい（入力しやすい）名前にしましよう。
```yaml
container_name: con_postgis

container_name: con_pgadmin
```
portsの設定：左がホスト（パソコン）で使うport番号、右がコンテナ内部のportになります。左のホスト番号はエラー回避のため、通常には既定の番号と異なるportを使用します。
```yaml
ports:
 - "5438:5432"

ports:
 - "8088:80"
```

volumes:左と右もホストとコンテナ内部のフォルダの対照です。
```yaml
volumes:
     - ./postgis_data:/var/lib/postgresql/data
     - ./:/work

volumes:
     - ./pgadmin_data:/var/lib/pgadmin
```

pgAdminのメールはメールアドレスっぽくないバリューを入力すると、エラーに怒られる事件もあります！（多分正規表現で判断）
```yaml
PGADMIN_DEFAULT_EMAIL: postgis@example.com
```

以上のyamlファイルを準備した後、docker composeで実行：

```
sudo docker-compose up
```

pgadminのPermission denied エラーが出た場合の処置：
```
con_pgadmin    | ERROR  : Failed to create the directory /var/lib/pgadmin/sessions:
con_pgadmin    |            [Errno 13] Permission denied: '/var/lib/pgadmin/sessions'
con_pgadmin    | HINT   : Create the directory /var/lib/pgadmin/sessions, ensure it is writeable by
con_pgadmin    |          'pgadmin', and try again, or, create a config_local.py file
con_pgadmin    |          and override the SESSION_DB_PATH setting per
con_pgadmin    |          https://www.pgadmin.org/docs/pgadmin4/8.12/config_py.html

```

以下の手順で実行したらOKです。
```
sudo chown -R 5050:5050 ./pgadmin_data
```


一旦　Ctrl+C、出来上がりを確認
```shell
sudo docker ps -a
CONTAINER ID   IMAGE                    COMMAND                  CREATED         STATUS                     PORTS     NAMES
a00000000001   dpage/pgadmin4:latest    "/entrypoint.sh"         3 hours ago     Exited (0) 3 hours ago               con_pgadmin
b00000000001   postgis/postgis:latest   "docker-entrypoint.s…"   3 hours ago     Exited (0) 3 hours ago               con_postgis

```

もう一度始動：
```
sudo docker start con_pgadmin && sudo docker start con_postgis
```


## OpenStreetMap データを用意
「https://download.geofabrik.de/asia/japan.html」
上記のリンクでosm データ（全国あるいは地方ごろ）をダウンロードします。今回は九州地方データにしました：

```shell
wget https://learnosm.org/files/default.style
wget https://download.geofabrik.de/asia/japan/kyushu-latest.osm.pbf
```
そして、postgisコンテナ内部に侵入！
```shell
sudo docker exec -it con_postgis /bin/bash
root@b00000000001:/#
```

コンテナ内部にもOSMデータファイルがあることを確認：
```shell
ls work
default.style  docker-compose.yml  kyushu-latest.osm.pbf pgadmin_data  postgis_data
```


osm2pgsqlパッケージをインストール：

```shell
root@b00000000001:/# apt update
root@b00000000001:/# apt install osm2pgsql
```

そして、コンテナ内部のデータベースにも確認：
```shell
root@b00000000001:/# psql -U postgres

psql (17.0 (Debian 17.0-1.pgdg110+1), server 16.4 (Debian 16.4-1.pgdg110+1))
Type "help" for help.

postgres=# \l
                                                        List of databases
       Name       |  Owner   | Encoding | Locale Provider |  Collate   |   Ctype    | Locale | ICU Rules |   Access privileges   
------------------+----------+----------+-----------------+------------+------------+--------+-----------+-----------------------
 osm_kyushu       | postgres | UTF8     | libc            | en_US.utf8 | en_US.utf8 |        |           | 
 postgres         | postgres | UTF8     | libc            | en_US.utf8 | en_US.utf8 |        |           | 

```
osm_kyushuというデータベースがあればOKです。

osm_kyushuのpostgis拡張機能も確認：
```shell
postgres=# \c osm_kyushu
psql (17.0 (Debian 17.0-1.pgdg110+1), server 16.4 (Debian 16.4-1.pgdg110+1))
You are now connected to database "osm_kyushu" as user "postgres".
osm_kyushu=# create extension postgis;
ERROR:  extension "postgis" already exists
osm_kyushu=# \q
```

\qを実行すると、コンテナのshellに戻るはずので、いよいよデータのインポート作業：
```shell
root@b00000000001:/# osm2pgsql --create --database=osm_kyushu --slim --style=work/default.style -U postgres -H localhost work/kyushu-latest.osm.pbf

osm2pgsql version 1.4.1
Database version: 16.4 (Debian 16.4-1.pgdg110+1)
PostGIS version: 3.4
Node-cache: cache=800MB, maxblocks=12800*65536, allocation method=11
Setting up table 'planet_osm_point'
Setting up table 'planet_osm_line'
Setting up table 'planet_osm_polygon'
Setting up table 'planet_osm_roads'
...
node cache: stored: 31042999(100.00%), storage efficiency: 53.09% (dense blocks: 1222, sparse nodes: 24229488), hit rate: 100.00%
osm2pgsql took 557s (9m 17s) overall.

```
大体10分ぐらいかかったようです。(i7-8700 CPU 16.0 GiB RTX 2080)

## 出来上がりを確認
localhost:8088でpgAdmin をアクセス：

サーバーを追加：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3914962/7dae0fe4-83c7-b19c-481a-ef36beb9598d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3914962/27af1cac-c933-cef3-4420-d08a3e0cda18.png)

Host nameはファイルのpostgisのservice名、 Portは右の内部Portにして、Maintence databaseはそのまま：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3914962/1976119c-3cc4-6834-8f5f-8769e00f7c46.png)

大丈夫であれば：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3914962/1a7807b5-4a3f-35d1-7f36-4de9d03e075a.png)

SQLコードで鹿児島付近の駅を抽出してみた：
```sql
SELECT "name", ST_Astext(ST_Transform(way, 4612)) FROM public.planet_osm_point WHERE (railway = 'stop' OR railway = 'station') AND

ST_Contains(
	ST_Transform(
      ST_GeomFromText('POLYGON((130.37 31.45, 130.37 31.79, 130.79 31.79, 130.79 31.45, 130.37 31.45))', 4612),
	  4612
	  ),
    ST_Transform(way, 4612)
  )

LIMIT 1000;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3914962/535892f4-88f9-dac5-e512-8132a2725bc6.png)

地図として表示することもできます：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3914962/b36f6833-d9be-c96c-694e-8e836080d3a7.png)


参照：

https://zenn.dev/s_takashi/articles/e3e96f4daba814


https://qiita.com/hiyuzawa/items/ba1b9de36bf911145c1c


https://qiita.com/jammachine/items/73217cfb7abe7012c5ec


ブロッグ作者の方に感謝申し上げます。