Docker系列10:docker file指令詳解(2)

十、指令10:RUN指令html

  • RUM命令是基於Dockerfile構建鏡像的時候要運行的命令mysql

  • 好比基於url的方式獲取nginx安裝包:獲取到gz包之後須要使用RUN指令來運行tar來解壓展開這個nginx的包了。nginx

案例:編寫docker file,並製做鏡像
web

#my first docker file
FROM busybox:latest
MAINTAINER "zxhk <237745635@qq.com>"

ENV DOC_ROOT=/data/ \
    WORK_DIR=/var/usr/src/ \
    REPO_DIR=/etc/yum.repos.d/ \
    MYSQL_DIR=/data/mysql/
    
COPY index.html ${DOC_ROOT:-/var/www/html/}
COPY yum.repos.d $REPO_DIR

WORKDIR $WORK_DIR
ADD http://nginx.org/download/nginx-1.17.6.tar.gz ./

RUN cd ${WORK_DIR} && tar -xf nginx-1.17.6.tar.gz && mv nginx-1.17.6 nginx

VOLUME $MYSQL_DIR
EXPOSE 80/tcp 53/udp
[root@host1 img1]# docker build -t miniser:v1-8 ./

基於鏡像啓動一個容器,檢測是否已經解壓sql

[root@host1 img1]# docker run --rm --name t1 miniser:v1-8 ls /var/usr/src/
nginx
nginx-1.17.6.tar.gz

十一、指令11:CMD指令docker

  • CMD是定義一個鏡像文件啓動爲容器的時候,默認要運行的程序,也就是那個pid爲1的程序shell

  • CMD能夠有多個,可是隻有最後一個纔是生效的。apache

CMD指令有三種格式vim

格式1:CMD <命令>bash

  • 這種格式的話,會自動的將這個命令運行爲shell的子進程,這樣的好處就是在這個命令中能夠有各類的特殊的符號,可是缺點就得是這個命令的進程號不是 1

  • 也能夠藉助於exec,讓這個進程的ID成爲1

格式2:CMD ["<命令>", "<參數1>","<參數2>"]

  • 這種格式的話是直接將這個進程啓動爲ID爲1的進程

格式3:CMD ["<參數1>","<參數2>"]

  • 這種格式須要藉助於ENTRYPOINT才能運行

案例1:使用格式1讓容器運行的時候,自動運行apache

第一步:建立dockerfile

FROM busybox
LABEL maintainer="zxhk<237745635@qq.com>"

ENV DOC_ROOT="/var/www/html/"

RUN mkdir -p ${DOC_ROOT} && \
    echo "<h1>test</h1>">${DOC_ROOT}index.html

CMD /bin/httpd -f -h ${DOC_ROOT}

第二步:製做鏡像

[root@host1 img2]# docker build -t miniser:v2-1 ./

第三步:查看鏡像的詳細信息

[root@host1 img2]# docker inspect miniser:v2-1 -f '{{.ContainerConfig.Cmd}}'
[/bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/bin/httpd -f -h ${DOC_ROOT}"]]

第四步:建立容器

[root@host1 img2]# docker run --name t1 --rm -d miniser:v2-1

第五步:登陸容器,查看容器信息

[root@host1 img2]# docker exec -it t1 /bin/sh
/ # 
/ # netstat -an
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 :::80                   :::*                    LISTEN      
/ # 
/ # ps
PID   USER     TIME  COMMAND
    1 root      0:00 /bin/httpd -f -h /var/www/html/
   10 root      0:00 /bin/sh
   15 root      0:00 ps
/ #

案例2:使用格式2讓容器運行的時候,自動運行apache

FROM busybox
LABEL maintainer="zxhk<237745635@qq.com>"

ENV DOC_ROOT="/var/www/html/"

RUN mkdir -p ${DOC_ROOT} && \
    echo "<h1>test</h1>">${DOC_ROOT}index.html
CMD ["/bin/sh", "-c", "/bin/httpd", "-f", "-h", "${DOC_ROOT}"]

十一、指令11:ENTRYPOINT指令

  • ENTRYPOINT的功能就是和CMD相似的,用於指定容器啓動後要默認運行的程序

  • 在啓動容器的時候,run後面指定的命令,能夠覆蓋鏡像中的CMD命令

  • ENTRYPOINT所運行的命令不會不被docker run所指定的命令覆蓋

案例:用ENTRYPOINT製做鏡像實現啓動容器自動運行apache

FROM busybox
LABEL maintainer="zxhk<237745635@qq.com>"

ENV DOC_ROOT="/var/www/html/"

RUN mkdir -p ${DOC_ROOT} && \
    echo "<h1>test</h1>">${DOC_ROOT}index.html

ENTRYPOINT /bin/httpd -f -h ${DOC_ROOT}

製做鏡像並啓動容器測試

[root@host1 img2]# docker build -t miniser:v2-2 ./
[root@host1 img2]# docker run --name t2 --rm -it miniser:v2-2 ls /data
  • 此時命令會卡住

  • ls /data會做爲參數傳遞給httpd -f -h  /data,由於httpd沒法識別這個參數,所以會卡住

ENTRYPOINT和CMD組合使用的狀況

  • 此時CMD後的內容就會做爲默認參數傳遞給ENTRYPOINT

FROM busybox
LABEL maintainer="zxhk<237745635@qq.com>"

ENV DOC_ROOT="/var/www/html/"

RUN mkdir -p ${DOC_ROOT} && \
    echo "<h1>test</h1>">${DOC_ROOT}index.html

CMD ["/bin/httpd", "-f", "-h", "${DOC_ROOT}"]
ENTRYPOINT ["/bin/sh","-c"]
  • 使用ENTRYPOINT的好處是,他比CMD更方便,由於他能夠在啓動容器的時候,直接向容器傳遞命令

案例:在啓動容器的時候,動態生成配置文件

一、建立工做目錄

[root@host1 img3]# mkdir /img3
[root@host1 img3]# cd /img3

二、準備一個shell腳本,用於生成配置文件

[root@host1 img3]# vim entrypoint.sh
#!/bin/sh
cat>/etc/nginx/conf.d/www.conf<<EOF
server {
    server_name $HOSTNAME;
    listen ${IP:-0.0.0.0}:${PORT:-80};
    root ${NGX_DOC_ROOT:-/usr/share/nginx/html};
}
EOF
exec "$@"

三、建立測試頁面

[root@host1 img3]# echo "test page">index.html

四、編寫Dockerfile文件

[root@host1 img3]# vim Dockerfile

FROM nginx:1.14-alpine

LABEL author="zxhk<237745635@qq.com>"
ENV NGX_DOC_ROOT='/data/web/html/'

ADD index.html ${NGX_DOC_ROOT}
ADD entrypoint.sh /bin/

#nginx的配置文件必須以;爲結尾
CMD ["/usr/sbin/nginx","-g","daemon off;"]
ENTRYPOINT ["/bin/entrypoint.sh"]

  • 在執行dockerfile的時候,CMD的內容會傳遞到ENTRYPOINT中

  • ENTRYPOIN會啓動運行這個shell腳本,shell腳本就是pid爲1的進程,shell腳本就會生成配置文件

  • 在腳本的最後會經過exec 來執行nginx,讓nginx工做在前臺,同時nginx進程頂替shell成爲pid爲1的進程

五、構建鏡像

[root@host1 img3]# docker build -t miniser:v2-4 ./

六、啓動容器

[root@host1 img3]# docker run --name nginx1 --rm miniser:v2-4

登陸容器看看

[root@host1 ~]# docker exec -it nginx1 /bin/sh
/ # 
/ # cat /etc/nginx/conf.d/www.conf 
server {
    server_name c1d255997da4;
    listen 0.0.0.0:80;
    root /data/web/html/;
}
/ #

七、再從新啓動一個容器,讓nginx監聽127.0.0.1的8080端口

[root@host1 img3]# docker run --name nginx1 --rm \
> -e "PORT=8080" -e "IP=1.2.3.4" miniser:v2-4

再登陸容器看看

[root@host1 ~]# docker exec -it nginx1 /bin/sh
/ # 
/ # 
/ # cat /etc/nginx/conf.d/www.conf 
server {
    server_name 92c978c97b3c;
    listen 127.0.0.1:8080;
    root /data/web/html/;
}
/ #
  • 經過這種方式能夠快速的爲不一樣的環境準備特定的配置文件

十二、指令12:USER指令

  • 用於指定容器中的主進程是以哪一個用戶的身份來運行

  • 也能夠用來指定在執行dockerfile的CMD  RUN  ENTRYPOIND的時候,以那個用戶的身份來運行

  • 須要確保容器的/etc/passwd中有這個用戶,不然會報錯

語法格式:

  • USER <UID> | <USERNAME>

1三、指令13:HEALTHCHECK指令

  • 檢查容器和容器中的服務是否正常工做

HEALTHCHECK的功能選項

  • --interval=xx  指定每隔多久檢查一次(默認每隔30s檢查一次)

  • --timeout=xx  指定等待超時時間(默認也是30s)

  • --start-period=xx 啓動容器後,等待多久開始作健康檢查(默認是0秒,也就是不等)

  • --retries=xx  指定請求幾回數據都沒得到返回的狀況下才認爲是出現了異常(默認是3次)

HEALTHCHECK的返回值

  • 0:success成功

  • 1:unhealth不健康

  • 2:預留,沒有意義

案例:每隔5分鐘檢查一次,超時時間是3秒

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

  • 若是健康檢查失敗,就返回1

1四、指令14:SHELL指令

  • 這個是用來指定運行程序的時候默認要用的程序

舉例:

SHELL ["/bin/sh","-c"]

1五、指令15:STOPSIGNAL指令

  • 這個指令能夠指定在執行docker stop的時候,本質上是向容器發送什麼什麼指令,默認是發送15,若是想執行stop的時候發送9的指令

格式

STOPSIGNAL 9

1六、指令16:ARG指令

  • ARG也是定義一個變量,只是這個變量是用在執行build dockerfile的過程當中

  • 能夠將nginx的版本定義成變量,而後在構建鏡像的時候能夠經過變量來動態指定做者

編寫鏡像文件

FROM nginx:1.14-alpine

ARG info="zxhk<237745635@qq.com>"
LABEL author="${info}"

ENV NGX_DOC_ROOT='/data/web/html/'

ADD index.html ${NGX_DOC_ROOT}
ADD entrypoint.sh /bin/

#nginx的配置文件必須以;爲結尾
CMD ["/usr/sbin/nginx","-g","daemon off;"]
ENTRYPOINT ["/bin/entrypoint.sh"]

製做鏡像

[root@host1 img3]# docker build -t miniser:v2-5 --build-arg new="tom@qq.com" ./
  • Dockerfile中的arg至關因而配置了一個默認值,在製做鏡像的時候,若是沒有傳值,就用默認值

注意區分ENV和ARG

  • docker run的時候能夠傳值,可是在docker build的時候是沒法傳值的

  • ENV所定義的變量在夠構建鏡像的時候使用的,而在構建鏡像的時候是隻能用ARG的默認值的

1七、指令17:ONBUILD指令

  • 本指令實際上是定義一個觸發器

  • 經過ONBUILD定義的Dcokerfile,在執行docker build的時候不執行,只有別人基於這個鏡像作新鏡像的時候,纔會被執行

案例:若是別人基於這個鏡像作新鏡像,就讓其下載一個文件

第一步:製做一個基礎鏡像

[root@host1 img3]# vim Dockerfile
FROM nginx:1.14-alpine
LABEL author="zxhk<237745635@qq.com>"

ENV NGX_DOC_ROOT='/data/web/html/'

ADD index.html ${NGX_DOC_ROOT}
ADD entrypoint.sh /bin/

ONBUILD ADD http://x.x.x.x/xxx /data/web/html/

#nginx的配置文件必須以;爲結尾
CMD ["/usr/sbin/nginx","-g","daemon off;"]
ENTRYPOINT ["/bin/entrypoint.sh"]

製做鏡像

[root@host1 img3]# docker build -t base:v1.1 ./

第二步:基於基礎鏡像作新鏡像

[root@host1 ~]# mkdir /img4
[root@host1 img4]# cd /img4
[root@host1 img4]# vim Dockerfile
FROM base:v1-1

RUN mkdir /data

製做鏡像

[root@host1 img4]# docker build -t newimg:v1-1 ./
相關文章
相關標籤/搜索