從0開始構建一個瀚高資料庫Docker映象

瀚高PG實驗室發表於2022-06-28

本文轉自微信公眾號“瀚高資料庫售前團隊”文章
https://mp.weixin.qq.com/s/jFASMI1rJescOQsrOm3kqQ

宣告

本文章內容僅用於學習、交流,未經瀚高資料庫售前團隊允許,不得任意修改或者增減此文章內容,不得以任何方式將其用於商業目的,利用此文所提供的資訊而造成的任何直接或間接的損失,均由使用者本人負責。

簡介
TIPS 什麼是 Docker

Docker 是一個應用打包、分發、部署的工具。

也可以把它理解為一個輕量的虛擬機器,只虛擬軟體需要的執行環境,多餘的部分都不要;而虛擬機器則是一個完整而龐大的系統,其中包含各種是不是必要的軟體。

打包:就是把軟體執行所需的依賴、第三方庫、軟體打包到一起,變成一個安裝包。
分發:可以把打包好的“安裝包”上傳到一個映象倉庫,其他人可以非常方便的獲取和安裝。
部署:拿著“安裝包”就能以一個命令執行起來應用,模擬出一模一樣的執行環境。

TIPS 容器與虛擬機器

傳統虛擬機器技術是虛擬出一套硬體後,在其上執行一個完整作業系統,在該系統上再執行所需應用程式;而容器內的應用程式直接執行於宿主的核心,容器內沒有自己的核心,而且也沒有進行硬體虛擬。因此容器要比傳統虛擬機器更為輕便。

下面的圖片比較了 Docker 和傳統虛擬化方式的不同之處。
在這裡插入圖片描述 在這裡插入圖片描述
TIPS Docker 的優勢
(1)更高效地利用系統資源。由於容器不需要進行硬體虛擬以及執行完整作業系統等額外開銷,Docker 對系統資源的利用率更高。

(2)更快速的啟動時間。Docker 容器應用,由於直接執行於宿主核心,無需啟動完整的作業系統,因此可以做到秒級啟動時間。
(3)一致的執行環境。由於開發環境、測試環境、生產環境不一致,導致有些 bug 並未在開發過程中被發現。而 Docker 的映象提供了除核心外完整的執行時環境,確保了應用執行環境一致性,從而不會再出現“這段程式碼在我機器上沒問題啊”這類問題。
(4)更輕鬆的遷移。由於 Docker 確保了執行環境的一致性,使得應用在不同平臺間的遷移更加容易。
(5)更輕鬆的維護和擴充套件。Docker 使用的分層儲存以及映象的技術,使得應用重複部分的複用更為容易,也使得應用的維護更新更加簡單,基於基礎映象進一步擴充套件映象也變得非常簡單。

TIPS Docker 的三個基本概念

一、Image

Docker 映象是一個特殊的檔案系統,除了提供容器執行時所需的程式、庫、資源、配置件外,還包含了一些為執行時準備的一些配置引數。映象不包含任何動態資料,其內容在構建之後也不會被改變。

映象採用特殊的檔案系統,設計為分層儲存的架構。映象構建時,會一層層構建,前一層是後一層的基礎。每一層構建完就不會再發生改變,後一層上的任何改變只發生在自己這一層。
在這裡插入圖片描述

採用的檔案系統參考:

二、Container

映象(Image)和容器(Container)的關係,就像是物件導向程式設計中的類和例項一樣,映象是靜態的定義,容器是映象執行時的實體。容器可以被建立、啟動、停止、刪除、暫停等。

每一個容器執行時,是以映象為基礎層,在其上建立一個當前容器的儲存層,我們可以稱這個為容器執行時讀寫而準備的儲存層為容器儲存層。

注意:任何儲存於容器儲存層的資訊都會隨容器刪除而丟失。
在這裡插入圖片描述
三、Registry

Docker Registry 是負責對映象集中儲存、分發映象的服務,分為公有服務和私有服務,一般使用公有服務 Docker Hub。一個 Docker Registry 中可以包含多個倉庫(Repository);每個倉庫可以包含多個標籤(Tag);每個標籤對應一個映象。

通常,一個倉庫會包含同一個軟體不同版本的映象,而標籤就常用於對應該軟體的各個版本。我們可以通過<倉庫名>:<標籤>的格式來指定具體是這個軟體哪個版本的映象。如果不給出標籤,將以 latest 作為預設標籤。

TIPS Docker架構

Docker 採用的是 C/S 架構,Docker client 與 Docker daemon 進行互動,Docker daemon 負責構建、執行和分發 Docker 映象。
在這裡插入圖片描述
一、Docker Daemon

Docker Daemon(dockerd)不但監聽 Docker API 的請求,並且管理著如images、containers、networks 和 volumes 等物件。

二、Docker Client

Docker Client 是使用者使用 Docker 的主要方式,可以將使用者的命令傳送給 dockerd 執行。

更詳細內容參考:

Docker 快速上手

TIPS安裝

本文安裝以 CentOS 7 虛擬機器為例,其他環境請參考官方文件

一、解除安裝舊版本

如果安裝過舊版本的 Dcoker CE,需要先解除安裝:

sudo yum remove docker \
              docker-client \
              docker-client-latest \
              docker-common \
              docker-latest \
              docker-latest-logrotate \
              docker-logrotate \
              docker-engine

二、從倉庫安裝

官網提供三種安裝方式,從 Docker 倉庫安裝、手動下載 RPM 包安裝、採用指令碼安裝。這裡採用從倉庫安裝的方法。

1.安裝 yum-utils 並設定 stable 倉庫;

sudo yum install -y yum-utils
sudo yum-config-manager \    --add-repo \
    

2.安裝最新版本 Docker Engine 和 containerd;

sudo yum install docker-ce docker-ce-cli containerd.io

3.啟動 Docker;

sudo systemctl start docker

4.通過執行 hello-world 映象檢查是否正確安裝。

sudo docker run hello-world
資料參考:

TIPS 映象命令

一、檢視映象

[root@192 ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    feb5d9fea6a5   6 months ago   13.3kB

二、拉取映象

docker pull NAME:TAG

以拉取 postgres 映象為例(未指定 TAG 預設為 latest );

[root@192 ~]# docker pull postgres
Using default tag: latest
latest: Pulling from library/postgres
a2abf6c4d29d: Pull complete
e1769f49f910: Pull complete33a59cfee47c: Pull complete461b2090c345: Pull complete8ed8ab6290ac: Pull complete495e42c822a0: Extracting [===>                                               ]  32.77kB/441.7kB18e858c71c58: Download complete594792c80d5f: Download complete794976979956: Downloading [=====================>                             ]  38.32MB/91.23MB
eb5e1a73c3ca: Download complete6d6360292cba: Download complete131e916e1a28: Download complete757a73507e2e: Download complete

拉取完成後,檢視本地已有映象。

[root@192 ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
postgres      latest    07e2ee723e2d   3 months ago   374MB
hello-world   latest    feb5d9fea6a5   6 months ago   13.3kB

三、刪除映象

docker rmi IMAGE

刪除所有映象,即:

docker rmi $(docker images -qa)
Docker 設定國內映象源可以參考:

TIPS容器命令

一、執行容器

執行容器時,如果本地沒有對應的映象,會先從倉庫拉取映象。

docker run --name pg14 -e POSTGRES_PASSWORD=qwe123 -d postgres

–name 為容器指定一個名字
-e 設定環境變數
-d 指定容器為後臺執行

具體使用的引數說明可以使用 docker run --help 檢視。

二、檢視容器

docker ps -a
[root@192 ~]# docker ps -a
CONTAINER ID   IMAGE         COMMAND                  CREATED          STATUS                      PORTS      NAMES
de77f9716542   postgres      "docker-entrypoint.s…"   4 minutes ago    Up 4 minutes                5432/tcp   pg14
ec0accd39909   hello-world   "/hello"                 36 minutes ago   Exited (0) 36 minutes ago              friendly_merkle

三、進入容器

[root@192 ~]# docker exec -it pg14 bash
root@de77f9716542:/# psql postgres postgrespsql (14.1 (Debian 14.1-1.pgdg110+1))Type "help" for help.postgres=# select version();
                                                           version-----------------------------------------------------------------------------------------------------------------------------
 PostgreSQL 14.1 (Debian 14.1-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit(1 row)postgres=# \q

-it 是以互動式執行容器中的指定應用,上面即執行 bash。

四、啟停容器

docker start CONTAINER
docker stop CONTAINER
docker restart CONTAINER

五、檢視容器詳細資訊

docker inspect NAME|ID
[root@192 ~]# docker inspect pg14[
    {
        "Id": "84bfdc303cdcd71cf640a13103c0b78576b1c0ddd73316b04ed65b38f9010b70",
        "Created": "2022-04-13T14:24:43.815894123Z",
        "Path": "docker-entrypoint.sh",
        "Args": [
            "postgres"
        ],
        "State": {
            "Status": "running",
            ......
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "672e3d3aa95c4eadf2028a33280052f920c7326bb3c36d84faff34eaebaeffdf",
                    "EndpointID": "5c749f10ab0470d588155c5e8d7f9ea07fe0bccb886f2f515ec894d773822ad4",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null                }
            }
        }
    }]

六、檢視日誌

[root@192 ~]# docker logs pg14
The files belonging to this database system will be owned by user "postgres".This user must also own the server process.The database cluster will be initialized with locale "en_US.utf8".The default database encoding has accordingly been set to "UTF8".The default text search configuration will be set to "english".Data page checksums are disabled.fixing permissions on existing directory /var/lib/postgresql/data ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default max_connections ... 100selecting default shared_buffers ... 128MB......

七、傳輸檔案

# 從主機向容器傳檔案
docker cp SRC_PATH CONTAINER:DEST_PATH
# 從容器向主機傳檔案
docker cp CONTAINER:SRC_PATH DEST_PATH

八、刪除容器

docker rm CONTAINER

刪除所有容器,即:

docker rm $(docker ps -qa)

TIPS 目錄掛載
預設情況下,容器的所有資料都被儲存在可寫層中,這意味著當容器被刪除的時候,容器中的資料也就不存在了。

Docker 提供三種資料管理的方式,附圖:
在這裡插入圖片描述
如圖所示,分別是 volume、bind mount 和 tmpfs mount,其意義有如下幾點:

1.volume 儲存在主機檔案系統中並由 Docker 管理(在Linux路徑中為 /var/lib/docker/volumes/)。
2.volume 是 Docker 中持久化資料的最好方式。
3.bind mount 可以儲存在主機上的任何地方,甚至是重要的系統檔案或目錄中。
4.tmpfs mount 僅將資料儲存在主機系統記憶體中,不會寫到主機檔案系統中。

資料參考:

下面僅介紹使用 -v/–volume 的掛載方式:

1.-v/–volume 由三個引數組成,使用:分隔,且順序必須正確;
2.對於具名掛載,第一個引數是卷名;對於匿名掛載,第一個引數可以省略;
3.第二個引數是在容器中掛載的路徑;
4.第三個引數是可選的,是一個逗號分隔的選項列表。

一、建立並管理卷

# 建立一個名為 mydata 的卷
docker volume create mydata
# 檢視已有的卷
docker volume ls
# 檢視 mydata 卷的資訊
docker volume inspect mydata
# 刪除一個卷
docker volume rm mydata
# 刪除未被使用的卷
docker volume prune

二、具名掛載

# 直接在掛載時指定卷名:容器內路徑
docker run -d --name pg14 -e POSTGRES_PASSWORD=qwe123 -v mydata:/var/lib/postgresql/data postgres
# 或提前建立好卷,然後掛載
docker volume create mydata1
docker run -d --name pg141 -e POSTGRES_PASSWORD=qwe123 -v mydata1:/var/lib/postgresql/data postgres

三、匿名掛載

# 匿名掛載在使用時直接指定容器內路徑即可,Docker 會自動建立捲進行管理
docker run -d --name pg142 -e POSTGRES_PASSWORD=qwe123 -v /var/lib/postgresql/data postgres

四、指定路徑掛載

# 在建立容器時直接指定掛載在主機上的路徑,不會自動建立卷
docker run -d --name pg143 -e POSTGRES_PASSWORD=qwe123 -v /root/my_pgdata:/var/lib/postgresql/data postgres
資料參考:

TIPS Dockerfile
Dockerfile 是一個文字檔案,其內包含了一條條的指令(Instruction),每一條指令構建一層,因此每一條指令的內容,就是描述該層應當如何構建,使用者可以使用 Dockerfile 快速建立自定義的映象。

一、FROM 指定基礎映象

定製映象,即以一個映象為基礎,在其上進行定製。FROM 就是指定基礎映象,因此一個 Dockerfile 中 FROM 是必備的指令,並且必須是第一條指令。

二、RUN 執行命令

RUN 指令是用來執行命令列命令的。由於命令列的強大能力,RUN 指令在定製映象時是最常用的指令之一。

RUN <命令>RUN ["可執行檔案", "引數1", "引數2"]

Dockerfile 中每一個指令都會建立一層,每一個 RUN 的行為,都會新建立一層,在其上執行這些命令,執行結束後,commit 這一層的修改,構成新的映象,所以不要濫用 RUN 命令。

在執行指令後進行相關的清理工作同樣是很重要的一步。前面說過,映象是多層儲存,每一層的東西並不會在下一層被刪除,會一直跟隨著映象。因此映象構建時,一定要確保每一層只新增真正需要新增的東西,任何無關的東西都應該清理掉。

三、COPY 複製檔案

COPY [--chown=<user>:<group>] <源路徑>... <目標路徑>COPY [--chown=<user>:<group>] ["<源路徑1>",... "<目標路徑>"]

COPY 指令將從構建上下文目錄中<源路徑>的檔案/目錄複製到新的一層的映象內的<目標路徑>位置。

<源路徑>可以是多個。如果源路徑為資料夾,複製的時候不是直接複製該資料夾,而是將資料夾中的內容複製到目標路徑。

<目標路徑>可以是容器內的絕對路徑,也可以是相對於工作目錄的相對路徑(工作目錄可以用 WORKDIR 指令來指定)。目標路徑不需要事先建立,如果目錄不存在會在複製檔案前先行建立缺失目錄。
四、ADD 更高階的複製檔案

ADD 指令和 COPY 的格式基本一致。

如果<源路徑>為一個 tar 壓縮檔案的話,壓縮格式為 gzip, bzip2 以及 xz 的情況下,ADD 指令將會自動解壓縮這個壓縮檔案到<目標路徑>去。

在 COPY 和 ADD 指令中選擇的時候,可以遵循這樣的原則,所有的檔案複製均使用 COPY 指令,僅在需要自動解壓縮的場合使用 ADD。

五、CMD 容器啟動命令

CMD <命令>CMD ["可執行檔案", "引數1", "引數2"...]

Docker 不是虛擬機器,容器就是程式。既然是程式,那麼在啟動容器的時候,需要指定所執行的程式及引數。CMD 指令就是用於指定預設的容器主程式的啟動命令的。

在執行時可以指定新的命令來替代映象設定中的這個預設命令。比如:

ubuntu 映象預設的 CMD 是 /bin/bash,如果我們直接 docker run -it ubuntu 的話,會直接進入 bash。

我們也可以在執行時指定執行別的命令,如 docker run -it ubuntu cat /etc/os-release。這就是用 cat /etc/os-release 命令替換了預設的 /bin/bash 命令了,輸出了系統版本資訊。

對於容器而言,其啟動程式就是容器應用程式,容器就是為了主程式而存在的,主程式退出,容器就失去了存在的意義,從而退出。

六、ENTRYPOINT 入口點

ENTRYPOINT 的格式、目的和 RUN 指令格式一樣,都是在指定容器啟動程式及引數。ENTRYPOINT 在執行時也可以替代,不過比 CMD 要略顯繁瑣,需要通過 docker run 的引數–entrypoint 來指定。

CMD 測試:

# 編寫 Dockerfile 檔案
FROM centos
CMD ["ls", "-a"]# 構建映象
docker build -t cmdtest:1.0 .# run執行,可以看到 ls -a 已經執行docker run cmdtest:1.0# 想追加一個命令引數,如果使用下面的寫法就會報錯
docker run cmdtest:1.0 -l
# 原因是 -l 替換了 CMD 的命令,而 -l 不是命令 ,就報錯了

ENTRYPOINT 測試:

# 編寫 Dockerfile 檔案
FROM centos
ENTRYPOINT ["ls", "-a"]# 構建映象
docker build -t entrypointtest:1.0 .# run 映象,同樣可以看到 ls -a 執行docker run entrypointtest:1.0# 這時候加上 -l,就不會報錯了
docker run entrypointtest:1.0 -l

七、ENV 設定環境變數

ENV <key> <value>ENV <key1>=<value1> <key2>=<value2>...

這個指令就是設定環境變數而已,無論是後面的其它指令,如 RUN,還是執行時的應用,都可以直接使用這裡定義的環境變數。

八、ARG 構建引數

ARG <引數名>[=<預設值>]

構建引數和 ENV 的效果一樣,都是設定環境變數。所不同的是,ARG 所設定的構建環境的環境變數,在將來容器執行時是不會存在這些環境變數的。但是不要因此就使用 ARG 儲存密碼之類的資訊,因為 docker history 還是可以看到所有值的。

Dockerfile 中的 ARG 指令是定義引數名稱,以及定義其預設值。該預設值可以在構建命令 docker build 中用–build-arg <引數名>=<值>來覆蓋。靈活的使用 ARG 指令,能夠在不修改 Dockerfile 的情況下,構建出不同的映象。

九、VOLUME 定義匿名卷

VOLUME ["<路徑1>", "<路徑2>"...]VOLUME <路徑>

容器執行時應該儘量保持容器儲存層不發生寫操作,對於資料庫類需要儲存動態資料的應用,其資料庫檔案應該儲存於卷(volume)中。

在 Dockerfile 中,我們可以事先指定某些目錄掛載為匿名卷,這樣在執行時如果使用者不指定掛載,其應用也可以正常執行,不會向容器儲存層寫入大量資料。

VOLUME /data,這裡的 /data 目錄就會在容器執行時自動掛載為匿名卷,當然,執行容器時可以覆蓋這個掛載設定 -v mydata:/data。

十、EXPOSE 宣告埠

EXPOSE <埠1> [<埠2>...]

宣告容器執行時提供服務的埠,這只是一個宣告,在容器執行時並不會因為這個宣告應用就會開啟這個埠的服務。

十一、WORKDIR 指定工作目錄

WORKDIR <工作目錄路徑>

使用 WORKDIR 指令可以來指定工作目錄(或者稱為當前目錄),以後各層的當前目錄就被改為指定的目錄,如該目錄不存在,WORKDIR 會幫你建立目錄。如果需要改變以後各層的工作目錄的位置,那麼應該使用 WORKDIR 指令。

十二、USER 指定當前使用者

USER <使用者名稱>[:<使用者組>]

USER 改變之後層的執行RUN,CMD 以及 ENTRYPOINT 這類命令的身份。

需要注意的是,USER 只是幫助你切換到指定使用者而已,這個使用者必須是事先建立好的,否則無法切換。

資料參考:
;https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

TIPS 構建HGDB映象

下面以構建一個瀚高資料庫安全版4.5.7的映象為例:

1.建立一個 hgdb457 目錄,把 rpm 包複製到該目錄中。

2.進入到目錄中,建立 Dockerfile 檔案,並編輯內容;

FROM centos:7
 COPY . /root
 WORKDIR /root
 ENV PGDATA=/opt/HighGo4.5.7-see/data
 RUN rpm -ivh hgdb4.5.7-see-centos7-x86-64-20211119.rpm \         && echo "export LD_LIBRARY_PATH=/usr/lib64:${LD_LIBRARY_PATH}:/opt/HighGo4.5.7-see/lib" >> /opt/HighGo4.5.7-see/etc/highgodb.env \         && source /opt/HighGo4.5.7-see/etc/highgodb.env \         && initdb -D ${PGDATA} -A md5 --pwfile=./default_password \         && chmod 0600 /opt/HighGo4.5.7-see/etc/server.* \         && cp /opt/HighGo4.5.7-see/etc/server.* ${PGDATA} \         && echo "listen_addresses = '*'" >> /opt/HighGo4.5.7-see/data/postgresql.auto.conf \         && sed -i "s/127.0.0.1\/32/0.0.0.0\/0/g" /opt/HighGo4.5.7-see/data/pg_hba.conf \         && /opt/HighGo4.5.7-see/bin/pg_ctl start -D /opt/HighGo4.5.7-see/data \         && echo "source /opt/HighGo4.5.7-see/etc/highgodb.env" >> /root/.bashrc \         && rm hgdb4.5.7-see-centos7-x86-64-20211119.rpm \         && rm default_password \         && rm Dockerfile
 VOLUME ["${PGDATA}"]
 EXPOSE 5866
 CMD ["/opt/HighGo4.5.7-see/bin/postgres"]

我們來建立 default_password 密碼檔案並編輯內容。

Hello@123
 Hello@123
 Hello@123
 ###注: 以上密碼分別為sysdba、syssao、syssso使用者的預設密碼###

3.構建映象

docker build -t hgdb457:1.0 .

執行上述命令後,使用 docker images 即可看到 hgdb457:1.0 的映象,接下來我們就可以使用這個映象來生成一個容器。

4.生成容器

docker run --name hgdb457_1 -p 5866:5866 -v hgdb_data:/opt/HighGo4.5.7-see/data --restart=always -d hgdb457:1.0

在這步中,我們使用 hgdb457:1.0 映象生成了一個名為 hgdb457_1 的容器。

其次,也將容器中的 /opt/HighGo4.5.7-see/data 掛載到了 hgdb_data 卷中,將容器的5866埠對映到主機的5866埠。

5.進入容器

執行 docker exec -it hgdb457_1 bash 即可進入容器,接著執行 psql -U sysdba -d highgo 在輸入密碼後可登入進資料庫。

這裡生成的容器就可以滿足我們的基本使用需求了。

注意:Docker 中的資料庫僅用於測試和學習,不建議用於生產環境。

現在我們有了自己的瀚高資料庫映象,如果想在其他機器的 Docker 中使用該映象,可以直接使用匯出和匯入映象的操作來完成,步驟如下:

1.儲存映象

docker save hgdb457:1.0 -o hgdb457.tar

本步可以將 hgdb457:1.0 映象匯出為 hgdb457.tar 檔案。

2.載入映象

將上一步的 hgdb457.tar 放到新的機器上,匯入為映象:

docker load -i hgdb457.tar

匯入映象完成後,使用 docker images 驗證映象是否正確,然後就可以按照之前的操作生成並使用容器了。

至此,我們已經簡單瞭解了 Docker 並可以構建一個滿足基本使用需求的瀚高資料庫映象。如果需要更多的功能,可以根據 Docker 的官方文件和瀚高資料庫的使用手冊,修改 Dockerfile 並重新構建映象。

Docker 快速上手版塊命令及幫助可參考:

本文分享到這裡就結束啦 感謝您的觀看


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69994931/viewspace-2903153/,如需轉載,請註明出處,否則將追究法律責任。

相關文章