Linux Ubuntu配置Python、C 下屬GDAL環境的Docker鏡像

2024年2月6日 15点热度 0人点赞

#精品長文創作季#

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

  本文就將PythonC 2種不同編程語言的GDAL模塊配置方法分開來介紹,大傢依據自己的需求來選擇即可——但無論是哪種方法,配置GDAL模塊的方法都非常簡單,終端中輸入幾句代碼就完成了。和我們之前在Windows系統中配置GDAL模塊的文章Visual Studio配置並編譯C 環境下GDAL庫、SQLite環境與PROJ庫的方法(
https://blog.csdn.net/zhebushibiaoshifu/article/details/127088090)比起來,真的是方便了很多。

1 Python版本

  首先,我們訪問GDAL庫的Docker鏡像官方網站(
https://github.com/OSGeo/gdal/tree/master/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 Ubuntu命令行快速配置C 開發環境(
https://blog.csdn.net/zhebushibiaoshifu/article/details/133006231)介紹的方法,配置
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

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

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

  至此,大功告成。

歡迎關註:瘋狂學習GIS