偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

面向開發(fā)人員的鏡像和容器實(shí)踐指南

譯文 精選
數(shù)據(jù)庫
了解鏡像和容器背后的關(guān)鍵概念。然后嘗試演示一個(gè)構(gòu)建和運(yùn)行鏡像和容器的實(shí)驗(yàn)。

容器和Open Container Initiative (OCI)是重要的開源應(yīng)用程序打包和交付技術(shù), Docker 和 Kubernetes 等項(xiàng)目使其流行起來。您對它們理解得越好,就越能夠使用它們來增強(qiáng)項(xiàng)目的一致性和可伸縮性。

在本文中,我將用簡單的術(shù)語描述這項(xiàng)技術(shù),重點(diǎn)介紹鏡像和容器的基本方面以供開發(fā)人員理解,然后討論開發(fā)人員可以遵循的一些最佳實(shí)踐,以使他們的容器可移植。我還將引導(dǎo)您完成一個(gè)簡單的實(shí)驗(yàn),該實(shí)驗(yàn)將演示如何構(gòu)建和運(yùn)行鏡像和容器。

什么是鏡像?

鏡像只不過是軟件的一種打包格式。一個(gè)很好的類比是 Java 的 JAR 文件或 Python 輪子。JAR(或 EAR 或 WAR)文件只是具有不同擴(kuò)展名的 ZIP 文件,Python 輪子作為 gzip 壓縮包分發(fā)。它們都遵循一個(gè)標(biāo)準(zhǔn)的內(nèi)部目錄結(jié)構(gòu)。

鏡像被打包為tar.gz(gzipped tarballs),它們包括您正在構(gòu)建或分發(fā)的軟件,但也就是僅有這點(diǎn)與 JAR 和輪子能夠類比的地方。一方面,鏡像不僅包含您的軟件,還包含運(yùn)行您的軟件所需的所有支持依賴項(xiàng),包括一個(gè)完整的操作系統(tǒng)。輪子和jar通常是作為依賴項(xiàng)構(gòu)建的,但也可以是可執(zhí)行的,而鏡像幾乎總是構(gòu)建為可執(zhí)行的,很少作為依賴項(xiàng)構(gòu)建。

了解鏡像中內(nèi)容的詳細(xì)信息對于了解如何使用鏡像或?yàn)樗鼈兙帉懞驮O(shè)計(jì)軟件并不是必要的。從軟件的角度來看,重要的是要理解您創(chuàng)建的鏡像將包含一個(gè)完整的操作系統(tǒng)。因?yàn)閺哪M\(yùn)行的軟件的角度來看,鏡像被打包成一個(gè)完整的操作系統(tǒng),所以它們必然比以更傳統(tǒng)方式打包的軟件大得多。

請注意,鏡像是不可變的。它們一旦構(gòu)建就無法更改。如果您修改鏡像上運(yùn)行的軟件,就必須構(gòu)建一個(gè)全新的鏡像并替換舊鏡像。

標(biāo)簽

在鏡像被創(chuàng)建時(shí),通常都會(huì)使用一個(gè)唯一的哈希值來創(chuàng)建,但也會(huì)使用人類可讀的名稱標(biāo)識它們。例如ubi、ubi-minimal、openjdk11等。但是,每個(gè)名稱都可以有不同版本的鏡像,并且通常通過標(biāo)簽來區(qū)分。例如,openjdk11鏡像可能被標(biāo)記為jre-11.0.14.1_1-ubi和jre-11.0.14.1_1-ubi-minimal,分別表示openjdk11軟件包版本11.0.14.1_1基于Red Hat ubi和ubi最小鏡像構(gòu)建的鏡像。

什么是容器?

容器是在主機(jī)系統(tǒng)上實(shí)例化并運(yùn)行的鏡像。從鏡像到運(yùn)行容器分為兩步:創(chuàng)建和啟動(dòng)。創(chuàng)建獲取鏡像并為其提供自己的 ID 和文件系統(tǒng)。Create(例如在docker Create中)可以重復(fù)多次,以創(chuàng)建一個(gè)鏡像的多個(gè)運(yùn)行實(shí)例,每個(gè)實(shí)例都有自己的 ID 和文件系統(tǒng)。啟動(dòng)容器將在主機(jī)上啟動(dòng)一個(gè)隔離的進(jìn)程,在容器中運(yùn)行的軟件將表現(xiàn)得就像運(yùn)行在自己的虛擬機(jī)中一樣。因此,容器是主機(jī)上的一個(gè)獨(dú)立的進(jìn)程,具有自己的 ID 和獨(dú)立的文件系統(tǒng)。

從軟件開發(fā)人員的角度來看,使用容器有兩個(gè)主要原因:一致性和可伸縮性。這些是相互關(guān)聯(lián)的,它們共同允許項(xiàng)目使用近年來最有前途的軟件開發(fā)創(chuàng)新之一,即“一次構(gòu)建,多次部署”的原則。

一致性

因?yàn)殓R像是不可變的,并且包含了從操作系統(tǒng)上運(yùn)行軟件所需的所有依賴項(xiàng),所以無論您選擇在何處部署它,都可以獲得一致性。這意味著無論您在開發(fā)、測試或任何數(shù)量的生產(chǎn)環(huán)境中將鏡像作為容器啟動(dòng),容器都將以完全相同的方式運(yùn)行。作為軟件開發(fā)人員,您不必?fù)?dān)心這些環(huán)境是否運(yùn)行在不同的主機(jī)操作系統(tǒng)或版本上,因?yàn)槿萜髅看味歼\(yùn)行相同的操作系統(tǒng)。這就是將軟件與其完整的運(yùn)行時(shí)環(huán)境一起打包的好處,而不僅僅是因?yàn)槿狈Ρ匦璧沫h(huán)境或依賴軟件,而無法運(yùn)行的軟件。

這種一致性意味著在幾乎所有情況下,當(dāng)在一個(gè)環(huán)境(例如,生產(chǎn)環(huán)境)中發(fā)現(xiàn)問題時(shí),您可以確信自己能夠在開發(fā)或其他環(huán)境中重現(xiàn)該問題,因此您可以確認(rèn)行為并專注于修復(fù)它。您的項(xiàng)目永遠(yuǎn)不應(yīng)該再次陷入“但是它可以在我的機(jī)器上工作”的可怕問題。

可伸縮性

鏡像不僅包含您的軟件,還包含運(yùn)行您的軟件所需的所有依賴項(xiàng),包括底層操作系統(tǒng)。這意味著在容器內(nèi)運(yùn)行的所有進(jìn)程都將容器視為宿主系統(tǒng),宿主系統(tǒng)對容器內(nèi)運(yùn)行的進(jìn)程是不可見的,并且從宿主系統(tǒng)的角度來看,容器只是它管理的另一個(gè)進(jìn)程。當(dāng)然,虛擬機(jī)做的事情幾乎一樣,這就提出了一個(gè)合理的問題:為什么要使用容器技術(shù)而不是虛擬機(jī)?答案在于速度和規(guī)模。

容器只需運(yùn)行支持獨(dú)立主機(jī)所需的軟件,而無需模擬硬件的開銷。虛擬機(jī)必須包含完整的操作系統(tǒng)并模仿底層硬件。后者是一個(gè)非常重量級的解決方案,它也會(huì)產(chǎn)生更大的文件。因?yàn)閺闹鳈C(jī)系統(tǒng)的角度來看,容器只是另一個(gè)正在運(yùn)行的進(jìn)程,所以它們可以在幾秒鐘內(nèi)而不是幾分鐘內(nèi)啟動(dòng)。當(dāng)您的應(yīng)用程序需要快速擴(kuò)容時(shí),容器每次都會(huì)在資源和速度上擊敗虛擬機(jī)。而且容器也更容易收縮。

從功能的角度來看,可伸縮性超出了本文的范圍,因此本實(shí)驗(yàn)不會(huì)演示該特性,但是為了理解為什么容器技術(shù)代表了軟件打包和部署方面的重大進(jìn)步,理解該原理是很必要的。

注意:雖然可以運(yùn)行不包含完整操作系統(tǒng)的容器,但很少這樣做,因?yàn)榭捎玫淖钚$R像可能會(huì)引發(fā)其它問題。

如何發(fā)現(xiàn)和存儲鏡像

與所有其他類型的軟件打包技術(shù)一樣,容器也需要一個(gè)可以共享、發(fā)現(xiàn)和重用的地方。這些被稱為鏡像注冊表,類似于 Java Maven 和 Python 輪子存儲庫或 npm 注冊表。

以下是互聯(lián)網(wǎng)上可用的不同鏡像注冊表的例子:

Docker Hub: 最初的Docker注冊表,托管了許多在世界各地項(xiàng)目中廣泛使用的Docker官方鏡像,并為個(gè)人提供托管自己鏡像的機(jī)會(huì)。如adoptopenjdk就是在Docker Hub上托管鏡像的組織之一;可以點(diǎn)擊openjdk11查看其存儲倉庫以獲取該組織項(xiàng)目鏡像和標(biāo)簽示例。

Red Hat Image Registry: 紅帽的官方鏡像注冊表,為那些有效紅帽訂閱者提供鏡像。

Quay: Red Hat 的公共鏡像注冊表托管了許多 Red Hat 的公共可用鏡像,并為個(gè)人提供了托管自己的鏡像的機(jī)會(huì)。

使用鏡像和容器

有兩個(gè)實(shí)用程序用于管理鏡像和容器:Docker和Podman。它們可用于 Windows、Linux 和 Mac 工作站。從開發(fā)人員的角度來看,它們在執(zhí)行命令時(shí)是完全等價(jià)的。它們可以被認(rèn)為是彼此的別名。您甚至可以在許多系統(tǒng)上安裝一個(gè)包,它會(huì)自動(dòng)將 Docker 更改為 Podman 別名。本文檔中無論在哪里提到 Podman,都可以安全地替換 Docker,而不會(huì)改變結(jié)果。

您會(huì)立即注意到這些實(shí)用程序與 Git 非常相似,因?yàn)樗鼈儓?zhí)行標(biāo)簽、推送和拉取操作。您將經(jīng)常使用或引用此功能。然而,它們不應(yīng)與 Git 混淆,因?yàn)?Git 也管理版本控制,而鏡像是不可變的,它們的管理實(shí)用程序和注冊表沒有變更管理的概念。如果您將兩個(gè)具有相同名稱和標(biāo)簽的鏡像推送到同一個(gè)存儲庫,則第二個(gè)鏡像將覆蓋第一個(gè)鏡像,而無法查看或理解發(fā)生了什么變化。

子命令

下面是你會(huì)經(jīng)常使用或引用的Podman和Docker子命令的例子:

build: 構(gòu)建鏡像

例子: podman build -t org/some-image-repo -f Dockerfile

image: 本地鏡像管理

例子: podman image rm -a 刪除所有本地鏡像

images: 列出本地存儲的鏡像

tag: 為鏡像打標(biāo)簽

container: 容器管理

例子: podman container rm -a 刪除所有已停止的容器

run: 創(chuàng)建并啟動(dòng)一個(gè)容器

還有 stop and restart

 pull/push: 從/向注冊表上的存儲庫拉/推和鏡像

Dockerfiles

Dockerfile 是定義鏡像的源文件,并使用build子命令進(jìn)行處理。該文件將定義一個(gè)父鏡像或基礎(chǔ)鏡像,復(fù)制或安裝您希望在鏡像中運(yùn)行的任何額外軟件,定義在構(gòu)建或運(yùn)行軟件過程中使用到的任何額外元數(shù)據(jù),并有可能指定一個(gè)命令,該命令在鏡像實(shí)例化為容器后會(huì)立即執(zhí)行。下面的實(shí)驗(yàn)對 Dockerfile 的結(jié)構(gòu)以及其中使用的一些更常用的命令進(jìn)行了更詳細(xì)的描述。

Docker 和 Podman 的根本區(qū)別

Docker是類unix系統(tǒng)中的守護(hù)進(jìn)程,是Windows系統(tǒng)中的服務(wù)。這意味著它一直在后臺運(yùn)行,并且具有root或管理員權(quán)限。Podman是二進(jìn)制的。這意味著它只能按需運(yùn)行,并且可以作為非特權(quán)用戶運(yùn)行。

這使得Podman對系統(tǒng)資源更安全、更高效。根據(jù)定義,以 root 權(quán)限運(yùn)行任何東西都不太安全。在云端使用鏡像時(shí),托管容器的云可以更安全地管理鏡像和容器。

Skopeo 和 Buildah

和 Docker 是一個(gè)單一的實(shí)用程序不同,Podman 在 GitHub 上有兩個(gè)由 Containers 組織維護(hù)的相關(guān)實(shí)用程序:Skopeo和Buildah。兩者都提供 Podman 和 Docker 不具備的功能,并且都是與Podman一起安裝在Red Hat系列Linux發(fā)行版上的容器工具包組的一部分。

在大多數(shù)情況下,鏡像構(gòu)建可以通過 Docker 和 Podman 執(zhí)行,但 Buildah 存在以防需要更復(fù)雜的鏡像構(gòu)建。這些更復(fù)雜的構(gòu)建的細(xì)節(jié)遠(yuǎn)遠(yuǎn)超出了本文的范圍,你很少會(huì)遇到需要它,但為了完整起見,我在這里提到了這個(gè)實(shí)用程序。

Skopeo 提供了 Docker 沒有的兩個(gè)實(shí)用功能:將鏡像從一個(gè)注冊表復(fù)制到另一個(gè)注冊表的能力以及從遠(yuǎn)程注冊表中刪除鏡像的能力。同樣,此功能超出了本次討論的范圍,但該功能最終可能對您有用,尤其是在您需要編寫一些 DevOps 腳本時(shí)。

Dockerfiles 實(shí)驗(yàn)

以下是一個(gè)非常短的實(shí)驗(yàn)(大約 10 分鐘),它將教您如何使用 Dockerfiles 構(gòu)建鏡像并將這些鏡像作為容器運(yùn)行。它還將演示如何將容器配置外部化,以實(shí)現(xiàn)容器開發(fā)的全部優(yōu)勢和“一次構(gòu)建,多次部署”。

安裝

以下實(shí)驗(yàn)室是在本地運(yùn)行 Fedora 并在已安裝 Podman 和 Git的Red Hat 沙盒環(huán)境中創(chuàng)建和測試的。我相信在Red Hat沙箱環(huán)境中運(yùn)行它會(huì)讓您從這個(gè)實(shí)驗(yàn)中獲得最大的收獲,但是在本地運(yùn)行它也是完全可以接受的。

您還可以在自己的工作站上安裝 Docker 或 Podman 并在本地工作。提醒一下,如果您安裝了 Docker,podman 和 docker對于這個(gè)實(shí)驗(yàn)來說是完全可以互換的。

構(gòu)建鏡像

1. 從 GitHub 克隆 Git 存儲庫:

$ git clone https://github.com/hippyod/hello-world-container-lab

2. 編輯 Dockerfile:

$ cd hello-world-container-lab
$ vim Dockerfile
1 FROM Docker.io/adoptopenjdk/openjdk11:x86_64-ubi-minimal-jre-11.0.14.1_1
2
3 USER root
4
5 ARG ARG_MESSAGE_WELCOME='Hello, World'
6 ENV MESSAGE_WELCOME=${ARG_MESSAGE_WELCOME}
7
8 ARG JAR_FILE=target/*.jar
9 COPY ${JAR_FILE} app.jar
10
11 USER 1001
12
13 ENTRYPOINT ["java", "-jar", "/app.jar"]

這個(gè)Dockerfile有以下特性:

FROM 語句(第 1 行)定義了構(gòu)建這個(gè)新鏡像的基礎(chǔ)(或父)鏡像。

USER 語句(第 3 行和第 11 行)定義了在構(gòu)建期間和執(zhí)行時(shí)正在運(yùn)行的用戶。起初,root 在構(gòu)建過程中運(yùn)行。在更復(fù)雜的 Dockerfile 中,我需要 root 才能安裝任何額外的軟件、更改文件權(quán)限等等,以完成新鏡像。在 Dockerfile 結(jié)束時(shí),我切換到 UID 為 1001 的用戶,這樣,每當(dāng)鏡像實(shí)例化為容器并執(zhí)行時(shí),用戶將不是 root,因此更安全。使用 UID 而不是用戶名,以便主機(jī)可以識別哪個(gè)用戶正在容器中運(yùn)行,以防主機(jī)加強(qiáng)了安全措施,阻止容器用root用戶運(yùn)行。

 ARG 語句(第 5 行和第 8 行)定義了只能在構(gòu)建過程中使用的變量。

 ENV 語句(第 6 行)定義了一個(gè)環(huán)境變量和值,可以在構(gòu)建過程中使用,但也可以在鏡像作為容器運(yùn)行時(shí)使用。請注意它是如何通過引用前面 ARG 語句定義的變量來獲取其值的。

COPY 語句(第 9 行)將 Spring Boot Maven 構(gòu)建創(chuàng)建的 JAR 文件復(fù)制到鏡像中。為了方便在未安裝 Java 或 Maven 的 Red Hat 沙箱中運(yùn)行的用戶,我預(yù)先構(gòu)建了 JAR 文件并將其推送到 hello-world-container-lab 存儲庫。在本實(shí)驗(yàn)室中無需進(jìn)行 Maven 構(gòu)建。(注意:還有一個(gè)add命令可以替代 COPY。由于該add命令可能具有不可預(yù)知的行為,因此最好使用 COPY。)

最后,ENTRYPOINT 語句定義了容器啟動(dòng)時(shí)應(yīng)該在容器中執(zhí)行的命令和參數(shù)。如果此鏡像成為后續(xù)鏡像定義的基礎(chǔ)鏡像并且定義了新的 ENTRYPOINT,它將覆蓋此鏡像。(注意:還有一個(gè)cmd命令可以代替 ENTRYPOINT。兩者之間的區(qū)別在此本文中無關(guān)緊要,超出了本文的范圍。)

鍵入:q并按Enter退出 Dockerfile 并返回到 shell。

3. 構(gòu)建鏡像:

$ podman build --squash -t test/hello-world -f Dockerfile

你應(yīng)該看到:

STEP 1: FROM docker.io/adoptopenjdk/openjdk11:x86_64-ubi-minimal-jre-11.0.14.1_1
Getting image source signatures
Copying blob d46336f50433 done
Copying blob be961ec68663 done
...
STEP 7/8: USER 1001
STEP 8/8: ENTRYPOINT ["java", "-jar", "/app.jar"]
COMMIT test/hello-world
...
Successfully tagged localhost/test/hello-world:latest
5482c3b153c44ea8502552c6bd7ca285a69070d037156b6627f53293d6b05fd7

除了構(gòu)建鏡像之外,這些命令還提供了以下說明:

--squash標(biāo)志將通過確保在鏡像構(gòu)建完成時(shí)僅向基礎(chǔ)鏡像添加一層來減小鏡像大小。多余的層會(huì)使最后生成的鏡像變得更大。FROM、RUN 和 COPY/ADD 語句都會(huì)添加一層,最佳實(shí)踐是在可能的情況下連接這些語句,例如:

RUN dnf -y --refresh update && \
dnf install -y --nodocs podman skopeo buildah && \
dnf clean all

上面的 RUN 語句不僅會(huì)運(yùn)行每個(gè)語句才僅創(chuàng)建一個(gè)層,而且如果其中任何一個(gè)失敗,也會(huì)使構(gòu)建失敗。

-t 用于命名鏡像。因?yàn)槲覜]有顯式地定義名稱的標(biāo)簽(如test/hello-world:1.0),所以默認(rèn)將鏡像標(biāo)記為latest。我也沒有定義注冊表(如quay.io/test/hello-world),所以默認(rèn)的注冊表將是 localhost。

-f 標(biāo)志用于明確聲明要構(gòu)建的 Dockerfile。

當(dāng)運(yùn)行構(gòu)建時(shí),Podman 將跟蹤“blob”的下載。這些是您的鏡像將建立的鏡像層。它們最初是從遠(yuǎn)程注冊表中提取的,它們將被緩存在本地以加速未來的構(gòu)建。

Copying blob d46336f50433 done  
Copying blob be961ec68663 done
...
Copying blob 744c86b54390 skipped: already exists
Copying blob 1323ffbff4dd skipped: already exists

4. 當(dāng)構(gòu)建完成時(shí),列出鏡像以確認(rèn)它已成功構(gòu)建:

$ podman images

你應(yīng)該看到:

REPOSITORY                                        TAG                                                      IMAGE ID      CREATED               SIZE
localhost/test/hello-world latest 140c09fc9d1d 7 seconds ago 454 MB
docker.io/adoptopenjdk/openjdk11 x86_64-ubi-minimal-jre-11.0.14.1_1 5b0423ba7bec 22 hours ago 445 MB

運(yùn)行容器

5. 運(yùn)行鏡像:

$ podman run test/hello-world

你應(yīng)該看到:

.   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.4)

...
GREETING: Hello, world
GREETING: Hello, world

輸出將繼續(xù)每三秒打印"Hello, world",直到退出:

crtl-c

6. 證明Java只安裝在容器中:

$ java -version

在容器內(nèi)運(yùn)行的 Spring Boot 應(yīng)用程序需要 Java 才能運(yùn)行,這也是我選擇基礎(chǔ)鏡像的原因。如果您在Red Hat 沙盒環(huán)境中運(yùn)行這個(gè)實(shí)驗(yàn),這也證明 Java 僅安裝在容器中,而不是主機(jī)上:

-bash: java: command not found...

外部化配置

鏡像現(xiàn)在已構(gòu)建,但是當(dāng)我希望將鏡像部署到每個(gè)環(huán)境中的“Hello, world”消息都不同時(shí)會(huì)發(fā)生什么?例如,我可能想要更改它,因?yàn)榄h(huán)境是針對不同的開發(fā)階段或不同的語言環(huán)境。如果我更改 Dockerfile 中的值,我需要構(gòu)建一個(gè)新鏡像才能看到消息,這破壞了容器最基本的好處之一——“一次構(gòu)建,多次部署”。那么如何使我的鏡像真正可移植,以便可以將其部署在我需要的任何地方呢?答案在于外部化配置。

7. 使用新的外部歡迎消息運(yùn)行鏡像:

$ podman run -e 'MESSAGE_WELCOME=Hello, world DIT' test/hello-world

你應(yīng)該看到:

Output:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.4)
...
GREETING: Hello, world DIT
GREETING: Hello, world DIT

通過使用crtl-c停止,并調(diào)整消息后重新執(zhí)行:

$ podman run -e 'MESSAGE_WELCOME=Hola Mundo' test/hello-world
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.4)
...
GREETING: Hola Mundo
GREETING: Hola Mundo

-e標(biāo)志定義了在啟動(dòng)時(shí)注入容器的環(huán)境變量和值。如您所見,即使該變量已內(nèi)置到原始鏡像中(Dockerfile 中的語句ENV MESSAGE_WELCOME=${ARG_MESSAGE_WELCOME}),它也會(huì)被覆蓋。現(xiàn)在,您已經(jīng)外部化了需要根據(jù)部署位置進(jìn)行更改的數(shù)據(jù)(例如,在DIT環(huán)境中或針對說西班牙語的用戶),從而使鏡像具有可移植性。

8. 使用文件中定義的新消息運(yùn)行鏡像:

$ echo 'Hello, world from a file' > greetings.txt
$ podman run -v "$(pwd):/mnt/data:Z" \
-e 'MESSAGE_FILE=/mnt/data/greetings.txt' test/hello-world

運(yùn)行這個(gè)例子,您應(yīng)該看到:

.   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.4)
...
GREETING: Hello, world from a file
GREETING: Hello, world from a file

重復(fù),直到按ctrl -c停止

在這種情況下,-e標(biāo)志定義了/mnt/data/greetings.txt 的文件路徑,該路徑通過-v 標(biāo)志從主機(jī)的本地文件系統(tǒng)$(pwd)/greetings.txt(pwd是一個(gè) bash 實(shí)用程序,輸出當(dāng)前目錄的絕對路徑,在您的情況下應(yīng)該是hello-world-container-lab)掛載到容器中?,F(xiàn)在,您已經(jīng)外部化了需要根據(jù)部署位置更改的數(shù)據(jù),但這一次數(shù)據(jù)是在掛載到容器中的外部文件中定義的。如果環(huán)境變量數(shù)量不多,那么直接在命令行設(shè)置是可以的,但是當(dāng)您要設(shè)置好幾個(gè)環(huán)境變量時(shí),使用文件將環(huán)境變量注入容器是更有效的方式。

注意::Z上述卷定義末尾的標(biāo)志適用于使用SELinux的系統(tǒng)。SELinux 管理許多 Linux 發(fā)行版上的安全性,并且該標(biāo)志允許容器訪問目錄。如果沒有這個(gè)標(biāo)志,SELinux 會(huì)阻止讀取文件,并且容器中會(huì)拋出異常。刪除:Z標(biāo)記后再次嘗試運(yùn)行上面的命令以查看演示。

實(shí)驗(yàn)到此結(jié)束。

容器開發(fā):外部化配置

“一次構(gòu)建,多次部署”之所以有效,是因?yàn)樵诓煌h(huán)境中運(yùn)行的不可變?nèi)萜鞑槐負(fù)?dān)心支持特定軟件項(xiàng)目所需的硬件或軟件的差異。這一原則使軟件開發(fā)、調(diào)試、部署和持續(xù)維護(hù)變得更快、更容易。它也不是完美的,必須在編寫代碼的方式上進(jìn)行一些小的更改,才能使容器真正可移植。

為容器化編寫軟件時(shí),最重要的設(shè)計(jì)原則是決定要外部化什么。這些決定最終使您的鏡像可移植,因此它們可以完全實(shí)現(xiàn)“一次構(gòu)建,多次部署”的范例。盡管這看起來很復(fù)雜,但在決定配置數(shù)據(jù)是否應(yīng)該注入到運(yùn)行的容器中時(shí),有一些容易記住的因素需要考慮:

數(shù)據(jù)環(huán)境是否特定的?這包括任何需要根據(jù)容器運(yùn)行位置配置的數(shù)據(jù),無論環(huán)境是生產(chǎn)環(huán)境、非生產(chǎn)環(huán)境還是開發(fā)環(huán)境。此類數(shù)據(jù)包括國際化配置、數(shù)據(jù)存儲信息以及您希望應(yīng)用程序在其下運(yùn)行的特定測試配置文件。

數(shù)據(jù)發(fā)布是否獨(dú)立? 這種類型的數(shù)據(jù)可以運(yùn)行從功能標(biāo)志到國際化文件再到日志級別的所有數(shù)據(jù)——基本上,您可能想要或需要在版本之間更改的任何數(shù)據(jù),而無需構(gòu)建和新部署。

數(shù)據(jù)是秘密嗎?憑證不應(yīng)被硬編碼或存儲在鏡像中。憑證通常需要在與發(fā)布時(shí)間表不匹配的時(shí)間表上刷新,并且將機(jī)密嵌入存儲在鏡像注冊表中的鏡像中存在安全風(fēng)險(xiǎn)。

最佳實(shí)踐是選擇應(yīng)該將配置數(shù)據(jù)外部化的位置(即在環(huán)境變量或文件中),并且只外部化那些滿足上述條件的部分。如果它不符合上述標(biāo)準(zhǔn),最好將其保留為不可變鏡像的一部分。遵循這些準(zhǔn)則將使您的鏡像真正可移植,并使您的外部配置保持合理的大小和可管理性。

總結(jié)

本文為剛接觸鏡像和容器的軟件開發(fā)人員介紹了四個(gè)關(guān)鍵概念和思路:

鏡像是不可變的二進(jìn)制文件:鏡像是打包軟件以便以后重用或部署的一種方法。

容器是獨(dú)立的進(jìn)程:當(dāng)它們被創(chuàng)建時(shí),容器是一個(gè)鏡像的運(yùn)行時(shí)實(shí)例。當(dāng)容器啟動(dòng)時(shí),它們成為主機(jī)上內(nèi)存中的進(jìn)程,這比虛擬機(jī)更輕、更快。在大多數(shù)情況下,開發(fā)人員只需要了解后者,但了解前者是有幫助的。

 “一次構(gòu)建,多次部署”:這個(gè)原則使容器技術(shù)如此有用。鏡像和容器提供了部署的一致性和獨(dú)立于主機(jī)的獨(dú)立性,允許您跨許多不同的環(huán)境進(jìn)行部署。由于這一原則,容器也很容易伸縮。

將配置外部化:如果您的鏡像具有特定于環(huán)境、獨(dú)立于發(fā)布或機(jī)密的配置數(shù)據(jù),請考慮將該數(shù)據(jù)置于鏡像和容器之外。您可以通過注入環(huán)境變量或?qū)⑼獠课募燧d到容器中來將此數(shù)據(jù)注入正在運(yùn)行的鏡像中。

譯者介紹

崔瑩峰,51CTO社區(qū)編輯,一名70后程序員,擁有10多年工作經(jīng)驗(yàn),長期從事 Java 開發(fā),架構(gòu)設(shè)計(jì),容器化等相關(guān)工作。精通Java,熟練使用Maven、Jenkins等Devops相關(guān)工具鏈,擅長容器化方案規(guī)劃、設(shè)計(jì)和落地。


原文標(biāo)題:A hands-on guide to images and containers for developers,作者:Evan "Hippy" Slatis

鏈接:https://opensource.com/article/22/5/guide-containers-images


責(zé)任編輯:莫奇 來源: 51CTO技術(shù)棧
相關(guān)推薦

2022-04-20 10:56:06

JavaJVM參數(shù)

2023-03-02 17:44:30

DevOps開發(fā)

2021-09-27 09:00:00

開發(fā)微服務(wù)架構(gòu)

2024-12-12 08:00:00

2025-06-06 08:36:21

2022-11-02 14:43:29

2025-02-08 11:02:57

2009-08-27 12:00:40

ibmdwJava

2022-05-16 13:58:52

開發(fā)區(qū)塊鏈Web3

2019-07-22 08:00:00

JavaGitHub編程語言

2024-02-21 08:00:00

機(jī)器學(xué)習(xí)Java大語言模型

2020-05-11 09:54:33

JavaScript開發(fā)技術(shù)

2016-01-25 09:32:37

容器網(wǎng)絡(luò)SDN

2015-02-10 09:24:04

Web開發(fā)JavaScript工具

2019-08-27 14:21:44

Python 開發(fā)程序員

2021-10-27 10:43:24

開發(fā)技能代碼

2020-08-30 14:30:33

macOS工具開發(fā)Mac

2016-10-18 10:45:00

開發(fā)開源

2018-11-26 09:55:07

MySQL誤刪數(shù)據(jù)數(shù)據(jù)庫

2012-05-17 10:03:25

.NET
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號