kubernetes(五)之Dockerfile

Dockerfile

鏡像相關的操做

  • 鏡像生成的途徑
    • Dockerfile
    • 基於容器製做docker commit
      kubernetes(五)之Dockerfile

定義

  • 構建docker鏡像的源碼
    • docker能夠根據Dockerfile中的指令進行鏡像的自動構建
    • Dockerfile是一個包含了一個用戶能夠調用的命令行去組織一個鏡像
    • 經過docker build命令能夠將一些用戶可調用的命令行指令去構建對應的鏡像
      kubernetes(五)之Dockerfile

構建Dockerfile的注意事項

  • 必須有一個工做目錄放Dockerfile文件與附文件
  • Dockerfile文件名必須是Dockerfile

Dockerfile的格式

  • 包含的信息:
    • 註釋
    • 指令: 全部指令通常都是大寫;是一個資源清單;沒有複雜的判斷語法等

指令

  • FROMphp

    • 是Dockerfile最重要的一個且必須爲文件開篇第一個非註釋行,用於爲鏡像文件構建過程當中指定基礎鏡像,後續的指令運行於此基準鏡像所提供的運行環境
    • 實踐中,基準竟想能夠是任何可用鏡像文件,默認狀況下,docker build會在docker主機上查找指定的鏡像文件,若本機不存在則去dockerHub拉取
    • 語法:
      • FROM <repository>[:tag]: repostory是鏡像倉庫名稱,tag是鏡像的標籤,如不指定,默認是latest
      • FROM <repository>@<digist>:digest是鏡像的ID(校驗碼)
  • MAINTAINERhtml

    • 用於指定Dockerfile的維護者信息,目前已經被廢棄
    • 出現的位置推薦在FROM的下一行
    • 語法:
      • MAINTAINER "wanghui <wanghui@tencent.com>"
  • LABELnode

    • 代替MAINTAINER指令,能夠定義鏡像的額外信息,能夠定義多個信息
    • 鏡像的元信息(metadata)
    • 語法:
      • LABEL <key>=<value> <key1>=<value1>
  • COPY
    • 用於從docker宿主機拷貝文件到鏡像的可寫層
    • 拷貝的原路徑必須是咱們的工做目錄
    • 語法:支持多個源地址
      • COPY <src>... <dest>
      • COPY ["<src>",...,"<dest>"]:路徑中由空白字符時,使用此格式
    • 注意事項
      • src必須是build上下文中的路徑,不能是父路徑中的文件
      • 若是src是目錄,則其內部的子文件或者子目錄會被遞歸複製,可是src目錄自身不會被複制
      • 若是指定了多個src,或者在src後面使用了通配符,則dest必須是一個目錄且必須以/結尾
      • 若是dest事先不存在,其將會被自動建立
[root@centos7-node1 ~]# mkdir /data/build_workshop -p
[root@centos7-node1 ~]# cd /data/build_workshop/
[root@centos7-node1 build_workshop]# echo "<h1>this is a test page</h1>" > index.html
[root@centos7-node1 ~]# cd /data/build_workshop/
[root@centos7-node1 build_workshop]# vim Dockerfile         
FROM busybox:latest
LABEL maintainer="wanghui<wanghui@yeecall.com>"
COPY index.html /data/web/html/
[root@centos7-node1 build_workshop]# docker build . -t myimg:v0.1
[root@centos7-node1 build_workshop]# docker run --name t1 --rm -it myimg:v0.1 /bin/sh
/ # ls /data/web/html/
index.html
[root@centos7-node1 build_workshop]# mkdir /data/build_workshop/pages/
[root@centos7-node1 build_workshop]# mv /data/build_workshop/index.html /data/build_workshop/pages/
[root@centos7-node1 build_workshop]# echo "<h1>test1 page</h1>" >  /data/build_workshop/pages/test1.html
[root@centos7-node1 build_workshop]# echo "<h1>test2 page</h1>" >  /data/build_workshop/pages/test2.html 
[root@centos7-node1 build_workshop]# vim /data/build_workshop/.dockerignore    #忽略拷貝文件
pages/test2.html
[root@centos7-node1 build_workshop]# vim /data/build_workshop/Dockerfile 
FROM busybox:latest
LABEL maintainer="wanghui<wanghui@yeecall.com>"
COPY pages/*.html /data/web/html/
[root@centos7-node1 build_workshop]# docker build . -t myimg:v0.2
[root@centos7-node1 build_workshop]# docker run --name t1 --rm -it myimg:v0.2 /bin/sh   #驗證
/ # ls /data/web/html/
index.html  test1.html
  • ADD
    • ADD相似於COPY指令,ADD支持tar文件和url路徑
    • 語法:
      • ADD &lt;src&gt;... &lt;dest&gt;
      • ADD ["&lt;src&gt;","...","&lt;dest&gt;"]
    • 操做準則
      • 同COPY指令
      • 若是src爲URL地址且dest不以/結尾,則src指定的文件警備下載並直接建立爲dest
      • 若是dest以/結尾,則文件名URL指定的文件會被下載保存爲dest/filename
      • 若是src是本地上傳的一個壓縮格式的tar文件,它將被展開爲一個目錄,其行爲相似與tar -x命令,然而URL獲取的他人文件不會被自動展開
      • 若是src有多個,或期間使用了通配符,則dest必須是一個以/結尾的目錄路徑
      • 若是dest不以/結尾,則被視爲一個普通文件,src的內容將被寫入到dest
[root@centos7-node1 ~]# mkdir /data/build_workshop/add_example
[root@centos7-node1 ~]# cd /data/build_workshop/add_example
[root@centos7-node1 add_example]# wget http://nginx.org/download/nginx-1.16.1.tar.gz
[root@centos7-node1 add_example]# vim Dockerfile
FROM  busybox:latest
LABEL maintainer="wanghui <wanghui@yeecall.com>"
ADD http://nginx.org/download/nginx-1.18.0.tar.gz /data/
ADD nginx-1.16.1.tar.gz /data/
[root@centos7-node1 add_example]# docker run --name t1 --rm -it myimg:v0.3 /bin/sh
/ # ls /data/
nginx-1.16.1         nginx-1.18.0.tar.gz
  • WORKDIRmysql

    • 用於指定Dockerfile中全部的RUN,CMD,ENTRYPOINT,COPY,ADD指定設定工做目錄
    • 語法:nginx

      • WORKDIR /var/log
      • WORKDIR $STATEPATH: 能夠引用環境變量,結合ENV使用
    • 注意事項: 能夠使用多個WORKDIR,最終用最新的WORKDIR
[root@centos7-node1 ~]# cd /data/build_workshop/
[root@centos7-node1 build_workshop]# cp add_example/ worksdir_example -r  && cd  worksdir_example
[root@centos7-node1 worksdir_example]# vim Dockerfile 
ADD http://nginx.org/download/nginx-1.18.0.tar.gz /data/
FROM  busybox:latest
LABEL maintainer="wanghui <wanghui@yeecall.com>"
WORKDIR  /usr/
ADD nginx-1.16.1.tar.gz src/
[root@centos7-node1 worksdir_example]# docker build . -t myimg:v0.4
[root@centos7-node1 worksdir_example]# docker run --name t1 --rm -it  myimg:v0.4 /bin/sh
/usr # ls src/nginx-1.16.1/
  • VOLUME
    • 用於在image中建立一個掛載點目錄,以掛載上docker host上的卷或者其餘容器上的卷
    • 語法:
      • VOLUME &lt;mountpoint&gt;
      • VOLUME ["&lt;mountpoint&gt;"]
    • 注意:
      • 若是掛載點目錄路徑下此前文件存在,docker run命令會在卷掛載完成後將此前的全部文件複製到新的掛載卷中
[root@centos7-node1 build_workshop]# mkdir /data/build_workshop/volumes_example/pages/
[root@centos7-node1 build_workshop]# cd /data/build_workshop/volumes_example
[root@centos7-node1 volumes_example]# echo "<h1>test1 page</h1>" >  /data/build_workshop/volumes_example/pages/test1.html
[root@centos7-node1 volumes_example]# echo "<h1>test2 page</h1>" > /data/build_workshop/volumes_example/pages/test2.html 
[root@centos7-node1 volumes_example]# vim Dockerfile 
FROM busybox:latest
LABEL maintainer="wanghui<wanghui@yeecall.com>"
COPY pages/*.html /data/web/html/
ADD   http://nginx.org/download/nginx-1.15.8.tar.gz /tmp/
WORKDIR /usr/
VOLUME /data/web/html/
[root@centos7-node1 volumes_example]# docker build . -t myimg:v0.5
[root@centos7-node1 volumes_example]# docker run --name t1 -it --rm myimg:v0.5 /bin/sh
/usr # cd /data/web/html/
/data/web/html # ls
index.html  test1.html  test2.html
[root@centos7-node1 ~]# docker inspect -f {{.Mounts}} t1     #另起窗口,找到Source,發現Source映射目錄的內容與容器中的同樣[隨機存儲卷]
  • EXPOSE
    • 用於爲容器打開制定監聽的端口,以實現與外部通訊
    • 語法:
      • EXPOSE &lt;port&gt;[/&lt;protocol&gt;] ...: 指定端口和協議
    • 注意事項:
      • EXPOSE 11211/udp 11211/tcp:一次指定多個端口
FROM busybox:latest
LABEL maintainer="wanghui<wanghui@yeecall.com>"
COPY pages/*.html /data/web/html/
ADD   http://nginx.org/download/nginx-1.15.8.tar.gz /tmp/
WORKDIR /usr/
VOLUME /data/web/html/
EXPOSE 80/tcp
[root@centos7-node1 expose_example]# docker build . -t myimg:v0.6
[root@centos7-node1 volumes_example]# docker run --name t1 -it -P --rm myimg:v0.6 /bin/sh
/usr # httpd -f -h /data/web/html/    #啓動httpd服務
[root@centos7-node1 expose_example]# docker port t1   #查看映射,而後訪問便可
  • ENV
    • 用與定義所須要的環境變量,並能夠被Dockerfile文件中位於其後的其餘指令(如ENV,ADD,COPY等)所調用
    • 調用格式爲 $variable_name${variable_name}
    • 在build階段使用的
    • 語法:
      • ENV &lt;key&gt; &lt;value&gt;: 一次只能設置一個變量
      • ENV &lt;key&gt;=&lt;value&gt;: 一次能夠設置多個變量,特數字答覆須要使用\轉義[推薦使用]
FROM busybox:latest
ENV webhome="/data/web/html/"
LABEL maintainer="wanghui<wanghui@yeecall.com>"
COPY pages/*.html ${webhome}
ADD http://nginx.org/download/nginx-1.15.8.tar.gz ${webhome}
WORKDIR ${webhome}
ADD nginx-1.16.1.tar.gz ./
VOLUME  ${webhome}
EXPOSE 80/tcp
[root@centos7-node1 env_example]# docker build . -t myimg:v0.7
  • ARG
    • 定義變量,能夠在build階段傳值,替換dockerfile中的值
    • 語法:
      • ARG &lt;name&gt;=[default]
    • 注意:
      • 支持docker1.14及其以上的版本
      • 推薦使用ARG
FROM busybox:latest
ARG webhome="/data/web/html/"
LABEL maintainer="wanghui<wanghui@yeecall.com>"
COPY pages/*.html ${webhome}
ADD http://nginx.org/download/nginx-1.15.8.tar.gz ${webhome}
WORKDIR ${webhome}
ADD nginx-1.16.1.tar.gz ./
VOLUME  ${webhome}
EXPOSE 80/tcp
[root@centos7-node1 arg_example]# docker build . -t myimg:v0.8     #正常不加參數的編譯,使用的是默認的參數
[root@centos7-node1 arg_example]# docker build --build-arg webhome="/webdata/htdocs/" . -t myimg:v0.8   #加入參數的編譯
[root@centos7-node1 arg_example]# docker run --name t1 -it --rm myimg:v0.8 /bin/sh   #結果測試
  • RUN
    • 用於指定docker build過程當中運行程序,其能夠是任何命令
    • 語法:
      • RUN &lt;command&gt;:command一般是一個shell命令,且以/bin/sh -c來運行它, 這意味着此進程在容器中的PID不爲1,不能接受Unix信號,所以,當使用docker stop &lt;container&gt;中止容器時,此進程接收不到SIGTERM信號
      • RUN ["&lt;executable&gt;","param1","param2"]:參數是一個json格式的數組,其中excutable是要運行的命令,後面的param是要傳遞給命令的選項或者參數,然而此種格式的參數不會以/bin/sh -c來發起,所以常見的shell操做,如變量替換以及通配符操做將不會進行,不過,若是要運行依賴此shell特性的話,能夠將其替換成以下的格式: RUN ["bin/sh","-c","&lt;executable&gt;","&lt;param1&gt;"]
    • 注意: 執行的命令必須是FROM拉取鏡像中能夠執行的;
    • 實例1
FROM busybox:latest
ARG webhome="/data/web/html/"
LABEL maintainer="wanghui<wanghui@yeecall.com>"
COPY pages/*.html ${webhome}
ADD http://nginx.org/download/nginx-1.15.8.tar.gz ${webhome}
WORKDIR ${webhome}
ADD nginx-1.16.1.tar.gz ./
VOLUME  ${webhome}
EXPOSE 80/tcp
RUN  mkdir -p /web/bbs && \
     ["/bin/sh","-c","echo helle >> /web/bbs/index.html"]
[root@centos7-node1 run_example]# docker build . -t myimg:v0.9
  • 實例2
FROM centos:7
LABEL maintainer="wanghui <122725501@qq.com>"
ARG  docroot=/var/www/html/
RUN yum makecache && \
    yum -y install httpd php php-mysql && \
    yum clean all && \
    rm -fr /var/cache/yum/*
[root@centos7-node1 ap]# docker run --name web1 --rm -it php-httpd:v0.1 bash
  • CMD
    • 運行在docker run階段,用於容器中運行命令或者應用程序
      • RUN指令運行於鏡像的構建過程當中,而CMD的運行是基於Dockerfile構建出的新鏡像文件啓動一個容器時
      • CMD指令首要目的在於爲溶洞的容器指定默認要運行的程序,且其運行結束後容器也將終止,不過,CMD指令的命令能夠被docker run的命令行所覆蓋
      • 在Dockerfile中能夠存在多個CMD命令,但僅最後一個生效
    • 語法:
      • CMD &lt;command&gt;
      • CMD ["&lt;executable&gt;","param1","param2"]
      • CMD ["param1","param2"]: 用於爲ENTRYPOINT提供默認參數
FROM centos:7
LABEL maintainer="wanghui <122725501@qq.com>"
ARG  docroot=/var/www/html/
RUN yum makecache && \
    yum -y install httpd php php-mysql && \
    yum clean all && \
    rm -fr /var/cache/yum/*
CMD ["/usr/sbin/httpd","-DFOREGROUND"]
[root@centos7-node1 ap]# docker build . -t php-httpd:v0.2
[root@centos7-node1 ap]# docker run --name web1 --rm  php-httpd:v0.2 
[root@centos7-node1 ap]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@centos7-node1 ap]# docker run --name web1 -it php-httpd:v0.2 /bin/bash
[root@47818a3ba906 /]# ps -ef    #httpd被覆蓋了
UID         PID   PPID  C STIME TTY          TIME CMD
root          1      0  1 09:41 pts/0    00:00:00 /bin/bash
  • ENTRYPOINT
    • 相似CMD指令的功能,用於爲容器指定默認的運行程序,從而使容器像是一個獨立的可執行程序
      • 與CMD不一樣的是,由ENTRYPOINT啓動的程序不會被docker run命令指定的參數所覆蓋,並且這些命令行參數被當作傳遞給ENTRYPOINT指定的程序
      • 不過,docker run命令的--entrypoint選項參數能夠覆蓋ENTRYPOINT指定的程序
    • 語法:
      • ENTRYPOINT &lt;command&gt;
      • ENTRYPOINT ["&lt;executable&gt;","param1","param2"]
    • 注意事項
      • docker run 命令傳入的參數會覆蓋CMD指令的內容而且附加到ENTRYPOINT命令的最後做爲其參數使用
      • Dockerfile存在多個ENTRYPOINT指令,但僅有最後一個會生效
[root@centos7-node1 ap]# tree ./
./
├── Dockerfile
├── entrypoint.sh
├── ok.html
└── phpinfo.php
[root@centos7-node1 ap]# cat Dockerfile 
FROM centos:7
LABEL maintainer="wanghui <122725501@qq.com>"
ARG  docroot=/var/www/html/
RUN yum makecache && \
    yum -y install curl httpd php php-mysql && \
    yum clean all && \
    rm -fr /var/cache/yum/*
ADD ok.html phpinfo.php ${docroot}
ADD entrypoint.sh /bin/
EXPOSE 80/tcp
VOLUME ${docroot}
HEALTHCHECK --interval=3s --timeout=3s --start-period=2s CMD curl -f http://localhost/ok.html || exit 1
CMD ["/usr/sbin/httpd","-DFOREGROUND"]
ENTRYPOINT ["/bin/entrypoint.sh"]
[root@centos7-node1 ap]# cat entrypoint.sh 
#!/bin/bash
listen_port=${LISTEN_PORT:-80}
server_name=${SERVER_NAME:-localhost}
doc_root=${DOC_ROOT:-/var/www/html/}
cat > /etc/httpd/conf.d/myweb.conf <<EOF
#LISTEN $listen_port
<VirtualHost *:${listen_port}>
    ServerName  "$server_name"
    DocumentRoot  "$doc_root"
    <Directory "$doc_root">
       Options  none
       AllowOverride none
       Require all granted
    </Directory>
</VirtualHost>
EOF
exec "$@"
Dockerfile  entrypoint.sh  ok.html  phpinfo.php
[root@centos7-node1 ap]# cat ok.html 
OK
[root@centos7-node1 ap]# cat phpinfo.php 
<?php
  phpinfo();
?>
  • USERweb

    • 用於指定image運行時任何RUN,CMD,ENTRYPOINT指令指定程序運行的用戶名或者UID
    • 默認狀況下USER是root
    • 語法:
      USAER &lt;uid&gt;|username
      • 注意:
      • 用戶必須是存在與/etc/passwd中的有效用戶,不然容器會運行失敗
  • HEALTHCHECKsql

    • 檢測容器是否正常運行
    • 語法:
      • HEALTHCHECK CMD command:檢查容器內的服務是否運行正常
      • HEALTHCHECK none:不須要健康檢查
    • 注意事項:
      --interval : 檢查週期,默認30s
      --timeout:等待超時,默認30s
      --start-period: 開始檢測的時間,默認是0s
      --retries:重試次數
  • ONBUILD
    • 用於在Dockerfile中定義觸發器,延遲運行
      • Dockerfile用於build鏡像文件,此鏡像文件也也能夠做爲base image被另外的一個Dockerfile用做FROM指令參數,並以次構建新的鏡像
        • 在後面的Dockerfile中的FROM指令在build過程當中被執行時,會觸發建立其base image的Dockerfile文件中的ONBUILD指令定義的觸發器
    • 語法:
      • ONBUILD &lt;INSTRUCTION&gt;
    • 注意事項
      • 儘管任何指令均可以註冊成爲觸發器指令,可是ONBUILD不能自我嵌套,且不會出發FROM和MAINTAINER指令
      • 在ONBUILD指令中使用ADD和COPY要格外當心,由於新構建過程當中的上下文在缺乏指定的原文件時會失敗
[root@centos7-node1 ~]# cd /data/build_workshop/
[root@centos7-node1 build_workshop]# mkdir testimg/ myicme/ -p
[root@centos7-node1 build_workshop]# vim testimg/Dockerfile 
FROM busybox:latest
LABEL maintainer="wanghui <122725501@qq.com>"
RUN mkdir -p /data/web/html
ONBUILD ADD http://nginx.org/download/nginx-1.18.0.tar.gz /usr/src
[root@centos7-node1 build_workshop]# docker build ./testimg/  -t testimg:v0.1   # 構建testing:v0.1
[root@centos7-node1 build_workshop]# vim myicme/Dockerfile
FROM  testimg:v0.1
LABEL from="testimg:v0.1
[root@centos7-node1 build_workshop]# docker build ./myicme/ -t myicme:v0.1   #此時構建纔會執行下載testing:v0.1
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM  testimg:v0.1
# Executing 1 build trigger
Downloading [==>                                                ]  47.73kB/1.04MB
  • 鏡像臨時導入導出
[root@centos7-node1 ~]# docker image save php-httpd:v0.6 -o php-httpd.tar   #導出鏡像
[root@centos7-node1 ~]# docker image load -i php-httpd.tar     # 導入鏡像
[root@centos7-node1 ~]# docker history php-httpd:v0.6   #構建歷史查看
相關文章
相關標籤/搜索