Docker系列(七):Dockerfile構建鏡像

dockerfile指令:


  • FROM:構建的新鏡像是基於哪個鏡像,例如:FROM centos:6

            語法:

            FROM <image>
            FROM <image>:<tag>

            FROM <image>:<digest> 

            三種寫法,其中<tag>和<digest> 是可選項,如果沒有選擇,那麼默認值爲latest

  • MAINTAINER:鏡像維護者姓名或郵箱地址,例如:MAINTAINER [email protected]

            語法:

            MAINTAINER <name>
  • RUN:構建鏡像時運行的Shell命令,例如:RUN ["yum", "install", "httpd"] 或 RUN yum install httpd

            RUN命令有兩種格式

                    1. RUN <command>
                    2. RUN ["executable", "param1", "param2"]

            第一種後邊直接跟shell命令,在linux操作系統上默認 /bin/sh -c,在windows操作系統上默認 cmd /S /C

            第二種是類似於函數調用。可將executable理解成爲可執行文件,後面就是兩個參數。

            兩種寫法比對:

                    RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME
                    RUN ["/bin/bash", "-c", "echo hello"]

            注意:多行命令不要寫多個RUN,原因是Dockerfile中每一個指令都會建立一層。多少個RUN就構建了多少層鏡像,會造成鏡像的臃腫、多層,不僅僅增加了構件部署的時間,還容易出錯。RUN書寫時的換行符是\。

  • CMD:運行容器時執行的Shell命令,

            語法有三種寫法

  1.             CMD ["executable","param1","param2"]
                CMD ["param1","param2"]
                CMD command param1 param2

            第三種比較好理解了,就時shell這種執行方式和寫法。第一種和第二種其實都是可執行文件加上參數的形式。

            例如:

         CMD ["-c", "/start.sh"]

         CMD ["/usr/sbin/sshd", "-D"]

         CMD /usr/sbin/sshd -D

  • EXPOSE:聲明容器運行的服務端口,例如:EXPOSE 80 443


            功能爲暴漏容器運行時的監聽端口給外部,但是EXPOSE並不會使容器訪問主機的端口。如果想使得容器與主機的端口有映射關係,必須在容器啓動的時候加上-P參數。

  • ENV:設置容器內環境變量,例如:ENV MYSQL_ROOT_PASSWORD 123456

            功能爲設置環境變量,語法有兩種:

                 ENV <key> <value>
                 ENV <key>=<value> ...

            兩者的區別就是第一種是一次設置一個,第二種是一次設置多個。

  • ADD:拷貝文件或目錄到鏡像,如果是URL或者壓縮包會自動下載或自動解壓

    用法:ADD <src>...<dest>

      ADD ["<src>",..."<dest>"]

            說明:<dest>路徑的填寫可以是容器內的絕對路徑,也可以是相對於工作目錄的相對路徑

                      <src>可以是一個本地文件或者是一個本地壓縮文件,還可以是一個url

                       如果把<src>寫成一個url,那麼ADD就類似於wget命令

                       注意:儘量不要把<scr>寫成一個文件夾,如果<src>是一個文件夾了,複製整個目錄的內容,包括文件系統元數據

    例如:

           ADD https://xxx.com/html.tar.gz /var/www/html

           ADD html.tar.gz /var/www/html

  • COPY:拷貝文件或目錄到鏡像,例如:COPY ./start.sh /start.sh

            語法如下:

                    COPY <src>... <dest>
                    COPY ["<src>",... "<dest>"]

            與ADD的區別:

                    COPY的<src>只能是本地文件,其他用法一致

  • ENTRYPOINT:運行容器時執行的Shell命令

            語法如下:

                    ENTRYPOINT ["executable", "param1", "param2"]

                    ENTRYPOINT command param1 param2

                    差別:第一種就是可執行文件加參數,第二種就是寫shell

            例如:ENTRYPOINT ["/bin/bash", "-c", "/start.sh"]

      ENTRYPOINT /bin/bash -c '/start.sh'

            與CMD比較說明(這倆命令太像了,而且還可以配合使用):

                    1. 相同點:

                            只能寫一條,如果寫了多條,那麼只有最後一條生效

                            容器啓動時才運行,運行時機相同

                    2. 不同點:

                            ENTRYPOINT不會被運行的command覆蓋,而CMD則會被覆蓋

                            如果我們在Dockerfile種同時寫了ENTRYPOINT和CMD,並且CMD指令不是一個完整的可執行命令,那麼CMD指定的內容將會作爲ENTRYPOINT的參數

  • VOLUME:指定容器掛載點到宿主機自動生成的目錄或其他容器,例如:VOLUME ["/var/lib/mysql"]

            語法爲:

                    VOLUME ["/data"]

            說明:

                    ["/data"]可以是一個JsonArray ,也可以是多個值。

                    所以如下幾種寫法都是正確的:

                            VOLUME ["/var/log/"]

                            VOLUME /var/log
                            VOLUME /var/log /var/db

            使用場景:一般的使用場景爲需要持久化存儲數據時,容器使用的是AUFS,這種文件系統不能持久化數據,當容器關閉後,所有的更改都會丟失,所以當數據需要持久化時用這個命令。

  • USER:爲RUN、CMD和ENTRYPOINT執行命令指定運行用戶USER <user>[:<group>]或USER <UID>[:<GID>],例如:USER zhangsan

          注意:如果設置了容器以daemon用戶去運行,那麼RUN, CMD 和 ENTRYPOINT 都會以這個用戶去運行
  • WORKDIR:爲RUN、CMD、ENTRYPOINT、COPY和ADD設置工作目錄,例如:WORKDIR /data

            語法:

                    WORKDIR /path/to/workdir

            設置工作目錄,對RUN,CMD,ENTRYPOINT,COPY,ADD生效。如果不存在則會創建,也可以設置多次。

            例如:

                    WORKDIR /a
                    WORKDIR b
                    WORKDIR c
                    RUN pwd

                    pwd執行的結果是/a/b/c

  • HEALTHCHECK:健康檢查

            語法有兩種:

                1. HEALTHCHECK [OPTIONS] CMD command
                2. HEALTHCHECK NONE

            說明:第一個的功能是在容器內部運行一個命令來檢查容器的健康狀況

                      第二個的功能是在基礎鏡像中取消健康檢查命令

             [OPTIONS]的選項支持以下三中選項:

                    --interval=DURATION 兩次檢查默認的時間間隔爲30秒

                    --timeout=DURATION 健康檢查命令運行超時時長,默認30秒

                    --retries=N 當連續失敗指定次數後,則容器被認爲是不健康的,狀態爲unhealthy,默認次數是3

             注意:HEALTHCHECK命令只能出現一次,如果出現了多次,只有最後一個生效。

            CMD後邊的命令的返回值決定了本次健康檢查是否成功,具體的返回值如下:

                    0: success - 表示容器是健康的

                    1: unhealthy - 表示容器已經不能工作了

                    2: reserved - 保留值

            例如:

                    HEALTHCHECK --interval=5m --timeout=3s --retries=3 CMD curl -f http://localhost/ || exit 1

                    健康檢查的命令是curl -f http://localhost/ ,兩次健康檢查的間隔時間是5m,命令超時時間爲3s。

  • ARG:在構建鏡像時指定一些參數

            語法:

                    ARG <name>[=<default value>]

            設置變量命令,ARG命令定義了一個變量,在docker build創建鏡像的時候,使用 --build-arg <varname>=<value>來指定參數

            如果用戶在build鏡像時指定了一個參數沒有定義在Dockerfile種,那麼將有一個Warning,提示如下:

                    [Warning] One or more build-args [foo] were not consumed.

    例如:

    FROM centos:6

    ARG user   # 定義一個參數,不在dockerfile中賦值

    USER $user

    # docker build --build-arg user=root Dockerfile .

  • LABEL:爲鏡像指定標籤

             語法:

                    LABEL <key>=<value> <key>=<value> <key>=<value> ...

             一個Dockerfile種可以有多個LABEL,如下:

                    LABEL "com.example.vendor"="ACME Incorporated"
                    LABEL com.example.label-with-value="foo"
                    LABEL version="1.0"
                    LABEL description="This text illustrates \
                    that label-values can span multiple lines."

            但是並不建議這樣寫,最好就寫成一行,如太長需要換行的話則使用\符號

            如下:

                    LABEL multi.label1="value1" \
                    multi.label2="value2" \
                    other="value3"

            說明:LABEL會繼承基礎鏡像種的LABEL,如遇到key相同,則值覆蓋

  • STOPSIGNAL:當容器推出時給系統發送什麼樣的指令

            語法:

                    STOPSIGNAL signal


使用dockerfile構建帶ssh服務的centos容器:

# 創建dockerfile

[root@centos7 ~]# mkdir dockerfile/centos_ssh -p 
[root@centos7 ~]# cd dockerfile/centos_ssh/
[root@centos7 centos_ssh]# vi dockerfile 
[root@centos7 centos_ssh]# cat dockerfile 
FROM centos
MAINTAINER "[email protected]"
ENV ROOT_PASSWORD 123456
RUN yum -y install openssh-server && yum clean all && \
  ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key && \
  ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key && \
  /bin/echo $ROOT_PASSWORD |passwd --stdin root
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

# 使用dockerfile創建鏡像

[root@centos7 centos_ssh]# docker build -t centos_ssh:v1 .
Sending build context to Docker daemon 2.048 kB
Step 1/6 : FROM centos
 ---> 1e1148e4cc2c
Step 2/6 : MAINTAINER "[email protected]"
 ---> Running in 8cad47a9e80a
 ---> ace0609297a5
Removing intermediate container 8cad47a9e80a
Step 3/6 : ENV ROOT_PASSWORD 123456
 ---> Running in a7ec1235fddb
 ---> 49d86fd09a96
Removing intermediate container a7ec1235fddb
Step 4/6 : RUN yum -y install openssh-server && yum clean all &&     ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key &&     ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key &&     /bin/echo $ROOT_PASSWORD |passwd --stdin root
 ---> Running in e9eb19cd496f
......
 ---> c366592c89f8
Removing intermediate container e9eb19cd496f
Step 5/6 : EXPOSE 22
 ---> Running in 5c0e295c1ed7
 ---> 7717f93524ae
Removing intermediate container 5c0e295c1ed7
Step 6/6 : CMD /usr/sbin/sshd -D
 ---> Running in f8b4fe42d264
 ---> e63f4d45cd57
Removing intermediate container f8b4fe42d264
Successfully built e63f4d45cd57

# 查看構建好的鏡像

[root@centos7 centos_ssh]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos_ssh          v1                  e63f4d45cd57        2 hours ago         228 MB
docker.io/nginx     latest              f09fe80eb0e7        3 weeks ago         109 MB
docker.io/busybox   latest              3a093384ac30        2 months ago        1.2 MB
docker.io/centos    latest              1e1148e4cc2c        2 months ago        202 MB

# 使用構建完畢的鏡像創建容器

[root@centos7 centos_ssh]# docker run -itd --name centos_ssh_01 -p 2222:22 centos_ssh:v1
ac59ac35955142095a1b59520f134a3de71a9a3f0d0305350d64adc91f886637
[root@centos7 centos_ssh]# docker ps -a 
CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS              PORTS                  NAMES
ac59ac359551        centos_ssh:v1       "/usr/sbin/sshd -D"   2 hours ago         Up 2 hours          0.0.0.0:2222->22/tcp   centos_ssh_01

# 嘗試使用ssh直接連接docker容器

003.png


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章