2017年4月6日 星期四

how to build an osm map server for taiwan on docker

最近集眾人智慧的開放街圖(OpenStreetMap)很熱門,以下介紹一個簡便架設台灣區 OSM 地圖伺服器的方法。
前提是需先安裝 docker 容器環境,例如: Windows 10 上安裝 docker for windows 容器軟體。
有了 docker 容器環境之後,取圖資及架網站的步驟如下:

0.主機打開命令列工具,例如: Windows 10 的 powershell 命令列工具。


以下分成手動及自動安裝兩種說明,手動說明方便理解安裝步驟,自動說明方便快速安裝。

A.【手動安裝法】以下利用原始映像檔,手動建立新映像檔taiwan-osmbright:v1

1.主機下載 dmakan/ubuntu-opentileserver:v1 原始映像檔,啟動容器命名 twbright
    > docker pull dmakan/ubuntu-opentileserver:v1
    > docker run -t -i -p 80:80 --name twbright dmakan/ubuntu-opentileserver:v1
    註: -t for terminal, -i for interactive 表示取得容器的終端機互動視窗,可用 Ctrl-p Ctrl-q 退回主機
    註: -p host_port:container:port for port mapping 先主機埠,後容器埠,可將容器埠對應到主機埠,對外提供服務

2.容器修改 opentileserver.sh 批次檔,讓資料庫接受 utf8 文字編碼
    # vi /opentileserver/opentileserver.sh

    原始 if [ $(psql -Upostgres -c "select datname from pg_database" | grep -m 1 -c ${OSM_DB}) -eq 0 ]; then
    之前新增一行 psql -Upostgres -c "DROP DATABASE IF EXISTS ${OSM_DB};"

    原始 psql -Upostgres -c "create database ${OSM_DB} owner=${OSM_USER};"
    修改 psql -Upostgres -c "CREATE DATABASE ${OSM_DB} TEMPLATE template0 ENCODING 'UTF8' OWNER ${OSM_USER};"

    原始 CREATE EXTENSION hstore;
    修改 CREATE EXTENSION IF NOT EXISTS hstore;

    原始 CREATE EXTENSION postgis;
    修改 CREATE EXTENSION IF NOT EXISTS postgis;

    註: 要先刪除原有資料庫,再重新建立一個接受 utf8 統一碼的資料庫
    註: OSM_USER 預設資料庫用戶名為 tile,OSM_DB 預設資料庫名稱為 gis

3.容器執行 opentileserver.sh 批次檔,下載套件及圖資
    # cd /opentileserver/
    # ./opentileserver.sh web bright http://download.geofabrik.de/asia/taiwan-latest.osm.pbf

    註: 紅色州名/國名可替換成任何想提供服務的國家,詳http://download.geofabrik.de/
    註: geofabrik每日更新一次圖資,只要再執行 opentileserver.sh 批次檔,就重新下載最新圖資,覆寫原有資料庫內容

4.容器修改 OSMBright.xml 樣式檔,讓形狀檔路徑正確
   利用串流修改指令sed進行字串取代
    # sed -ie 's/pulated_places/pulated_places_simple/g' /usr/local/share/maps/style/OSMBright/OSMBright.xml

   或者利用編輯器vi進行修改
    # vi /usr/local/share/maps/style/OSMBright/OSMBright.xml

    原始 <Parameter name="file">
          <![CDATA[/usr/local/share/maps/style/osm-bright-master/shp/
                      ne_10m_populated_places/ne_10m_populated_places.shp]]>
        </Parameter>
    修改 <Parameter name="file">
          <![CDATA[/usr/local/share/maps/style/osm-bright-master/shp/
                      ne_10m_populated_places_simple/ne_10m_populated_places_simple.shp]]>
        </Parameter>

5.容器開啟資料庫,網站,圖磚服務
    # service postgresql restart
    # service apache2 restart
    # service renderd restart

6.主機開啟瀏覽器驗證
    http://localhost/openlayers-example.html

7.主機儲存容器內容為新映像檔,供下回使用
    > docker commit twbright taiwan-osmbright:v1   # 新映像檔命名 taiwan-osmbright:v1
    > docker stop twbright     # 關閉容器
    > docker rm twbright    # 刪除容器


8.主機利用新映像檔,開啟容器,仍命名為 twbright,提供地圖服務
    > docker run -i -t -p 80:80 --name twbright taiwan-osmbright:v1
    http://localhost:80/openlayers-example.html



B.【自動安裝法】以下利用Github映像檔製作環境包快速製作新映像檔taiwan-osmbright:v1

1.下載映像檔製作環境包
  利用瀏覽器連線到網址 https://github.com/sekewei/docker-opentileserver
  點選下載映像檔製作環境包 taiwan-osmbright_v1_build.tar.gz

2.製作地圖服務映像檔
  利用如下指令製作地圖服務映像檔,其中,- 表示映像檔製作環境取自導向(<)進來的環境包檔案,
    -f ./Dockerfile 表示製作步驟檔位於映像檔製作環境之路徑
  > docker build -f ./Dockerfile -t taiwan-osmbright:v1 - < taiwan-osmbright_v1_build.tar.gz

3.啟動地圖服務容器
  利用如下指令啟動服務容器,命名twbright,介接到主機80號埠
  > docker run -it -p 80:80 --name twbright taiwan-osmbright:v1
  按Ctrl-p + Ctrl-q跳出容器終端機

4.測試地圖服務
  利用瀏覽器連線到本地主機80號埠測試地圖服務
  http://localhost:80/openlayers-example.html

  註: 如果要修改初始地圖顯示位置為(lon,lat),方法如下:
        # vi /var/www/html/openlayers-example.html
            var toProjection   = new OpenLayers.Projection("EPSG:900913"); // spherical mercator projection
            var fromProjection = new OpenLayers.Projection("EPSG:4326"); // WGS 1984
            var position       = new OpenLayers.LonLat(lon,lat).transform(fromProjection, toProjection);
            var zoom           = 15;
            map.setCenter(position, zoom);

5.更新地圖資料
  利用如下指令連入容器終端機,執行腳本下載圖資,匯入資料庫,重新啟動服務
  > docker attach twbright
  # cd /opentileserver
  # sh ./reload-opentileserver.sh
  按Ctrl-p + Ctrl-q跳出容器終端機



C.【除錯資訊】以下為自動或手動建立新映像檔,啟動容器後的除錯要點:
0.本機進入容器的終端機 > docker attach twbright 

1.圖磚前景啟動 # sudo -u tile renderd -f -c /usr/local/etc/renderd.conf
     可確認字型檔 unifont.ttf 及形狀檔 ne_10m_populated_places_simple.shp 是否載入正確

2.圖磚快取位置 # ls /var/lib/mod_tile/default/
     可確認目錄下是否有.png圖磚產生

3.字型位置必須有unifont統一碼字型
     # ls /usr/share/fonts/truetype/unifont/unifont.ttf

4.資料庫設定檔必須驗證方式為trust才不必輸入密碼,如下:
     /etc/postgresql/9.3/main/pg_hba.conf
     local all all trust

5.資料庫驗證
     # psql -d gis -Utile   # 以用戶 tile 身份連入資料庫 gis
     gis=# \d         # 列出資料表
               List of relations
   Schema |        Name        | Type  |  Owner
  --------+--------------------+-------+----------
   public | geography_columns  | view  | postgres
   public | geometry_columns   | view  | tile
   public | planet_osm_line    | table | tile
   public | planet_osm_nodes   | table | tile
   public | planet_osm_point   | table | tile
   public | planet_osm_polygon | table | tile
   public | planet_osm_rels    | table | tile
   public | planet_osm_roads   | table | tile
   public | planet_osm_ways    | table | tile
   public | raster_columns     | view  | postgres
   public | raster_overviews   | view  | postgres
   public | spatial_ref_sys    | table | tile
  (12 rows)
 
     gis=# \d planet_osm_point  # 列出欄位
  osm_id             | bigint                 |
  access             | text                   |
  addr:housename     | text                   |
  addr:housenumber   | text                   |
  addr:interpolation | text                   |
  admin_level        | text                   |
  aerialway          | text                   |
  aeroway            | text                   |
  amenity            | text                   |
  area               | text                   |
  barrier            | text                   |
  bicycle            | text                   |
  brand              | text                   |
  bridge             | text                   |
  boundary           | text                   |
  building           | text                   |
  .....
  water              | text                   |
  waterway           | text                   |
  wetland            | text                   |
  width              | text                   |
  wood               | text                   |
  z_order            | integer                |
  way                | geometry(Point,900913) |

     gis=# select osm_id, name from planet_osm_point limit 10;  # 取10個點看中文名正確否
     osm_id   |   name
  ------------+-----------
     63252122 |
   1647048653 | 青屿
   1645249987 | 五膽島
   1645249985 | 四膽島
   1645249984 | 三膽島
   1645249983 | 二膽島
   1645249988 | 大膽島
   1645251414 | 獅球
   1645249986 | 大南礁
   1645249989 | 兔嶼

     gis=# select count(*) from planet_osm_point;  # 計算總共資料庫有幾個點
  count
--------
 198300
(1 row)

     gis=# \q         # 離開

沒有留言: