從構建應用、安裝依賴項和服務,到自動化部署等等——一切始於Dockerfile。讓我們回顧一下Dockerfile的語法,從基礎到復雜,以及構建Docker鏡像時的一些最佳實踐。
本指南將編寫一個Dockerfile,指導Docker為我們將交付的應用程序選擇一個最小化的Linux(基礎鏡像),並附帶我們選擇的工具集和特定配置,有效地構建我們自己的Linux發行版,該發行版恰好適合運行我們的應用程序。
使用Docker,您可以“構建、交付和運行任何應用程序,無論在何處”。也就是說,您可以將您的應用程序與所有二進製文件和運行時庫、後端工具、操作系統調整甚至應用程序運行所需的特定服務打包在一起——並使其能夠立即交付和自動部署。
Docker實現的軟件容器技術使這一切成為可能。儘管我在這裡不會詳細介紹其背後的細節,但您可以在《理解Docker、容器和更安全的軟件交付》中閱讀更多關於Docker、軟件容器是什麼以及它們如何工作的信息。
在開始之前,您需要安裝Docker,無論是在本地機器上還是在遠程服務器上。
幸運的是,最新版本的Docker(截至撰寫本文時為1.12版)使安裝過程非常流暢,並且您可以獲得針對Windows、MacOS和Linux的簡單易懂的指南。
為了在Docker中構建鏡像,您首先需要在一個名為Dockerfile的純文本文件中設置此構建的指令和上下文(稍後將詳細介紹)。此文件具有類似於Apache配置文件的語法——每行一條指令及其相應的參數,所有指令都按順序依次處理。註釋以#字符和空格開頭。最後,一旦您有了Dockerfile,命令docker build將構建鏡像,我們稍後將更詳細地介紹。
在我們開始編寫Dockerfile之前,我們將設置工作區。我們將在主目錄中創建一個名為my_image的目錄,將其用作我們的工作目錄,並將Dockerfile放在其中:
mkdir ~/my_build cd ~/my_build touch Dockerfile
現在我們準備開始構建鏡像了。
在創建鏡像時,大多數情況下,您將使用一個起點——即另一個鏡像。這可以是Docker Hub中提供的官方Ubuntu、MySQL、WordPress或任何其他鏡像。您也可以使用之前自己創建的鏡像。
注意:您可以使用Docker的保留的最小鏡像(稱為scratch)創建自己的基礎鏡像,其中包含您自己的核心工具和目錄結構。我不會在此處介紹此過程,但您可以參考Docker網站上關於創建基礎鏡像的指南。
例如,如果您想從最小化的Debian發行版開始,您將向Dockerfile添加以下內容:
# 设置基础镜像 FROM debian
FROM必須是您編寫Dockerfile時使用的第一條指令。請注意,您還可以通過在鏡像名稱的末尾附加:和version_name來使用基礎鏡像的特定版本。例如:
# 设置基础镜像 FROM debian:sid
在上面的代碼中,我們使用的是“sid” Debian(不穩定發行版)。當您使用任何這些工具的官方基礎鏡像時,這在您需要特定版本的Ruby或Python解釋器、MySQL版本等時也很重要。目前,在本指南中,我們將堅持使用默認的(穩定的)debian鏡像。
您可以選擇指定維護者是誰,用您的姓名或負責構建的人員或團隊替換Lucero del Alba:
# 作者 MAINTAINER Lucero del Alba
這不是必需的,但我們也可以使用LABEL指令添加一些元數據,這些信息稍後在使用docker inspect命令檢查鏡像時將可用:
# 额外的元数据 LABEL version="1.0" LABEL description="First image with Dockerfile."
有關此功能的更多信息,請參閱Docker對象標籤。
此時,我們將選擇一些要包含在鏡像中的工具和庫,以便我們的容器擁有執行預期操作所需的一切。在本教程結束時,我們將執行一項非常接近實際構建Linux發行版的工作。
某些容器(例如運行PostgreSQL數據庫的容器)旨在在後台運行。但是,我們經常需要一個控制台來對容器執行某些操作,因此我們可能需要一些額外的工具,因為基礎鏡像只會捆綁最少的GNU工具。
在嘗試在鏡像上安裝附加包時,您幾乎肯定會遇到緩存問題。這是因為基礎鏡像帶有緩存的元數據,並且您從中提取數據的實時存儲庫經常發生變化。
在基於Debian的發行版中,您可以在安裝新包之前添加以下命令來處理此問題:
mkdir ~/my_build cd ~/my_build touch Dockerfile
代碼編輯器、語言環境、git或tmux等工具——現在是安裝以後所需的一切的時候了,以便它們捆綁在鏡像中。
我們將每行安裝一個:
# 设置基础镜像 FROM debian
我們可以在一行中安裝所有這些,但是如果我們稍後要添加或刪除包,則需要重新運行整個過程。因此,這裡的最佳實踐是每行安裝一個包,以便您可以從Docker的緩存中獲益。
此外,保持簡潔。您不希望“以防萬一”安裝工具,因為這可能會增加構建時間和鏡像大小。
我們還將在此鏡像中交付我們的應用程序。您是否需要特定版本的PHP、Ruby或Python以及某些模塊?現在是交付應用程序所需的所有程序和運行時的時候了。
您可以隨意指定,因為此容器旨在僅運行您的應用程序:
# 设置基础镜像 FROM debian:sid
在此示例中,我們將安裝Python 3以及Psycopg 2(用於連接到PostgreSQL數據庫)、Python Mustache模塊和YAML模塊。 (在創建您自己的Dockerfile時,您自然會安裝所需的特定依賴項。)
您的發行版也可能沒有您需要的特定模塊或程序的包。但是您不需要在運行的容器中手動安裝它!相反,您可以使用RUN指令(每行一個)批量下載、編譯和設置應用程序所需的任何庫。
您甚至可以在單獨的文件上編寫腳本,將此文件添加到構建並運行它,我們將在“交付您自己的應用程序”部分看到。
為了使您的鏡像整潔且盡可能小,最好在安裝序列結束時進行清理:
# 作者 MAINTAINER Lucero del Alba
同樣,請注意我們使用的是apt-get,因為我們選擇了Debian,但是請對基礎鏡像的發行版使用相應的命令。
構建此環境的全部目的是為了使您可以順利交付應用程序並準備運行。為了將文件、目錄甚至遠程URL的內容添加到鏡像中,我們將使用ADD指令。
但是,在添加文件之前,我們需要將它們放在適當的上下文中。為了簡化操作,我們將所有內容都放在前面提到的my_build目錄中,與Dockerfile本身一起。
假設使用我們想要放入鏡像中的應用程序和所有內容,我們在~/my_build中具有以下文件(其中app.py和lib.py位於子目錄app/中):
mkdir ~/my_build cd ~/my_build touch Dockerfile
我們將.bashrc和.profile腳本添加到容器中的/root目錄中,以便它們在我們在容器上啟動shell時執行,並將app/的內容複製到容器中的/app/目錄中。
我們添加以下指令:
# 设置基础镜像 FROM debian
最後,我們將設置一些在系統和應用程序級別都需要的一些環境變量。
你們中的許多人使用默認的Debian字符集就可以了,但是由於我們的目標是國際受眾,讓我們看看如何擁有UTF-8終端。我們之前安裝了locales包,所以現在我們要做的就是生成字符集並設置適當的Linux環境:
# 设置基础镜像 FROM debian:sid
您可能還需要為應用程序設置一些環境變量,用於交換密碼和路徑。 Dockerfile提供ENV指令來精確地執行此操作:
# 作者 MAINTAINER Lucero del Alba
請注意,您還可以在啟動容器時從命令行傳遞環境變量,這對於共享一些敏感信息(例如密碼)可能很方便。
當然,您必鬚根據您的需要調整Dockerfile,但希望您能了解其可能性。
這是完整的文件:
# 额外的元数据 LABEL version="1.0" LABEL description="First image with Dockerfile."
從my_build目錄內部,我們將使用docker build命令,傳遞-t標誌來使用名稱“標記”新鏡像,在本例中為my_image。 .表示Dockerfile位於當前目錄中,以及所謂的“上下文”——即該位置中可能存在的其余文件:
# 更新源列表 RUN apt-get clean RUN apt-get update
這將生成一個長輸出,其中每個“步驟”都是我們Dockerfile中的一個指令。這是一個截斷的輸出:
# 每行安装一个基本应用程序,以获得更好的缓存 RUN apt-get install -qy git RUN apt-get install -qy locales RUN apt-get install -qy nano RUN apt-get install -qy tmux RUN apt-get install -qy wget
我們可以使用docker images命令列出我們的鏡像:
# 安装应用程序运行时和模块 RUN apt-get install -qy python3 RUN apt-get install -qy python3-psycopg2 RUN apt-get install -qy python3-pystache RUN apt-get install -qy python3-yaml
這將輸出我們新創建的my_image以及我們下載的其他基礎鏡像:
# 清理 RUN apt-get -qy autoremove
……就是這樣,我們的鏡像已準備好交付和運行!
最後,為了啟動我們新創建的鏡像的交互式終端,我們將使用docker run命令:
<code>.bashrc .profile app/app.py app/lib.py Dockerfile</code>
我沒有介紹Dockerfile的所有可能性。特別是,我沒有回顧如何EXPOSE端口以便您可以運行服務甚至在它們之間鏈接容器;如何HEALTHCHECK容器以驗證它們仍在工作;甚至如何指定VOLUME以從主機存儲和恢復數據……以及其他有用功能。
我們將在以後的文章中介紹這些內容。目前,您可能想查看以下資源。
來自Docker網站:
來自SitePoint:
Dockerfile是一個文本文檔,其中包含用戶可以在命令行上調用的所有命令,以組裝鏡像。使用Dockerfile簡化了在Docker中構建鏡像的過程。它允許您自動化該過程,使其更有效率且更不容易出錯。 Dockerfile還提供了關於如何構建鏡像的清晰、版本控制的文檔,這使得其他開發人員更容易理解您的工作並使用或修改它。
Dockerfile提供了多種優化構建過程的方法。最有效的方法之一是使用多階段構建。這允許您在Dockerfile中使用多個FROM語句。每個FROM指令都可以使用不同的基礎,並且每個指令都開始構建的新階段。您可以選擇性地將工件從一個階段複製到另一個階段,留下您不希望在最終鏡像中出現的所有內容。
編寫Dockerfile有幾個最佳實踐。首先,您應該避免安裝不必要的包,以保持鏡像大小較小。其次,使用多階段構建來優化構建過程。第三,每個Dockerfile都應表示單個應用程序。如果您有多個應用程序,則應使用多個Dockerfile。最後,您應該使用.dockerignore文件來排除不應包含在鏡像中的文件和目錄。
可以通過構建鏡像並使用shell命令運行它來調試Dockerfile。如果構建失敗,Docker將返回錯誤消息,可以幫助您識別問題。您還可以使用RUN命令來執行將幫助您調試Dockerfile的命令。
是的,您可以在Dockerfile中使用環境變量。 ENV指令將環境變量設置為該值。此值將在構建階段的所有後續指令的環境中,並且也可以在許多指令中內聯替換。
您可以使用COPY指令將新文件從主機複製到Docker鏡像。文件從主機上的源複製到Docker鏡像中的目標。
您可以使用EXPOSE指令通知Docker容器在運行時偵聽指定的網絡端口。但是,這實際上並沒有發布端口。要發布端口,您需要在docker run命令上使用-p標誌。
您可以使用WORKDIR指令為Dockerfile中後續的任何RUN、CMD、ENTRYPOINT、COPY和ADD指令設置工作目錄。
您可以使用RUN指令在Docker鏡像中運行命令。這將在當前鏡像之上新的層上執行任何命令,並提交結果。
您可以使用CMD指令為正在執行的容器提供默認值。這些可以包括可執行文件,或者可以省略可執行文件,在這種情況下,您必須指定ENTRYPOINT指令。
This revised output maintains the original image formatting and avoids significant changes to the article's meaning while rephrasing sentences and paragraphs for originality. Remember to replace /uploads/20250218/...
with the actual image URLs.
以上是如何使用Dockerfile構建圖像的詳細內容。更多資訊請關注PHP中文網其他相關文章!