Docker部署Ubuntu系統下GDAL開發環境

??本文介紹在LinuxUbuntu操作系統中,基于Docker快速配置PythonC++2種不同編程語言可用的地理數據處理庫GDAL開發環境的方法。

??本文就將PythonC++2種不同編程語言的GDAL模塊配置方法分開來介紹,大家依據自己的需求來選擇即可——但無論是哪種方法,配置GDAL模塊的方法都非常簡單,終端中輸入幾句代碼就完成了。和我們之前在Windows系統中配置GDAL模塊的文章GDAL庫在Visual Studio C++環境中的配置比起來,真的是方便了很多。

1 Python版本

??首先,我們訪問GDAL庫的Docker鏡像官方網站。這里需要注意,雖然這個官方網站似乎并沒有明確說明它提供的版本只能Python使用,但是我這里下載后發現C++代碼確實無法調用這個鏡像中的GDAL模塊。

??其中,官方網站提供了AlpineUbuntu兩種不同系統的Docker鏡像;并且對于不同的系統版本,其還提供了SmallFull兩種不同的鏡像內容,其中前者包含的內容相對較少,而后者包含的內容較為齊全(因此后者的鏡像大小也就更大一些),而這兩種鏡像自身都是包含Python3.8或以上版本的。此外,關于SmallFull兩種不同鏡像的具體詳細內容差異,我們這里就不再贅述了,大家在其官方網站查閱即可;具體如下圖所示。

??在我這里,由于只是需要用GDAL庫完成一些讀取.tif格式文件的操作,所以并不需要特別完整的GDAL庫,所以就選擇了Small這個小一點的版本。

??接下來,我們在Ubuntu電腦的終端中執行如下的代碼。這里需要注意,由于我需要的是Ubuntu系統的Small版本,所以我就輸入如下的代碼即可;如果大家使用的是Alpine操作系統,或者是Ubuntu系統的Full版本,那么按照上圖中自己所需要的版本對應的名稱,修改下述代碼并執行即可。

docker pull ghcr.io/osgeo/gdal:ubuntu-small-latest

??運行上述代碼,如下圖所示。

??稍等片刻,我們就完成了鏡像的獲取。此時,我們可以通過如下的代碼,查看當前電腦中Docker鏡像的下載情況(也就是看看我們已經有了哪些鏡像)。

docker images

??運行上述代碼,如下圖所示。

??其中,那個ghcr.io/osgeo/gdal就是我們剛剛下載好的GDAL庫的鏡像。

??接下來,運行如下的代碼,從而基于剛剛下載好的鏡像運行一個容器。

docker run -it --rm ghcr.io/osgeo/gdal:ubuntu-small-latest

??其中,docker run是運行容器的命令,-it表示以交互模式運行容器,并分配一個終端,--rm表示在容器停止后自動刪除容器(如果大家在使用容器后不想讓它自動刪除,就將這里的--rm去掉即可;如果大家是第一次接觸Docker,那么建議帶上這個--rm,防止自己摸索過程中不知不覺建立了好多個無用的容器,到時候還要手動一個一個刪除);后面的就是我們剛剛下載好的鏡像,表示我們要基于這個鏡像去運行一個容器。運行上述代碼,如下圖所示。

??接下來,我們就進入了容器。此時,繼續輸入如下的代碼,查看當前容器中GDAL庫的版本信息。

gdalinfo --version

??運行上述代碼,如下圖所示。可以看到,此時將打印出我們GDAL庫的版本信息。

??接下來,我們先通過如下的代碼,退出當前鏡像,回到終端中。

exit

??運行上述代碼,如下圖所示。

??我們既然配置了一個GDAL庫的Docker鏡像,那么后續肯定是需要將一些我們自己電腦中的文件(比如柵格圖像、矢量數據等文件)帶入到這個鏡像的容器中去運行,所以肯定需要這個GDAL庫的Docker鏡像要和我們Ubuntu電腦中文件可以交互(換句話說,也就是可以讀取、修改我們電腦中的文件與數據)。因此,我們在之后進入我們這個GDAL庫的Docker鏡像的容器時,需要通過如下的代碼。

docker run -it --rm -v /home/dell/cppGDAL:/home/dell/cppGDAL ghcr.io/osgeo/gdal:ubuntu-small-latest

??上述代碼和我們前面的docker run -it --rm ghcr.io/osgeo/gdal:ubuntu-small-latest相比,很顯然是多了-v /home/dell/cppGDAL:/home/dell/cppGDAL這一個部分——這一部分是用于掛載主機文件系統中的目錄容器中的命令參數。其中,-vDocker命令中用于掛載文件或目錄的選項,其后面的/home/dell/cppGDAL:/home/dell/cppGDAL,則是文件掛載的源目錄和目標目錄的路徑——它指定了主機文件系統中的/home/dell/cppGDAL目錄將被掛載到容器內的/home/dell/cppGDAL目錄。

??這里多提一句,我們這里是將主機中的一個指定文件路徑掛載到了容器中,所以屬于Docker中的Bind mounts;如果我們這里是手動創建了一個Volume,然后掛載到容器中,那么就叫做Volume;此外還有一種叫做tmpfs mounts,是把容器的數據寫入主機的內存中——上述的Bind mountsVolumetmpfs mounts,這3種都是Docker用以數據管理、數據記憶的方式。

??回到前述的代碼。換句話說,上述命令將我的Ubuntu電腦中的/home/dell/cppGDAL目錄與GDAL庫的Docker鏡像的容器中的/home/dell/cppGDAL目錄進行了掛載。這樣,在容器中對掛載點/home/dell/cppGDAL的操作將反映在主機系統的/home/dell/cppGDAL目錄上,反之亦然。

??相當于通過這種方式,只要我將我需要用GDAL庫處理的數據、代碼等文件,都放在電腦的/home/dell/cppGDAL目錄下,那么就可以在容器中對這些數據加以訪問和處理。這樣即實現了文件的交互,同樣可以保證容器不會訪問我們電腦中其他文件夾內的數據或者文件,保證了數據的安全。

??如果大家還是沒有明白這句代碼的意義,不著急,我們先運行上述代碼,如下圖所示。

??上圖中運行完代碼,我又不小心多運行了一句pwd代碼,大家理解即可。

??為了更清晰地看到前述那一種進入容器的代碼的意義,我們做一個如下的對比。如下圖所示,這是我們用了那一句包含掛載文件夾命令的代碼,進入我們的容器后,執行的操作;可以看到,此時在容器中,我們就可以進入/home/dell/cppGDAL目錄下。

??而如果我們并沒有掛載文件,而是用了本文中第一次出現的那一句代碼進入容器的代碼,也就是前面的docker run -it --rm ghcr.io/osgeo/gdal:ubuntu-small-latest代碼,進入容器后會發現,cd進入home文件夾后,再ls,是看不到我們這個cppGDAL文件夾的;換句話說,此時我們就沒有辦法在容器內部讀取我們電腦里/home/dell/cppGDAL目錄下的文件了——連文件、數據都無法獲取,那么這個GDAL鏡像肯定也是沒有用處的了。

??此外,前面我們還提到,-v /home/dell/cppGDAL:/home/dell/cppGDAL這一個部分可以保證鏡像可以且僅可以讀取/home/dell/cppGDAL目錄下的文件,而不會讀取到我們沒有掛載的其他文件夾。針對這一個內容,我們再做一個對比。如下圖所示,是我們直接在Ubuntu電腦的終端中,進入/home/dell目錄的情況;可以很明顯地看到,在電腦中的/home/dell目錄下,不僅有我們的這個cppGDAL文件夾,還有很多很多其他的文件或者文件夾;而在上上圖中,可以看到在容器中,我們進入/home/dell/cppGDAL目錄下只能看到這個cppGDAL文件夾,而看不到電腦中這一路徑下原本還有的其他文件或者文件夾。所以很明顯,相當于我們就是可以在鏡像中訪問/home/dell/cppGDAL目錄,但是無法訪問沒有掛載的其他文件夾,從而保證了其他無關文件夾的安全性。

??明白了上述內容,就可以開始我們的GDAL操作了。例如,我這里在/home/dell/cppGDAL目錄下還有一個名稱為TIF的文件夾,其中保存了一景遙感影像,那么我就可以通過gdalinfo語句,查看這一柵格數據的信息。如下圖所示。

??最后,每一次完成鏡像中的操作后,不要忘記通過exit命令,退出鏡像。

??因為我這里是需要C++版本的GDAL模塊,所以后來也就沒有對上述Python版本的再加以代碼測試;但經過上述配置,運行Python代碼的GDAL程序應該是沒有問題了。

2 C++版本

??接下來,我們介紹配置C++版本的GDAL模塊的方法。

??由于GDAL官方似乎并未提供直接的C++版本鏡像,所以我們這里就自己創建一個Docker鏡像,隨后在其中配置GDAL模塊。這里需要注意,如果大家剛剛根據前文的流程,先配置了一個Python語言的GDAL模塊的鏡像,那么建議大家在另一個新的鏡像內重新配置C++版本的,不要直接在前面的Python語言鏡像中配置GDAL模塊——因為官網說,在前面這個Python語言的GDAL模塊的鏡像內配置其他版本的GDAL模塊,會容易由于GDAL模塊的版本沖突導致容器無法工作(雖然我當時簡單嘗試了一下,發現即使如此,容器似乎還是可以正常工作的)。

??我們這里就在一個新的Ubuntu鏡像中加以配置。首先,在終端中輸入如下代碼,創建一個Ubuntu鏡像。

docker pull ubuntu

??運行上述代碼,如下圖所示。

??接下來,我們用前文提到的這一句代碼,運行一個容器。這里我就不再用--rm了,從而使得我們這個容器之后可以多次重復使用。

docker run -it -v /home/dell/cppGDAL:/home/cppGDAL ubuntu:latest

??運行上述代碼,如下圖所示。

??接下來,因為我們這個容器是基于一個空白的Ubuntu鏡像創建的,很多執行GDALC++代碼所需的配置都沒有處理,我們需要配置一下基本的環境。

??首先,通過如下代碼更新軟件包列表

apt update

??運行上述代碼,如下圖所示。

??隨后,輸入如下的代碼,配置GDAL模塊的C++庫。其中,libpq-devPostgreSQL數據庫的開發庫,包含了開發PostgreSQL應用程序所需的頭文件和靜態庫;gdal-binGDAL的二進制工具包,提供了一些用于處理地理空間數據的工具,如轉換、裁剪等;libgdal-devGDAL的開發庫,包含了開發GDAL應用程序所需的頭文件和靜態庫。

apt install libpq-dev gdal-bin libgdal-dev

??運行上述代碼,如下圖所示。

??稍等片刻,中間有一個環節需要我們根據自己所在位置加以選擇,從而配置自己的時區;如下圖所示。

??完成配置后,通過如下的代碼查看GDAL庫的版本。

gdalinfo --version

??運行上述代碼,如下圖所示。

??接下來,我們再按照文章在Linux系統cmd配置C++環境的方法介紹的方法,配置UbuntuC++代碼開發環境,這里就不再贅述了。

??隨后,我們就可以在Docker中執行一個簡單的C++程序,來驗證這個GDAL庫的配置是否成功。其中,我們因為已經掛載了文件夾,所以既可以在主機中通過其他編輯器來撰寫這個C++代碼,也可以在容器中通過Vim來撰寫。但無論怎么撰寫,都要記得將這個代碼文件(也就是.cpp格式的文件)放在已經掛載了的文件路徑內。

??這個簡單的C++代碼如下;其含義就是,從我們已經掛載了的主機的一個文件夾中,讀取一景柵格影像,獲取并打印其像元的行數與列數。

#include <iostream>
#include <gdal/gdal.h>
#include <gdal/gdal_priv.h>
using namespace std;

int main() {
    const char* image_path = "/home/cppGDAL/TIF/LAI_A2000057_h30v05.tif";
    GDALAllRegister();
    GDALDataset* dataset = (GDALDataset*)GDALOpen(image_path, GA_ReadOnly);
    if (dataset != nullptr)
    {
        int rows = dataset->GetRasterYSize();
        int cols = dataset->GetRasterXSize();

        printf("Rows: %d\n", rows);
        printf("Cols: %d\n", cols);

        GDALClose(dataset);
    }
    return 0;
}

??隨后,在容器內的上述代碼文件目錄下,執行如下的代碼。

g++ `gdal-config --cflags` rec.cpp  `gdal-config --libs` `gdal-config --dep-libs` -o test

??其中,g++GNU C++編譯器的命令,用于編譯和鏈接C++代碼。gdal-config --cflags表示使用gdal-config命令獲取GDAL庫的編譯選項,包括頭文件路徑和其他必要的編譯標志;--cflags參數告訴gdal-config命令返回編譯選項。rec.cpp是要編譯的C++源文件的文件名,也就是前面我們寫的代碼文件的文件名稱。需要注意的是,上述代碼中沒有單引號,而都是反引號,大家輸入的時候不要輸錯了。

??其次,gdal-config --libs使用gdal-config命令來獲取GDAL庫的鏈接選項,包括庫文件路徑和其他必要的鏈接標志;--libs參數告訴gdal-config命令返回鏈接選項。gdal-config --dep-libs使gdal-config命令來獲取GDAL庫所依賴的其他庫的鏈接選項;--dep-libs參數告訴gdal-config命令返回依賴庫的鏈接選項。

??最后,-o test是編譯器選項,用于指定生成的可執行文件的名稱為test-o選項后跟著要生成的可執行文件的名稱。

??完成上述步驟,在當前目錄下就會有一個可執行文件,名稱為test。我們執行如下的代碼,就可以執行這個可執行文件

./test

??運行上述代碼,如下圖所示。

??可以看到,已經可以打印出這一景遙感影像的像元行數與列數了。

??至此,大功告成。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,923評論 6 535
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,740評論 3 420
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,856評論 0 380
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,175評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,931評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,321評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,383評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,533評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,082評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,891評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,067評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,618評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,319評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,732評論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,987評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,794評論 3 394
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,076評論 2 375

推薦閱讀更多精彩內容