【Docker 系列】docker 學習七,DockerFile 編寫和實戰

小魔童哪吒發表於2021-11-28

我們開始來一起學習 DockerFile 的知識點

DcokerFile 是用來構建 docker 映象的檔案,是一個命令引數指令碼

一般 docker 映象的構建步驟:

1、編寫一個 dockerfile 檔案

2、docker build 構建成為一個映象

3、docker run 執行映象

4、docker push 釋出映象(我們們可以釋出到 DockerHub,也可以釋出到阿里雲上面)

我們來看看官方的映象是咋玩的

例如我們在 DockerHub 上搜尋 ubuntu ,看看官網的 DockerFile 是啥樣子的

https://hub.docker.com/_/ubuntu

點選連結我們會進入到 git 倉庫上,也是 DockerFile

我們們看到就 3 行 Docker 命令,是官方做成映象的 DockerFile,所以這個官方的 ubuntu 映象是非常簡單的,閹割版本的,甚至連 clear 命令都沒有,ll命令也沒有

很多的官方映象包都是非常簡單的,很多功能都是沒有的,我們通常會自己搭建自己的映象來滿足我們的各種需求

DockerFile 的構建過程

官方能構建映象,我們也可以自己的映象

DockerFile 的基礎知識:

  • 每個 DockerFile 的保留字(指令),都必須是大寫的
  • DockerFile 指令碼執行是按照順序執行的
  • # 表示註釋
  • 每一個指令都會建立提交一個新的映象層,並提交

可以在網路上找到這樣的圖片,可以看到映象是一層一層的,可以在瀏覽器上搜尋到 DockerFile 裡面的指令解釋

dockerfile 是面向開發的,我們以後在做專案的時候,是直接釋出一個映象,交付的是一個映象,就需要編寫 DockerFile 檔案,這個檔案非常的簡單!

我們們必須要掌握 Docker 映象,逐漸成為企業交付的標準了。

我們們學習的過程是先會使用別人的東西,再去研究別人是怎麼寫的,進而我們也學會如何去寫,去開發

例如:

我們先學習使用了,

DockerImages:通過 DockerFile 構建生產的映象,最終釋出和執行的產品

Docker 容器:容器服務就是映象執行起來的伺服器

現在我們開始詳細學習 DockerFIle : 構建檔案,定義了一切的步驟,這是原始碼

DockerFile 的指令

圖片來源於網路,我們一一解釋一波

  • FROM

基礎的映象,一切都是從這裡開始的

  • MAINTAINER

指明映象是誰寫的,寫下自己的姓名和郵箱

  • RUN

映象構建的時候需要執行的命令

  • ADD

加入某些配置,例如加入 mysql 的壓縮包,新增內容

  • WORKDIR

映象的工作目錄

  • VOLUME

掛載目錄

  • EXPOSE

暴露埠 和 -p 是一個效果

  • CMD

指定這個容器啟動的時候執行的命令,只會是最優一個指令進行生效,會被替代

  • ENTRYPOINT

指定這個容器啟動的時候執行的命令,可以追加

  • ONBUILD

當構建一個被繼承的 DockerFIle ,這個時候就會執行 ONBUILD 的指令,觸發相應的動作

  • COPY

與 ADD 類似,此命令是將檔案拷貝到映象中

  • ENV

構建的時候設定環境變數

乍一看感覺 CMDENTRYPOINT功能好像差不多,但是還是不太清楚具體區別在哪裡,文章末尾會有詳細說明

實戰

我們自己來做一個自定一個 ubuntu 映象

官方的ubuntu是閹割版本的,很多工具和命令都是不支援的,那麼我們就自己加進去,自給自足

自己寫一個 DockerFile

這裡需要注意的是,基本上 99%的映象,都是基於這個基礎映象 scratch,我們可以看到官方的 DockerFIle 也是基於這個映象來玩的

ubuntu git url

那麼我們可以基於這個 ubuntu 來進行自定義,加入一些我們需要的工具,如vimifconfig

FROM ubuntu

RUN apt-get update                    # 更新源

RUN  apt-get install -y vim            # 安裝 vim

RUN  apt-get install -y net-tools    # 安裝 net-tools

ENV MYPATH /usr/local                # 設定環境變數
WORKDIR $MYPATH                        # 設定映象工作目錄

EXPOSE 8888                            # 暴露埠

CMD echo "----- end -----"            # 執行 echo 命令

CMD /bin/bash

開始構建

docker build -f dockerfile2 -t xmtubuntu .

如果不在 DockerFile 中寫入 apt-get update 更新源,會出現下面這個問題,這個要注意

執行上述命令,會看到如下列印資訊,最終會看到Successfully,即為構建成功

通過上圖我們可以看出, DokerFile 中寫了 9 個步驟,執行的時候也是分了 9 步,知道全部成功才算成功

最終構建成功後我們可以看到

Successfully built a6f88c9f245b
Successfully tagged xmtubuntu:latest

驗證結果

docker images 檢視我們的映象

# docker images
REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
xmtubuntu             latest    a6f88c9f245b   13 minutes ago   172MB

docker inspect a6f88c9f245b 檢視我們映象的構建過程

# docker history a6f88c9f245b
IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT
a6f88c9f245b   14 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/bin…   0B
3c0d23b8188f   14 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B
ffb019142fc7   14 minutes ago   /bin/sh -c #(nop)  EXPOSE 8888                  0B
8867e6d97670   14 minutes ago   /bin/sh -c #(nop) WORKDIR /usr/local            0B
c9d0141ec3b0   14 minutes ago   /bin/sh -c #(nop)  ENV MYPATH=/usr/local        0B
41e73f7e314d   14 minutes ago   /bin/sh -c apt-get install -y net-tools         1.52MB
52013ca51f1d   14 minutes ago   /bin/sh -c apt-get install -y vim               68.2MB
5ea7d553d403   14 minutes ago   /bin/sh -c apt-get update                       29.7MB
1318b700e415   11 days ago      /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>      11 days ago      /bin/sh -c #(nop) ADD file:524e8d93ad65f08a0…   72.8MB

xmtubuntu 這個映象的構建過程我們可以清晰的看出都執行了哪些步驟,當然,同樣的方式,我們也可以看看官方的映象是如何構建的,我們來看看官方 ubuntu 的

# docker history ubuntu
IMAGE          CREATED       CREATED BY                                      SIZE      COMMENT
1318b700e415   11 days ago   /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>      11 days ago   /bin/sh -c #(nop) ADD file:524e8d93ad65f08a0…   72.8MB

官方的就很簡單,閹割了很多東西,我們可以看出官方的 ubuntu 就 2 個步驟,第一個是加入ubuntu 壓縮包,第二個就是 /bin/bash

我們檢視我們的自定義映象 xmtubuntu

果然,我們的自定義ubuntu映象,有了vimifconfig工具,實戰成功

CMD 和 ENTRYPOINT 的區別

  • CMD

指定這個容器啟動的時候執行的命令,只會是最優一個指令進行生效,會被替代

  • ENTRYPOINT

指定這個容器啟動的時候執行的命令,可以追加

如何理解呢?我們來做一個對比試驗就可以很好的理解上述的解釋說明,docker 裡面有很多命令會有這樣的微小區別,我們可以舉一反三,慢慢深入學習

CMD 的例子

寫一個簡單的 DockerFile 檔名為 dockerfile-cmd

FROM xmtubuntu
CMD ["ls","-a"]

構建映象

e# docker build -f dockerfile-cmd -t dockerfile-cmd .
Sending build context to Docker daemon  1.346GB
Step 1/2 : FROM xmtubuntu
 ---> a6f88c9f245b
Step 2/2 : CMD ["ls","-a"]
 ---> Running in 101670af4290
Removing intermediate container 101670af4290
 ---> 1697fc03b8ce
Successfully built 1697fc03b8ce
Successfully tagged dockerfile-cmd:latest

建立並啟動容器

docker run 101670af4290,可以看到如下效果

image-20210807121235380

我們嘗試在啟動容器時候追加命令

docker run 101670af4290 -l,就會有如下報錯

# docker run 1697fc03b8ce -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.

原因如下:

使用 CMD指令是(例如我們的例子是 ls -a),我們在啟動容器的時候,後面追加的命令(-l)會把 ls -a替換掉,由於-l不是一個命令,因此報錯

ENTRYPOINT 的例子

寫一個簡單的 DockerFile 檔名為 dockerfile-entrypoint

FROM xmtubuntu
ENTRYPOINT ["ls","-a"]

構建映象,建立並啟動容器和 CMD 的例子一模一樣,我們們直接啟動容器的效果和 CMD的例子也是一模一樣,我們直接來看啟動容器並追加引數的例子

可以看出使用 ENTRYPOINT是可以在後面追加引數的,使用CMD若指令後面追加引數,那麼會覆蓋CMD指定的指令

那麼,對於以後遇到相關的指令,我們也可以舉一反三,做對比試驗,這樣我們就會理解的更加清楚

如何釋出我們的映象

1、登入 dockerhub

沒有註冊的 xdm 可以註冊一個,https://hub.docker.com/

# docker login -u xxxx使用者名稱
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

2、修改我們的映象 tag

docker tag 我們的映象id 我們的docker使用者名稱/映象名字:版本

3、將映象推到我們自己的倉庫中

釋出映象的時候,也是按照一層一層的提交的

最後補充一個網路上找到的圖片,現在看這張圖就能更清晰的明白其中的原理了

參考資料:

docker docs

歡迎點贊,關注,收藏

朋友們,你的支援和鼓勵,是我堅持分享,提高質量的動力

好了,本次就到這裡

技術是開放的,我們的心態,更應是開放的。擁抱變化,向陽而生,努力向前行。

我是小魔童哪吒,歡迎點贊關注收藏,下次見~

相關文章