使用dockerfile定制鏡像及dockerfile指令解析


查看使用 Dockerfile 定制鏡像

1.從零開始來創建一個新的鏡像、

什么是 Dockerfile 文件?

Dockerfile是用來構建Docker鏡像的構建文件,是由一系列命令和參數構成的腳本

主要作用:

1、找一個鏡像:   centos

2、創建一個容器: docker run  centos

3、進入容器:     docker exec -it 容器 命令

4、操作:         各種應用配置

                ....

5、構造新鏡像:    docker commit

Dockerfile 使用准則

1、大: 首字母必須大寫D

   2、空: 盡量將Dockerfile放在空目錄中。

   3、單: 每個容器盡量只有一個功能。

   4、少: 執行的命令越少越好。

Dockerfile 基礎四指令:

   基礎鏡像信息          從哪來?

   維護者信息           我是誰?

   鏡像操作指令          怎么干?

   容器啟動時執行指令     嗨!!!

Dockerfile使用命令:

構建鏡像命令格式:

  docker build -t [鏡像名]:[版本號] [Dockerfile所在目錄]

構建樣例:

  docker build -t nginx:v0.2 /opt/dockerfile/nginx/

參數詳解:

  -t     指定構建后的鏡像信息,

  /opt/dockerfile/nginx/     則代表Dockerfile存放位置,如果是當前目錄,則用 .(點)表示

1.1編寫Dockerfile文件、

$ mkdir mynginx
$ cd mynginx
$ touch Dockerfile
$ cat Dockerfile
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

說明:

每一個指令都會在鏡像上創建一個新的層,每一個指令的前綴都必須是大寫的

第一條FROM,指定使用哪個鏡像源,基礎鏡像

FROM scratch (表示空白的鏡像,是一個虛擬的概念,實際不存在)

RUN 指令是用來執行命令行命令的(兩種格式)

shell 格式:RUN <命令>
exec 格式:RUN ["可執行文件", "參數1", "參數2"]
如:# RUN ["./test.php", "dev", "offline"] 等價於 RUN ./test.php dev offline

最好不要寫多個指令,每一個指令代表一層,則會創建了很多層鏡像,如果需要寫多個指令可以用連接符 && 連接起來,在同一層上面創建即可。

1.2 構建鏡像

Dockerfile 文件所在目錄執行:

$ docker build -t nginx:2.0 .
發現其執行了兩步,查看鏡像列表已經存在創建的鏡像了
-t:指定要創建的鏡像名
.:Dockerfile 文件所在目錄,可以指定Dockerfile 的絕對路徑

運行鏡像:

[root@rbtnode1 mynginx]# docker run -d -p 82:80 nginx:2.0

 

 

查看 nginx,運行的頁面如構建的shell腳本更改一致

 

 

 

1.3上下文路徑

最后一個 . 是上下文路徑,怎么理解呢?

是docker在構建鏡像,不一定使用RUN指令完成的,有時候想要使用本機的文件(如復制COPY),docker build命令得知這個路徑后,會將路徑下的所有東西打包。docker是C/S模式,我們使用C,引擎是S。而build是是引擎完成的,則docker不能使用我們本機C的文件,所以需要制定目錄下的文件打包給S使用。如果不說嗎,則為Dockerfile所在的位置。

如果在Dockerfile中寫:

COPY ./package.json /app/
這並不表示要復制docker build命令所在的目錄下的package.json,也不是復制Dockerfile所在目錄下的package.json,而是復制上下文目錄下的package.json。

**COPY 這類指令中的源文件的路徑都是相對路徑。**

docker build -t nginx:2.0 . 中的這個 .,實際上是在指定上下文的目錄,docker build 命令會將該目錄下的內容打包交給 Docker 引擎以幫助構建鏡像。(輸出的第一行就是其過程)

 

 

為了避免犯錯:

  1. 應該會將 Dockerfile 置於一個空目錄下,或者項目根目錄下。

  1. 如果該目錄下沒有所需文件,那么應該把所需文件復制一份過來,去copy正常的Linux的路徑如 ../../等是不會工作的。

  1. 不希望傳有些東西給docker引擎,用.dockerignore文件(似.gitignore)剔除

為什么會誤認為是指定Dockerfile路徑呢?

  1. 因默認情況且不指定Dockerfile的話,會將上下文目錄下的名為Dockerfile的文件名為Dockerfile

  2. 不必須命名為Dockerfile,可以用 -f ../Dockerfile.php 參數指定某個文件作為 Dockerfile

  3. 當然,一般大家習慣性的會使用默認的文件名 Dockerfile,以及會將其置於鏡像構建上下文目錄中

2.其它 docker build 的用法

2.1 直接用 Git repo 進行構建

  1. docker build支持url構建

    $ docker build https://github.com/twang2218/gitlab-ce-zh.git#:11.1
    指定默認的 master 分支,構建目錄為 /11.1/,然后 Docker 就會自己去 git clone 這個項目、切換到指定分支、並進入到指定目錄后開始構建。

     

2.2用給定的 tar 壓縮包構建

$ docker build http://server/context.tar.gz
Docker 引擎會下載這個包,並自動解壓縮,以其作為上下文,開始構建。

2.3從標准輸入中讀取 Dockerfile 進行構建

docker build - < Dockerfile
cat Dockerfile | docker build -

如果標准輸入傳入的是文本文件,則將其視為 Dockerfile,並開始構建。直接讀取Dockerfile中的內容,沒有上下文

2.4從標准輸入中讀取上下文壓縮包進行構建

$ docker build - < context.tar.gz

直接將其展開,將里面視為上下文,並開始構建

 

3.Dockerfile 指令詳解

3.1 COPY和ADD

COPY復制指令,將從構建上下文目錄中 <源路徑> 的文件/目錄復制到新的一層的鏡像內的 <目標路徑> 位置。ADD是更高級的復制文件,兩種格式兩種(命令行,函數調動型):

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

如:COPY package.json /usr/src/app/

加入組的方式:COPY --chown=1 files* /mydir/

[--chown=<user>:<group>]**:可選參數,用戶改變復制到容器內文件的擁有者和屬組。

<源路徑>:源文件或者源目錄,這里可以是通配符表達式,其通配符規則要滿足 Go 的 filepath.Match 規則

COPY hom* /mydir/
COPY hom?.txt /mydir/

<目標路徑>:容器內的指定路徑,該路徑不用事先建好,路徑不存在的話,會自動創建。 可以是容器內的絕對路徑,也可以是相對於工作目錄的相對路徑(工作目錄可以用 WORKDIR 指令來指定。

使用COPY指令,各類元數據都會保留,git時很方便。

ADD源路徑:

  1. 是一個url,docker引擎會去下載這個路徑,自動設置權限為600,也可以加RUN調整權限。下載到的若是個壓縮包,若解壓則加一層RUN指令,也可以wget或curl下載,處理。

  2. <源路徑> 為一個 tar 壓縮文件的話,壓縮格式為 gzip, bzip2 以及 xz 的情況下,ADD 指令將會自動解壓縮這個壓縮文件到 <目標路徑>

    1. 使用注意:

      1. 盡量多用COPY,只是復制沒必要那么復雜,需要自動解壓再用ADD

      2. ADD會讓鏡像構建失效,從而鏡像緩慢。

      3. --chown=<user>:<group>
        ADD --chown=55:mygroup files* /mydir/  
        修改用戶及所屬組

3.2 CMD和ENTRYPOINT

  1. 概念

    CMD:指定默認的容器主進程的啟動命令,程序運行結束,容器也就結束。CMD 指令指定的程序可被 docker run 命令行參數中指定要運行的程序所覆蓋。多個CMD時僅最后一個生效。

    ENTRYPOINT:類似於 CMD 指令,但其不會被 docker run 的命令行參數指定的指令所覆蓋,而且這些命令行參數會被當作參數送給 ENTRYPOINT 指令指定的程序,存在多個 ENTRYPOINT 指令,僅最后一個生效。需要通過 docker run 的參數 --entrypoint 來指定。

  2. 格式

CMD 指令的格式和 RUN 相似,CMD與ENTRYPOINT類似。也是兩種格式(推薦exec):

  • shell 格式:CMD <命令>

  • exec 格式:CMD ["可執行文件", "參數1", "參數2"...]

  • 參數列表格式:CMD ["參數1", "參數2"...]。在指定了 ENTRYPOINT 指令后,用 CMD 指定具體的參數。

  1. 使用規則

    1. CMD
      1. 使用exec格式,其會被解析成接送數組,一定需要“”雙引號。

      2. 使用shell格式,實際命令會被包裝是 sh -c 執行。這樣就需要環境變量,環境變量會被shell進行解析。容器中執行的命令需要在前台執行,類似於systemd后台命令無法執行,被迫容器退出,因為容器執行會解讀為sh執行,這樣sh就是這個命令的主進程。那么后台的命令結束則sh結束了就退出了,啟動程序就是容器應用進程,容器就是為了主進程而存在的,主進程結自然容器也退出了。除非CMD要求前台執行。

    2. ENTRYPOINT
      1. 指定了 ENTRYPOINT 后,CMD 的含義就發生了改變,不再是直接的運行其命令,而是將 CMD 的內容作為參數傳給 ENTRYPOINT 指令。<ENTRYPOINT> "<CMD>"

      2. 可以讓鏡像變成像命令一樣使用

      3. 啟動容器就是啟動主進程,但有些時候,啟動主進程前,需要一些准備工作。

         

3.3環境指令詳情

1. 環境設置指令

  ENV

  格式:

      ENV <key> <value>

      ENV <key>=<value> ...

  解釋:

      設置環境變量,可以在RUN之前使用,然后RUN命令時調用,容器啟動時這些環境變量都會被指定

 

  WORKDIR

   格式:

    WORKDIR /path/to/workdir                 (shell 模式)

  解釋:

      切換目錄,為后續的RUN、CMD、ENTRYPOINT 指令配置工作目錄。 相當於cd

    可以多次切換(相當於cd命令),

       也可以使用多個WORKDIR 指令,后續命令如果參數是相對路徑,則會基於之前命令指定的路徑。例如

   舉例:

    WORKDIR /a

    WORKDIR b

    WORKDIR c

    RUN pwd

    則最終路徑為 /a/b/c。

 

ENV實踐

修改Dockerfile文件內容:

  # 在上一個Dockerfile文件內容基礎上,在RUN下面增加一個ENV

ENV NIHAO=helloworld

 

WORKDIR實踐

  修改Dockerfile文件內容:

    # 在上一個Dockerfile文件內容基礎上,在RUN下面增加一個WORKDIR

WORKDIR /nihao/itcast/

RUN ["touch","itcast.txt"]

 

Dockerfile構建過程

Dockerfile**構建過程:**

  1. 從基礎鏡像1運行一個容器A

    遇到一條Dockerfile指令,都對容器A做一次修改操作

    執行完畢一條命令,提交生成一個新鏡像2

    再基於新的鏡像2運行一個容器B

    遇到一條Dockerfile指令,都對容器B做一次修改操作

    執行完畢一條命令,提交生成一個新鏡像3

    ...

  1. 構建過程鏡像介紹**

    構建過程中,創建了很多鏡像,這些中間鏡像,我們可以直接使用來啟動容器,通過查看容器效果,從側面能看到我們每次構建的效果。

    提供了鏡像調試的能力

    我們可以通過docker history <鏡像名> 來查看整個構建過程所產生的鏡像

    執行的步驟越多越好呢?還是越少越好?

  1. 構建緩存**

    我們第一次構建很慢,之后的構建都會很快,因為他們用到了構建的緩存。

不適用構建緩存方法常見兩種:

全部不同緩存:

docker build --no-cache -t [鏡像名]:鏡像版本

只要構建的緩存時間不變,那么就用緩存,如果時間一旦改變,就不用緩存了

樣例:

# 構建一個基於ubuntu-base的docker定制鏡像

# 基礎鏡像

FROM ubuntu-base

\ # 鏡像作者

MAINTAINER 郵箱

\ # 創建構建刷新時間

ENV REFRESH_DATE 2019-12-06

# 執行命令

...

 

構建歷史:

1. 查看構建過程查看

docker history

清理構建緩存:

docker system prune

docker system prune --volumes


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM