Docker鏡像構建的兩種方式(六)


鏡像構建介紹

 

在什么情況下我們需要自己構建鏡像那?

(1)當我們找不到現有的鏡像,比如自己開發的應用程序

(2)需要在鏡像中加入特定的功能

 

docker構建鏡像有兩種方式:docker commit命令與Dockerfile構建文件

 

docker commit構建鏡像

 

dockercommit構建進行主要有三步:

  • 運行容器
  • 修改容器
  • 將容器保存為新的鏡像

比如在centos鏡像中安裝vim編輯器並存為新的鏡像

(1)運行容器

[root@ken1 docker]# docker run -it centos
Unable to find image 'centos:latest' locally
latest: Pulling from library/centos
a02a4930cb5d: Pull complete 
Digest: sha256:184e5f35598e333bfa7de10d8fb1cebb5ee4df5bc0f970bf2b1e7c7345136426
Status: Downloaded newer image for centos:latest

 

(2)安裝vim編輯器

vim編輯器確認沒有安裝

[root@69f501e858a6 /]# vim
bash: vim: command not found

進行安裝

[root@69f501e858a6 /]# yum install vim -y

 

(3)保存為新得鏡像

首先查看當前運行的鏡像

[root@ken1 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
69f501e858a6        centos              "/bin/bash"         2 minutes ago       Up 2 minutes                            quizzical_torvalds

使用commit存為新的鏡像

[root@ken1 ~]# docker commit 69f501e858a6 centos-vim
sha256:42083b89a179368bc29a8f40d14f8824990183c8e4b28fd84411d440c26342e5

69f501e858a6是運行容器的ID使用name下面的名稱也行
centos-vim是新鏡像的名字

查看一下是否有了centos-vim鏡像

重新啟動新的鏡像,驗證是否可以使用vim編輯器

可以發現新的鏡像可以使用vim編輯器了

[root@ken1 ~]# docker run -it centos-vim 
[root@61d090898bad /]# vim
[root@61d090898bad /]# vim test

 

上面演示了如何使用commit創建新的鏡像,但是docker並不建議使用這種方式創建鏡像,原因如下:

  • 這是一種手工創建鏡像的方式,容器出錯,而且效率低且可重復性弱
  • 更重要的是。使用者並不知道鏡像是如何創建出來的。里面是否有惡意程序

 

Dockerfile構建鏡像

 

第一個Dockerfike

 

第一步:創建一個新的目錄

[root@ken1 ~]# mkdir /test

 

第二步:編寫Dockerfile

名稱就叫Dockerfile,且第一個D需要大寫

[root@ken1 ~]# cat Dockerfile
FROM centos
RUN yum install vim -y

FROMcentos表示使用centos這個基礎鏡像

RUN表示在centos上安裝vim編輯器

 

第三步:構建鏡像

[root@ken1 ~]# docker build -t centos-vim2 .

-t后面指定新的鏡像的標簽名(tag)

. 最后的一個點指明docker context為當前目錄。docker默認會從build context中查找 Dockerfile文件,我們也可以通過-f參數指定Dockerfile的位置

 

第四步:查看鏡像

 

 查看鏡像分層結構

 

docker history會顯示鏡像的構建歷史,也就是Dockerfile的執行過程。

 

Dcokerfile常用指令

 

  1.FROM

指定base鏡像

  2. MAINTAINER

設置鏡像的作者。可以是任意的字符

  3.COPY

將文件從build context復制到鏡像

COPY支持兩種格式:COPY src dest 和 COPY [“src”,”dest”]

注意:src只能制動build context中的文件或目錄即在和Dockerfile同目錄下才可以

  4.ADD

與COPY類似,從build context復制文件到鏡像。

不同的是,如果src是歸檔文件(tar,zip,tgz,xz),文件會被自動接要到dest

  5.ENV

設置環境變量,環境變量可被后面的指令使用,例如:

ENV name ken RUN echo $name

  6.EXPOSE

指定容器中的進程會監聽某個端口,Docker可以將該端口暴露出來

  7.VOLUME

將文件或目錄聲明為volume

  8.WORKDIR

為后面的RUN,ENTRYPINT,ADD,COPY指令設置鏡像中的當前工作目錄

  9.RUN

在容器中運行指定的命令

  10.CMD

容器啟動時運行指定的命令

dockerfile中可以多個CMD指令,但是只要最后一個生效。CMD可以被docker run之后的參數替換

  11.ENTRYPOINT

設置容器啟東市的命令

dockerfile中可以有多個ENTRYPOINT,但是只有最后一個生效。

CMD或者docker run之后的參數會被當做參數傳遞給ENTERYPOINT.

 

Dockerfile演示

 

下面演示一個比較全面的dockerfile

 
[root@ken1 test]# cat Dockerfile 
#my Dockerfile
FROM busybox
MAINTAINER ken
WORKDIR /ken
RUN touch test
COPY ["ken1","."]
ADD ["wordpress.tar.gz","."]
ENV name "ken"
 

注意:Dockerfile支持以#開頭的注釋

構建鏡像

 
[root@ken1 test]# docker build -t myimage .
Sending build context to Docker daemon  4.281MB
Step 1/7 : FROM busybox
 ---> 3a093384ac30
Step 2/7 : MAINTAINER ken
 ---> Running in 2a73a83507ce
Removing intermediate container 2a73a83507ce
 ---> 8c3df9b3d823
Step 3/7 : WORKDIR /ken
 ---> Running in 31c6f9fe2195
Removing intermediate container 31c6f9fe2195
 ---> a458cf986072
Step 4/7 : RUN touch test
 ---> Running in e1b08ebd363c
Removing intermediate container e1b08ebd363c
 ---> 41601920009a
Step 5/7 : COPY ["ken1","."]
 ---> 2ebfa0933fca
Step 6/7 : ADD ["wordpress.tar.gz","."]
 ---> d0ad29d3aa34
Step 7/7 : ENV name "ken"
 ---> Running in fceae6e20e63
Removing intermediate container fceae6e20e63
 ---> 7efe0600e48f
Successfully built 7efe0600e48f
Successfully tagged myimage:latest
 

查看鏡像

運行該鏡像

[root@ken1 test]# docker run -it myimage
/ken # ls
ken1       test       wordpress
/ken # echo $name
ken

 

  •  可以發現當前工作目錄為/ken,且自動創建
  • ken1是我們從docker context目錄中復制過去的
  • test是使用touch創建的
  • wordpres壓縮包已經被自動解壓
  • $name為變量值為ken

 

 RUN,CMD,ENTRYPOINT

 

這三個指令看上去很類似,很容易混淆,簡單來說:

  • RUN:執行命令創建新的鏡像層,RUN經常用於安裝軟件包
  • CMD:設置容器啟動后默認執行的命令及參數,但CMD能夠被docker run后面跟的命令行參數替換
  • ENTRYPOINT:配置容器啟動時運行的命令
  1. 使用 RUN 指令安裝應用和軟件包,構建鏡像。
  2. 如果 Docker 鏡像的用途是運行應用程序或服務,比如運行一個 MySQL,應該優先使用 Exec 格式的 ENTRYPOINT 指令。CMD 可為 ENTRYPOINT 提供額外的默認參數,同時可利用 docker run 命令行替換默認參數。
  3. 如果想為容器設置默認的啟動命令,可使用 CMD 指令。用戶可在 docker run 命令行中替換此默認命令。

 

Shell和Exec格式

 

可以用兩種方式制定RUN,CMD,ENTRYPOINT要運行的命令:shell格式以及exec格式

 

shell舉例:

RUN echo "hello world"
CMD echo "hello world"
ENTRYPOINT echo "hello world"

當指令執行時,shell格式底層會調用/bin/sh -c [command].例如下面的dockerfile片段:

ENV name ken  

ENTRYPOINT echo "Hello, $name"

執行 docker run <image> 將輸出:

Hello, ken

 

注意環境變量 name 已經被值 ken替換。

下面來看 Exec 格式。

 

Exec 格式

<instruction> [“executable”, “param1”, “param2”, …]

 

例如:

RUN ["yum", "install", "python3"]  

CMD ["/bin/echo", "Hello world"]  

ENTRYPOINT ["/bin/echo", "Hello world"]

 

當指令執行時,會直接調用 <command>,不會被 shell 解析。
例如下面的 Dockerfile 片段:

ENV name ken

ENTRYPOINT ["/bin/echo", "Hello, $name"]

 

運行容器將輸出:

Hello, $name

 

注意環境變量“name”沒有被替換。
如果希望使用環境變量,照如下修改

ENV name ken  

ENTRYPOINT ["/bin/sh", "-c", "echo Hello, $name"]

 

運行容器將輸出:

Hello, ken

 

CMD 和 ENTRYPOINT 推薦使用 Exec 格式,因為指令可讀性更強,更容易理解。RUN 則兩種格式都可以。


免責聲明!

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



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