最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Docker核心技術(shù)之Dockerfile指令詳解及綜合案例

 更新時(shí)間:2026年05月15日 10:19:54   作者:IvanCodes  
Dockerfile是一個(gè)用來構(gòu)建鏡像的文本文件, 文本內(nèi)容包含了一條條構(gòu)建鏡像所需的指令和說明,這篇文章主要介紹了Docker核心技術(shù)之Dockerfile指令詳解及綜合案例的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

在前面的章節(jié)中,我們學(xué)會(huì)了如何拉取和運(yùn)行他人構(gòu)建好的鏡像。但要真正掌握 Docker,我們必須學(xué)會(huì)創(chuàng)建屬于自己的鏡像。Dockerfile 就是實(shí)現(xiàn)這一目標(biāo)的核心工具。它就像一張自動(dòng)化的“安裝說明書”或“構(gòu)建藍(lán)圖”,讓鏡像的創(chuàng)建過程變得透明、可重復(fù)且易于版本控制

思維導(dǎo)圖

一、什么是 Dockerfile?

Dockerfile 是一個(gè)包含一系列指令的文本文件。每一條指令都對(duì)應(yīng) Docker 鏡像中的一個(gè)層。當(dāng)我們執(zhí)行 docker build 命令時(shí),Docker 會(huì)逐一執(zhí)行 Dockerfile 中的指令,最終生成一個(gè)完整的、可運(yùn)行的自定義鏡像。

核心構(gòu)建命令:

docker build -t <image_name>:<tag> .

-t: 指定新鏡像的名稱和標(biāo)簽。
.: 指定構(gòu)建上下文的路徑,通常是包含 Dockerfile 的當(dāng)前目錄。構(gòu)建上下文中的所有文件都會(huì)被發(fā)送到 Docker 守護(hù)進(jìn)程,以便在構(gòu)建過程中使用。

二、Dockerfile 核心指令詳解

以下是最常用且最重要的 Dockerfile 指令,我們將逐一解析。

FROM

作用:指定新鏡像所基于的基礎(chǔ)鏡像。

語法:FROM <image>[:<tag>] [AS <name>]

說明:FROM 指令必須是 Dockerfile 中第一條非注釋的指令。AS <name> 用于在多階段構(gòu)建中為當(dāng)前構(gòu)建階段命名。

代碼案例:

FROM ubuntu:22.04

解析:這個(gè)鏡像將基于 Ubuntu 22.04 官方鏡像進(jìn)行構(gòu)建

WORKDIR

作用:設(shè)置后續(xù) RUN, CMD, ENTRYPOINT, COPY, ADD 指令的工作目錄。

語法:WORKDIR /path/to/workdir

說明:如果目錄不存在,WORKDIR 會(huì)自動(dòng)創(chuàng)建它。使用 WORKDIR 是一個(gè)非常好的實(shí)踐,可以避免在多個(gè)指令中使用 cd 命令。

代碼案例:

WORKDIR /app

解析:此后的所有指令,如 COPY . .,都會(huì)在容器內(nèi)的 /app 目錄下執(zhí)行。

COPY 與 ADD

作用:將構(gòu)建上下文中的文件或目錄復(fù)制到鏡像的文件系統(tǒng)中。

語法:COPY [--chown=<user>:<group>] <src>... <dest>

ADD [--chown=<user>:<group>] <src>... <dest>

核心區(qū)別:

COPY: 功能純粹,就是復(fù)制文件/目錄。
ADD: 功能更豐富,除了 COPY 的功能外,還支持:
自動(dòng)解壓:如果 <src> 是一個(gè)可識(shí)別的壓縮文件 (如 tar, gzip, bzip2),ADD 會(huì)自動(dòng)將其解壓到 <dest>。
URL支持:如果 <src> 是一個(gè)URL,ADD 會(huì)嘗試下載該文件。
最佳實(shí)踐:優(yōu)先使用 COPY。因?yàn)樗男袨楦鞔_、可預(yù)測(cè)。只在確實(shí)需要自動(dòng)解壓或遠(yuǎn)程下載時(shí)才考慮使用 ADD。

代碼案例:

# 將當(dāng)前目錄下的 app.jar 復(fù)制到鏡像的 /app/ 目錄下
COPY app.jar /app/

# 將 src 目錄下的所有內(nèi)容復(fù)制到鏡像的 /app/src/ 目錄下
COPY src/ /app/src/

RUN

作用:在鏡像構(gòu)建過程中執(zhí)行命令。

語法:

RUN <command> (shell 格式)
RUN ["executable", "param1", "param2"] (exec 格式,推薦)

說明:每條 RUN 指令都會(huì)創(chuàng)建一個(gè)新的鏡像層。為了減小鏡像體積,通常建議將多個(gè)相關(guān)命令用 && 連接在同一條 RUN 指令中。

代碼案例:

# shell 格式:安裝依賴并清理緩存
RUN apt-get update && apt-get install -y wget && rm -rf /var/lib/apt/lists/*

# exec 格式:
RUN ["/bin/bash", "-c", "echo hello"]

EXPOSE

作用:聲明容器在運(yùn)行時(shí)會(huì)監(jiān)聽的網(wǎng)絡(luò)端口。

語法:EXPOSE <port> [<port>/<protocol>...]

重要說明:EXPOSE 僅僅是一個(gè)文檔性的指令,它并不會(huì)自動(dòng)將端口發(fā)布到宿主機(jī)。實(shí)際發(fā)布端口需要在運(yùn)行容器時(shí)使用 docker run -p <host_port>:<container_port> 參數(shù)。

代碼案例:

# 聲明容器將監(jiān)聽 8080 端口
EXPOSE 8080

CMD 與 ENTRYPOINT

作用:這兩個(gè)指令都用于指定容器啟動(dòng)時(shí)要執(zhí)行的命令。

指令行為語法 (推薦 exec 格式)
CMD提供容器啟動(dòng)時(shí)的默認(rèn)命令。如果 docker run 命令后面跟了其他命令,CMD 會(huì)被覆蓋。CMD ["executable", "param1", "param2"]
ENTRYPOINT配置容器使其像一個(gè)可執(zhí)行文件。docker run 后面跟的所有內(nèi)容都會(huì)被當(dāng)作參數(shù)傳遞給 ENTRYPOINT。ENTRYPOINT ["executable", "param1", "param2"]

最佳實(shí)踐 (組合使用):

使用 ENTRYPOINT 定義容器的主執(zhí)行命令,使用 CMD 提供該命令的默認(rèn)參數(shù)。

ENTRYPOINT ["java", "-jar", "app.jar"]
CMD ["--server.port=8080"]

docker run <image> -> 執(zhí)行 java -jar app.jar --server.port=8080
docker run <image> --server.port=9090 -> CMD 被覆蓋,執(zhí)行 java -jar app.jar --server.port=9090

ENV 與 ARG

作用:用于定義變量。

核心區(qū)別:

ENV: 設(shè)置環(huán)境變量。它在構(gòu)建過程中和容器運(yùn)行時(shí)都有效。
ARG: 設(shè)置構(gòu)建時(shí)變量。它只在 Dockerfile 構(gòu)建過程中有效,容器運(yùn)行后該變量不存在。

代碼案例:

ARG APP_VERSION=1.0
ENV APP_HOME=/app
ENV APP_VERSION=${APP_VERSION} # 將ARG的值持久化到ENV中

WORKDIR ${APP_HOME}
RUN echo "Building version ${APP_VERSION} in ${APP_HOME}"

其他常用指令

  • VOLUME: 創(chuàng)建一個(gè)可以掛載數(shù)據(jù)卷的掛載點(diǎn)。
  • USER: 指定后續(xù) RUN, CMD, ENTRYPOINT 指令所使用的用戶名或UID。出于安全考慮,推薦創(chuàng)建一個(gè)非root用戶來運(yùn)行應(yīng)用。
  • LABEL: 為鏡像添加元數(shù)據(jù),如 LABEL maintainer="your.email@example.com"。

三、綜合案例

這個(gè)案例將使用 多階段構(gòu)建,這是現(xiàn)代Dockerfile 的最佳實(shí)踐,可以極大地減小最終鏡像的體積

前提條件:

你有一個(gè)可以正常打包的 Spring Boot Maven 項(xiàng)目。
項(xiàng)目根目錄下有 pom.xml 和 src 目錄。
最終打包生成的 JAR 文件位于 target/ 目錄下。

步驟一:在項(xiàng)目根目錄下創(chuàng)建 Dockerfile 文件

# ---- Build Stage ----
# 使用一個(gè)包含 Maven 和 JDK 的鏡像作為構(gòu)建環(huán)境
FROM maven:3.8.3-openjdk-11 AS builder

# 設(shè)置工作目錄
WORKDIR /build

# 復(fù)制 pom.xml 并下載依賴,利用 Docker 的層緩存機(jī)制
COPY pom.xml .
RUN mvn dependency:go-offline

# 復(fù)制源代碼并進(jìn)行打包
COPY src/ ./src/
RUN mvn package -DskipTests

# ---- Runtime Stage ----
# 使用一個(gè)非常精簡(jiǎn)的、只包含Java運(yùn)行時(shí)的鏡像作為最終鏡像
FROM openjdk:11-jre-slim

# 設(shè)置工作目錄
WORKDIR /app

# 從構(gòu)建階段 (builder) 復(fù)制已打包好的 JAR 文件到當(dāng)前階段
COPY --from=builder /build/target/*.jar app.jar

# 聲明應(yīng)用將監(jiān)聽的端口
EXPOSE 8080

# 定義容器啟動(dòng)時(shí)執(zhí)行的命令
ENTRYPOINT ["java", "-jar", "app.jar"]

解析多階段構(gòu)建:

FROM ... AS builder: 定義了第一個(gè)階段,并命名為 builder。這個(gè)階段包含了所有構(gòu)建工具 (Maven, JDK),它的唯一目的是生成 app.jar 文件。
FROM openjdk:11-jre-slim: 開始一個(gè)全新的、干凈的構(gòu)建階段。這個(gè)基礎(chǔ)鏡像非常小,只包含運(yùn)行Java應(yīng)用所必需的 JRE。
COPY --from=builder ...: 核心步驟。它從之前命名為 builder 的構(gòu)建階段中,只把我們需要的構(gòu)建產(chǎn)物 (app.jar) 復(fù)制到當(dāng)前階段。所有構(gòu)建工具和中間文件都被丟棄了。

步驟二:構(gòu)建鏡像

在包含 Dockerfile 和項(xiàng)目代碼的目錄下,執(zhí)行:

docker build -t my-springboot-app:1.0 .

步驟三:運(yùn)行容器

docker run -d -p 8080:8080 --name spring-app my-springboot-app:1.0

步驟四:驗(yàn)證應(yīng)用

# 查看容器日志,確認(rèn) Spring Boot 啟動(dòng)成功
docker logs spring-app

# 使用 curl 測(cè)試應(yīng)用的某個(gè)端點(diǎn) (假設(shè)有一個(gè) /hello 端點(diǎn))
curl http://localhost:8080/hello

通過這個(gè)流程,我們成功地將一個(gè) Spring Boot 應(yīng)用打包成一個(gè)輕量級(jí)、可移植、自包含的Docker鏡像。

練習(xí)題

題目一:FROM 指令

一個(gè) Dockerfile 的第一條有效指令 (非注釋) 必須是什么?

題目二:COPY vs ADD

如果你只想簡(jiǎn)單地將本地的一個(gè) config.json 文件復(fù)制到鏡像中,應(yīng)該優(yōu)先選擇 COPY 還是 ADD?為什么?

題目三:RUN 指令優(yōu)化

以下 Dockerfile 寫法有什么潛在問題?應(yīng)該如何優(yōu)化以減小鏡像體積?

RUN apt-get update
RUN apt-get install -y curl

題目四:CMD 與 ENTRYPOINT

假設(shè) Dockerfile 中有 ENTRYPOINT ["/bin/echo", "Hello"]。執(zhí)行 docker run <image> World 命令后,最終會(huì)執(zhí)行什么命令?

題目五:EXPOSE 指令的作用

執(zhí)行 EXPOSE 3000 指令后,在不使用 -p 參數(shù)的情況下運(yùn)行容器,宿主機(jī)是否可以通過 localhost:3000 訪問到容器?

題目六:WORKDIR 指令

以下 Dockerfile 執(zhí)行后,pwd 命令的輸出是什么?

WORKDIR /app
WORKDIR client
RUN pwd

題目七:ENV vs ARG

哪個(gè)指令設(shè)置的變量在容器運(yùn)行后依然可以通過 env 命令查看到?

題目八:USER 指令

為了提高安全性,在 Dockerfile 中通常會(huì)在什么時(shí)間點(diǎn)之后使用 USER 指令切換到非root用戶?

題目九:多階段構(gòu)建

在多階段構(gòu)建中,使用 COPY --from=<stage_name> 的主要目的是什么?

題目十:構(gòu)建命令

如何構(gòu)建一個(gè)名為 my-web-app,標(biāo)簽為 v2 的鏡像,Dockerfile 位于當(dāng)前目錄?

題目十一:運(yùn)行命令

如何以后臺(tái)模式運(yùn)行一個(gè)名為 webapp-instance 的容器,基于 my-web-app:v2 鏡像,并將宿主機(jī)的 8888 端口映射到容器的 80 端口?

題目十二:Dockerfile 最佳實(shí)踐

為什么在 RUN 指令中安裝軟件包后,通常會(huì)緊接著清理包管理器的緩存 (如 rm -rf /var/lib/apt/lists/*)?

題目十三:編寫一個(gè)簡(jiǎn)單的 Dockerfile

編寫一個(gè) Dockerfile,基于 alpine 鏡像,安裝 curl 工具,并在容器啟動(dòng)時(shí)執(zhí)行 curl ifconfig.me 命令。

題目十四:CMD 的覆蓋

一個(gè) Dockerfile 的最后一條指令是 CMD ["echo", "Default"]。如何運(yùn)行這個(gè)鏡像的容器,使其輸出 “Hello Docker” 而不是 “Default”?

答案與解析

答案一:

FROM 指令。

答案二:

應(yīng)該優(yōu)先選擇 COPY。

解析: COPY 的功能更單一、透明,就是復(fù)制文件。而 ADD 可能會(huì)有意想不到的自動(dòng)解壓行為,不夠明確。遵循最小權(quán)限和最明確原則,選擇 COPY。

答案三:

這會(huì)創(chuàng)建兩個(gè)獨(dú)立的鏡像層。第一層緩存了 apt-get update 的結(jié)果,第二層安裝了 curl。將它們合并到一條 RUN 指令中,以減少鏡像層數(shù),從而減小最終鏡像的體積。

RUN apt-get update && apt-get install -y curl

答案四:

最終會(huì)執(zhí)行 /bin/echo Hello World。

解析: 當(dāng) ENTRYPOINT 存在時(shí),docker run 后面的所有內(nèi)容 (World) 都被作為參數(shù)追加到 ENTRYPOINT 命令的末尾。

答案五:

不可以。

解析: EXPOSE 只起到聲明和文檔的作用,并方便容器間互聯(lián)。要從宿主機(jī)訪問,必須在 docker run 時(shí)使用 -p 或 -P 顯式發(fā)布端口。

答案六:

輸出是 /app/client。

解析: WORKDIR 指令可以使用相對(duì)路徑。第二個(gè) WORKDIR client 是相對(duì)于第一個(gè) WORKDIR /app 的,所以最終工作目錄是 /app/client。

答案七:

ENV 指令。

解析: ARG 是構(gòu)建時(shí)變量,在鏡像構(gòu)建完成后就消失了。ENV 設(shè)置的環(huán)境變量會(huì)持久化在鏡像中,并在容器運(yùn)行時(shí)存在。

答案八:

通常在所有需要 root 權(quán)限的操作完成之后,例如安裝軟件包、創(chuàng)建目錄、修改文件權(quán)限等 RUN 指令之后,在設(shè)置 ENTRYPOINT 或 CMD 之前。

# ...
RUN chown -R myuser:mygroup /app
USER myuser
ENTRYPOINT ["./my-app"]

答案九:

主要目的是將前一個(gè)構(gòu)建階段的產(chǎn)物 (如編譯好的二進(jìn)制文件、打包好的JAR/WAR包) 復(fù)制到當(dāng)前新的、更精簡(jiǎn)的構(gòu)建階段中,從而實(shí)現(xiàn)最終鏡像的瘦身,去除所有不必要的構(gòu)建工具和中間文件。

答案十:

docker build -t my-web-app:v2 .

答案十一:

docker run -d -p 8888:80 --name webapp-instance my-web-app:v2

答案十二:

因?yàn)?Dockerfile 的每一條 RUN 指令都會(huì)創(chuàng)建一個(gè)新的鏡像層。如果在一條 RUN 指令中安裝了軟件包,然后在另一條 RUN 指令中清理緩存,那么包含緩存的那一層仍然存在于鏡像中,無法減小鏡像體積。將安裝和清理放在同一條 RUN 指令中,可以確保在該層提交之前,緩存就被清除了,不會(huì)占用最終鏡像的空間。

答案十三:

FROM alpine:latest
RUN apk add --no-cache curl
CMD ["curl", "ifconfig.me"]

解析: alpine 使用 apk 作為包管理器。--no-cache 選項(xiàng)可以在安裝時(shí)避免留下緩存,是減小鏡像體積的好習(xí)慣。CMD 使用 exec 格式定義啟動(dòng)命令。

答案十四:

docker run <image> echo "Hello Docker"

總結(jié)

到此這篇關(guān)于Docker核心技術(shù)之Dockerfile指令詳解及綜合案例的文章就介紹到這了,更多相關(guān)Docker Dockerfile指令詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Docker容器實(shí)現(xiàn)按順序啟動(dòng)的完整指南

    Docker容器實(shí)現(xiàn)按順序啟動(dòng)的完整指南

    在日常開發(fā)和運(yùn)維中,我們會(huì)遇到這樣的需求,即多個(gè) Docker 容器需要按特定順序啟動(dòng),下面小編就和大家詳細(xì)介紹一下具體的實(shí)現(xiàn)方法吧
    2025-12-12
  • Docker拉取鏡像部分成功部分失敗的解決方案

    Docker拉取鏡像部分成功部分失敗的解決方案

    最近在部署 Zitadel 身份認(rèn)證平臺(tái)的過程中,遇到一個(gè)看似“隨機(jī)”的問題:Docker 有些鏡像可以拉取,有些卻一直超時(shí)失敗,最終通過配置 Docker 守護(hù)進(jìn)程級(jí)別的代理 才解決,文章記錄整個(gè)問題分析和解決過程,便于自己和大家后期參考,需要的朋友可以參考下
    2025-05-05
  • 一些常見的精簡(jiǎn)Docker?file規(guī)則總結(jié)

    一些常見的精簡(jiǎn)Docker?file規(guī)則總結(jié)

    這篇文章主要介紹了一些常見的精簡(jiǎn)Docker?file規(guī)則的相關(guān)資料,這些精簡(jiǎn)規(guī)則有助于優(yōu)化Dockerfile,生成更高效、簡(jiǎn)潔的鏡像,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-11-11
  • Docker批量容器編排的實(shí)現(xiàn)

    Docker批量容器編排的實(shí)現(xiàn)

    這篇文章主要介紹了Docker批量容器編排的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 詳解基于docker 如何部署surging分布式微服務(wù)引擎

    詳解基于docker 如何部署surging分布式微服務(wù)引擎

    這篇文章主要介紹了詳解基于docker 如何部署surging分布式微服務(wù)引擎,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-06-06
  • Docker數(shù)據(jù)管理之Volume與Bind?Mount的核心技術(shù)詳解

    Docker數(shù)據(jù)管理之Volume與Bind?Mount的核心技術(shù)詳解

    這篇文章主要為大家詳細(xì)介紹了Docker數(shù)據(jù)持久化的兩種核心技術(shù),主要是Volume(數(shù)據(jù)卷)和Bind?Mount(綁定掛載),有需要的小伙伴可以了解下
    2026-05-05
  • 詳解Docker容器跨主機(jī)通信的方法

    詳解Docker容器跨主機(jī)通信的方法

    本篇文章主要介紹了詳解Docker容器跨主機(jī)通信的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-11-11
  • docker如何部署tomcat應(yīng)用

    docker如何部署tomcat應(yīng)用

    這篇文章主要介紹了docker如何部署tomcat應(yīng)用問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • docker安裝zookeeper全過程

    docker安裝zookeeper全過程

    這篇文章介紹了在CentOS上使用Docker安裝Zookeeper的步驟,包括拉取鏡像、查看鏡像、啟動(dòng)容器、檢查容器狀態(tài)以及運(yùn)行客戶端
    2025-11-11
  • 教你一分鐘搞定docker+redis哨兵模式

    教你一分鐘搞定docker+redis哨兵模式

    這篇文章主要介紹了教你一分鐘搞定docker+redis哨兵模式,本文主要講解一主二從三哨兵,特將其部署到一臺(tái)機(jī)器上,并通過端口區(qū)分,需要的朋友可以參考下
    2023-03-03

最新評(píng)論

东宁县| 苗栗市| 特克斯县| 沙田区| 柳林县| 万盛区| 平陆县| 岑溪市| 紫云| 怀仁县| 涞源县| 双鸭山市| 梁河县| 固原市| 云安县| 三穗县| 囊谦县| 阿克苏市| 葵青区| 方城县| 汕尾市| 来凤县| 瓦房店市| 奎屯市| 马鞍山市| 金乡县| 上蔡县| 拜城县| 班戈县| 梧州市| 安国市| 芦溪县| 张家港市| 敖汉旗| 卫辉市| 海阳市| 龙里县| 延庆县| 儋州市| 武夷山市| 鄂尔多斯市|