FROM命令:repository爲基礎鏡像(base image)的名稱,tag爲base image的標籤,不指定就是latest。若是不指定registry,就從docker hub上拉取。html
FROM <registry><repository>[:<tag>]nginx
FROM <registry><repository>@<digest>c++
當從外部registry拉image時,image有可能被別人替換了,可是repository名字相同,因此不安全。digest是image的hash值,因此指定了digest就不會被別人替換掉了。web
MAINTAINER(不推薦使用,被LABLE替代了)命令:用於讓dockerfile製做者提供本人的詳細信息。docker
MAINTAINER能夠出如今任何位置,但推薦放到FROM後面。shell
LABEL命令:用於指定元數據,好比做者,文件大小等。centos
COPY命令:複製宿主機裏的文件或目錄到:要build出的image的文件系統的某個目錄裏。安全
語法:bash
文件複製準則:微信
src必須是dockerfile裏面的文件或目錄,不能是其父目錄中的文件或路徑。
若是src是目錄,則其內部文件或子目錄都會被遞歸複製,但src目錄自身不會被複制。
至關於:cp src/* /dest。
若是指定了多個src,或在src中使用了通配符,則dest必須是目錄,且必須以/結尾。
若是dest事先不存在,它將會被自動建立,其父目錄也會被一併建立。
好比COPY命令,若是目標目錄相同,則最好只使用一次COPY。雖然使用屢次COPY也不出錯誤,可是會多出層,性能很差。
獲取幫助信息:
# docker build --help Usage: docker build [OPTIONS] PATH | URL | - Build an image from a Dockerfile Options: --add-host list Add a custom host-to-IP mapping (host:ip) --build-arg list Set build-time variables --cache-from strings Images to consider as cache sources --cgroup-parent string Optional parent cgroup for the container --compress Compress the build context using gzip --cpu-period int Limit the CPU CFS (Completely Fair Scheduler) period --cpu-quota int Limit the CPU CFS (Completely Fair Scheduler) quota -c, --cpu-shares int CPU shares (relative weight) --cpuset-cpus string CPUs in which to allow execution (0-3, 0,1) --cpuset-mems string MEMs in which to allow execution (0-3, 0,1) --disable-content-trust Skip image verification (default true) -f, --file string Name of the Dockerfile (Default is 'PATH/Dockerfile') --force-rm Always remove intermediate containers --iidfile string Write the image ID to the file --isolation string Container isolation technology --label list Set metadata for an image -m, --memory bytes Memory limit --memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap --network string Set the networking mode for the RUN instructions during build (default "default") --no-cache Do not use cache when building the image --pull Always attempt to pull a newer version of the image -q, --quiet Suppress the build output and print image ID on success --rm Remove intermediate containers after a successful build (default true) --security-opt strings Security options --shm-size bytes Size of /dev/shm -t, --tag list Name and optionally a tag in the 'name:tag' format --target string Set the target build stage to build. --ulimit ulimit Ulimit options (default [])
dockerfile 例子1:拷貝一個文件。
FROM busybox:latest MAINTAINER "magedu <mage@magedu.com>" LABEL maintainer="magedu <mage@magedu.com>" COPY index.html /data/html/
build一下上面的dockerfile 試試,使用-t
,來指定image的名字和tag,發現build成功了。
# docker build -t tinyhttpd:v0.01 ./ Sending build context to Docker daemon 3.072kB Step 1/4 : FROM busybox:latest ---> b534869c81f0 Step 2/4 : MAINTAINER "magedu <mage@magedu.com>" ---> Using cache ---> 5c5a1c47716c Step 3/4 : LABEL maintainer="magedu <mage@magedu.com>" ---> Using cache ---> 88b87ddfdb22 Step 4/4 : COPY index.html /data/html/ ---> Using cache ---> 59b7dd6c3eb8 Successfully built 59b7dd6c3eb8 Successfully tagged tinyhttpd:v0.01
啓動這個image,看看裏面有沒有/data/html/index.html
# sudo docker run --name b1 --rm tinyhttpd:v0.01 cat /data/html/index.html <h1>http server</h1>
dockerfile 例子2:拷貝一個目錄。
FROM busybox:latest MAINTAINER "magedu <mage@magedu.com>" LABEL maintainer="magedu <mage@magedu.com>" COPY index.html /data/html/ COPY yum.repos.d /etc/yum.repos.d/
執行build:
docker build -t tinyhttpd:v0.02 ./ Sending build context to Docker daemon 30.21kB Step 1/5 : FROM busybox:latest ---> b534869c81f0 Step 2/5 : MAINTAINER "magedu <mage@magedu.com>" ---> Using cache ---> 5c5a1c47716c Step 3/5 : LABEL maintainer="magedu <mage@magedu.com>" ---> Using cache ---> 88b87ddfdb22 Step 4/5 : COPY index.html /data/html/ ---> Using cache ---> 59b7dd6c3eb8 Step 5/5 : COPY yum.repos.d /etc/yum.repos.d/ ---> 99d306a25cc7 Successfully built 99d306a25cc7 Successfully tagged tinyhttpd:v0.02
驗證:
docker run --name b1 -it --rm tinyhttpd:v0.02 ls /etc/yum.repos.d/ CentOS-Base.repo CentOS-Sources.repo CentOS-Base.repo_20191129 CentOS-Vault.repo CentOS-CR.repo CentOS-fasttrack.repo CentOS-Debuginfo.repo docker-ce.repo CentOS-Media.repo
ADD命令:相似COPY,比COPY多了支持壓縮類文件的自動解壓和從URL下載
語法:
ADD準則:
tar -x
;然而經過URL下載的壓縮文件不會自動展開。例子1:使用URL
FROM busybox:latest MAINTAINER "magedu <mage@magedu.com>" LABEL maintainer="magedu <mage@magedu.com>" COPY index.html /data/html/ COPY yum.repos.d /etc/yum.repos.d/ ADD http://nginx.org/download/nginx-1.2.9.tar.gz /usr/local/src
確認結果:
# docker run --name b1 --rm tinyhttpd:v0.03 ls /usr/local/src/ nginx-1.2.9.tar.gz
例子2:使用本地壓縮文件
FROM busybox:latest MAINTAINER "magedu <mage@magedu.com>" LABEL maintainer="magedu <mage@magedu.com>" COPY index.html /data/html/ COPY yum.repos.d /etc/yum.repos.d/ #ADD http://nginx.org/download/nginx-1.2.9.tar.gz /usr/local/src/ ADD nginx-1.2.9.tar.gz /usr/local/src/
確認結果:
# docker run --name b1 --rm tinyhttpd:v0.03 ls /usr/local/src/nginx-1.2.9 CHANGES CHANGES.ru LICENSE README auto conf configure contrib html man src
WORKDIR命令:用於dockerfile中全部RUN,CMD,ENTRYPOINT,COPY和ADD指定設定的工做目錄。
WORKDIR能夠出現屢次,這些命名去上面去找離它最近的WORKDIR做爲相對路徑的起始。
語法:
例子:
FROM busybox:latest MAINTAINER "magedu <mage@magedu.com>" LABEL maintainer="magedu <mage@magedu.com>" COPY index.html /data/html/ COPY yum.repos.d /etc/yum.repos.d/ #ADD http://nginx.org/download/nginx-1.2.9.tar.gz /usr/local/src/ WORKDIR /usr/local/ ADD nginx-1.2.9.tar.gz ./src1/
確認結果:
sudo docker run --name b1 --rm tinyhttpd:v0.03 ls /usr/local/src1/nginx-1.2.9 [sudo] password for ys: CHANGES CHANGES.ru LICENSE README auto conf configure contrib html man src
VOLUME:和run -v相似,但只能指定image裏的某個目錄,而不能指定宿主機的目錄。
語法:
注意:若是image掛載點目錄下有文件,則啓動容器後,會把掛載點下的文件拷貝到宿主機。
例子:
FROM busybox:latest MAINTAINER "magedu <mage@magedu.com>" LABEL maintainer="magedu <mage@magedu.com>" COPY index.html /data/html/ COPY yum.repos.d /etc/yum.repos.d/ #ADD http://nginx.org/download/nginx-1.2.9.tar.gz /usr/local/src/ WORKDIR /usr/local/ ADD nginx-1.2.9.tar.gz ./src/ VOLUME /usr/local/src
確認結果:因爲image的/usr/local/src目錄下有nginx-1.2.9,因此nginx-1.2.9會被拷貝到宿主機。
# docker run --name b1 -it --rm tinyhttpd:v0.03 # ls /var/lib/docker/volumes/1240925e87efaa5d9ed375b268a6d804c29013c04792f9a0dde9e135aa7e9f9e/_data/ nginx-1.2.9
EXPOSE:和-p選項類型,指定容器要暴漏給外部的端口,但不能指定宿主機的端口,由於在做dockerfile的時候,沒法肯定此image運行在什麼宿主機上。也就沒法知道宿主機上哪些端口可使用。因此是隨機去找宿主機裏可使用的端口。
注意:即便使用了EXPOSE命令,但若是RUN時不加-P
選項的話,端口也不會被暴露出去的。
語法:EXPOSE <port>[/protocol] <port>[/protocol]
例子:
FROM busybox:latest MAINTAINER "magedu <mage@magedu.com>" LABEL maintainer="magedu <mage@magedu.com>" COPY index.html /data/html/ COPY yum.repos.d /etc/yum.repos.d/ #ADD http://nginx.org/download/nginx-1.2.9.tar.gz /usr/local/src/ WORKDIR /usr/local/ ADD nginx-1.2.9.tar.gz ./src/ VOLUME /usr/local/src EXPOSE 80
確認結果:
啓動時先不指定-P
,用docker port查看,發現沒有端口。
# docker run --name b1 --rm tinyhttpd:v0.03 /bin/httpd -f -h /data/html/ # docker port b1
啓動時先指定-P
,用docker port查看,發現有端口。
# docker run --name b1 --rm -P tinyhttpd:v0.03 /bin/httpd -f -h /data/html/ # docker port b1 80/tcp -> 0.0.0.0:32768
EXPOSE的做用是:默認想暴露的端口,在啓動的時候,可使用-p
去覆蓋EXPOSE指定的端口。
ENV:在容器的系統了定義環境變量,ENV,ADD,COPY等指令可使用。
語法:
例子:${DOC_ROOT:-/data/html/}的用法是,if(DOC_ROOT 沒有值) {DOC_ROOT=/data/html/}
FROM busybox:latest MAINTAINER "magedu <mage@magedu.com>" LABEL maintainer="magedu <mage@magedu.com>" ENV DOC_ROOT=/data/html/ \ WEB_SERVER_PACKAGE="/nginx-1.2.9" COPY index.html ${DOC_ROOT:-/data/html/} COPY yum.repos.d /etc/yum.repos.d/ #ADD http://nginx.org/download/nginx-1.2.9.tar.gz /usr/local/src/ WORKDIR /usr/local/ ADD ${WEB_SERVER_PACKAGE}.tar.gz ./src/ VOLUME /usr/local/src EXPOSE 80
延申,在docker run的時候也可使用-e
選項設置環境變量。
在run的時候,經過-e,能夠改變dockerfile裏指定環境變量的值。
dockerfile裏定義的是nginx-1.2.9,可是-e指定的nginx-1.2.3,因此WEB_SERVER_PACKAGE=/nginx-1.2.3。
# docker run --name b1 --rm -e WEB_SERVER_PACKAGE=/nginx-1.2.3 tinyhttpd:v0.03 printenv PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=7a242517b02e WEB_SERVER_PACKAGE=/nginx-1.2.3
可是,/usr/local/src裏的目錄仍是nginx-1.2.9。由於在build的時點,image裏放的就已是nginx-1.2.9了,因此你在-e裏,改變的只是環境變量的值而已。
# docker run --name b1 --rm -e WEB_SERVER_PACKAGE=/nginx-1.2.3 tinyhttpd:v0.03 ls /usr/local/src nginx-1.2.9
RUN:在build執行過程當中,執行基礎鏡像裏能夠執行的任何shell命令。若是是多個命令是有關聯的話,最好寫到一塊兒。
語法:
例子:咱們指定ADD裏的src若是是壓縮文件的話,不會自動解壓縮,因此咱們RUN一個tar命令去解壓縮它。
FROM busybox:latest MAINTAINER "magedu <mage@magedu.com>" LABEL maintainer="magedu <mage@magedu.com>" ENV DOC_ROOT=/data/html/ \ WEB_SERVER_PACKAGE="nginx-1.2.9" COPY index.html ${DOC_ROOT:-/data/html/} COPY yum.repos.d /etc/yum.repos.d/ ADD http://nginx.org/download/${WEB_SERVER_PACKAGE}.tar.gz /usr/local/src/ RUN cd /usr/local/src && \ tar xf ${WEB_SERVER_PACKAGE}.tar.gz
RUN用途舉例:先找個基礎的centos鏡像,而後裝一個nginx,通常都是下載源代碼編譯安裝,不是使用yum install。理由是yum會產生多餘的文件。
FROM centos RUN yum -y install epel-release && \ yum makecache && \ yum install nginx
CMD:在docker build時不被運行,而是在docker run時運行。好比nginx鏡像啓動的時候,那麼CMD確定是啓動nginx的命令。因此CMD即便給了多個,只有最後一個生效。
語法:
CMD <command>
command一般是shell命令,並且是以/bin/sh -c來運行此命令,所以,是經過shell啓動的,因此可使用shell的特性,並且啓動結束後,shell進程會自動推出,讓此進程代替shell進程。因此它pid是1。
CMD ["executable1","arg1","executable2","arg1"]
executable是目錄名加上可執行程序名,好比/bin/ls。它不是經過/bin/sh -c來運行,是由內核直接啓動,因爲不是由shell啓動,因此shell裏的通配符,管道,重定向等特性,所有不能用。若是想用shell特性,能夠這麼使用:CMD ["/bin/bash","-c","executable","arg"].
RUN的第一種和第二種用法和CMD的第一種和第二種用法同樣。
CMD ["arg1","arg2"]
配合ENTRYPOINT命令使用。
例子:
FROM busybox LABEL maintainer="mageedu <mage@magedu.com>" app="httpd" ENV WEB_ROOT="/data/web/html/" RUN mkdir -p ${WEB_ROOT} && \ echo '<h1>Busybox httpd.</h1>' > ${WEB_ROOT}/index.html CMD /bin/httpd -f -h ${WEB_ROOT}
確認結果:用inspect確認,確實是用/bin/sh -c來啓動的。
"Cmd": [ "/bin/sh", "-c", "/bin/httpd -f -h ${WEB_ROOT}" ],
pid也是1
docker exec -it b1 /bin/sh / # ps PID USER TIME COMMAND 1 root 0:00 /bin/httpd -f -h /data/web/html/ 6 root 0:00 /bin/sh 11 root 0:00 ps # printenv HOSTNAME=e877c51f7dab WEB_ROOT=/data/web/html/
ENTRYPOINT:
相似CMD指令,用於爲容器指定默認運行程序。
與CMD不一樣的是,不會被docker run指定的參數覆蓋(也有覆蓋的辦法),並且docker run指定的參數,會自動加到ENTRYPOINT命令的後面,至關於ENTRYPOINT命令的參數了。
run時使用--entrypoint string選項,能夠強制替換ENTRYPOINT命令。
若是docker run時沒有指定參數,則使用上面CMD的第三種格式定義的參數,做爲ENTRYPOINT的參數。
若是docker run時指定了參數,CMD的第三種格式也指定了參數,ENTRYPOINT使用的是docker run時指定的參數,忽略CMD的第三種格式指定的參數。
dockerfile文件種也能夠出現多個ENTRYPOINT,但只有最後一個生效。
語法:
例子:在build時建立nginx的配置文件,並且在run的時候,還能夠經過-e參數傳遞環境變量,修改監聽的端口號等信息。
FROM nginx:alpine LABEL maintainer="MageEdu <mage@magedu.com>" ENV NGX_DOC_ROOT="/data/web/html/" ADD entrypoint.sh /bin/ ADD index.html ${NGX_DOC_ROOT} CMD ["/usr/sbin/nginx", "-g", "daemon off;"] ENTRYPOINT ["/bin/entrypoint.sh"]
ENTRYPOINT命令執行的是一個本身定義的shell命令文件,內容以下。
首先用cat命令建立了一個nginx的配置文件,還使用了環境變量。
而後,調用exec系統函數,參數是CMD定義的命令:["/usr/sbin/nginx", "-g", "daemon off;"]。exec函數的做用是:啓動ngxin進程,並終止當前進程(/bin/sh進程),讓nginx進程取代當前的shell進程,因此nginx進程的pid是1。
"$@":shell的所有參數,也就是/usr/sbin/nginx", "-g", "daemon off;
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 "$@"
當run的時候,執行ENTRYPOINT命令,參數是CMD裏定義的。
確認結果:經過-e把監聽端口設置成了8080;nginx的pid是1;www.conf也被建立了。在宿主機器上執行【curl -H "Host: a6b94dae9be4" 192.0.0.2:8080】,也輸出了index.html的結果。
# docker run --name b1 --rm -d -e "PORT=8080" mynignx:002 # docker exec -it b1 /bin/sh / # netstat -tnl Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN # cat /etc/nginx/conf.d/www.conf server { server_name a6b94dae9be4; listen 0.0.0.0:8080; root /data/web/html/; } / # ps PID USER TIME COMMAND 1 root 0:00 nginx: master process /usr/sbin/nginx -g daemon off; 8 nginx 0:00 nginx: worker process # cat /data/web/html/index.html <h1>nginx hello</h1> $ curl -H "Host: a6b94dae9be4" 192.0.0.2:8080 <h1>nginx hello</h1>
試驗一下,在run時,指定參數:/usr/sbin/nginx daemon off(故意不加-g),去覆蓋CMD。由於缺乏了-g,因此容器啓動失敗,說明了,確實覆蓋CMD裏定義的命令。
# docker run --name b1 --rm -d -e "PORT=8080" mynignx:002 /usr/sbin/nginx daemon off 4c88e021408c143ec45e70611c42bd715831cb9c75d6f4a00d307a7a6b53af5c [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
試驗一下,使用--entrypoint "/bin/sh",覆蓋ENTRYPOINT。
覆蓋成功了,1號進程是/bin/sh進程;www.conf文件沒有被建立;nginx進程沒有被啓動。
# docker run --name b1 --rm -it -e "PORT=8080" --entrypoint "/bin/sh" mynignx:002 / # ls bin dev home media opt root sbin sys usr data etc lib mnt proc run srv tmp var / # ps PID USER TIME COMMAND 1 root 0:00 /bin/sh 7 root 0:00 ps / # ls /etc/nginx/conf.d/ default.conf
ENTRYPOINT用法的最佳實踐:build以前事先建立好配置文件,build時,注入到image了。就能達到動態建立各類服務的配置文件,從而解決了只是由於配置文件的不一樣,而不得不建立多個image的問題。
USER
使用USER的背景,不指定USER的時候,進程的全部者都是root,好比下面的nginx。當不但願是root的時候,使用此命令。
/ # ps PID USER TIME COMMAND 1 root 0:00 nginx: master process nginx -g daemon off;
docker run,CMD,ENTRYPOINT執行的時候,所使用的用戶名或者UID
默認狀況下是root
語法:USER <UID> | <UserName>
UID或者UserName必須是在image裏存在的,必須存在於/etc/passwd中。
HEALTHCHECK:
按期查看容器裏運行的進程是否還在工做狀態。docker本身會自動檢查容器裏的進程是否還活着,若是死了或者不在前臺運行的時候,docker會自動殺死這個容器。但這是不夠的,有的容器即便活着,但不能提供服務了,那也至關於死了,因此要本身定義一個命令去檢查容器裏運行的進程,是否還在工做。
語法:
例子:健康檢查結果是正常的。
FROM nginx:alpine LABEL maintainer="MageEdu <mage@magedu.com>" ENV NGX_DOC_ROOT="/data/web/html/" ADD entrypoint.sh /bin/ ADD index.html ${NGX_DOC_ROOT} HEALTHCHECK --interval=3s --timeout=3s \ CMD wget -O - -q http://${IP:-0.0.0.0}:${PORT:-80}/ CMD ["/usr/sbin/nginx", "-g", "daemon off;"] ENTRYPOINT ["/bin/entrypoint.sh"]
結果確認:
# docker run --name b1 --rm mynginx:v001 127.0.0.1 - - [08/Dec/2019:13:54:18 +0000] "GET / HTTP/1.1" 200 612 "-" "Wget" "-" 127.0.0.1 - - [08/Dec/2019:13:54:21 +0000] "GET / HTTP/1.1" 200 612 "-" "Wget" "-" 127.0.0.1 - - [08/Dec/2019:13:54:25 +0000] "GET / HTTP/1.1" 200 612 "-" "Wget" "-"
例子:健康檢查結果是不正常的。發現不正常後,直接【kill 1】。容器啓動後,立刻就被殺死了。
FROM nginx:alpine LABEL maintainer="MageEdu <mage@magedu.com>" ENV NGX_DOC_ROOT="/data/web/html/" ADD entrypoint.sh /bin/ ADD index.html ${NGX_DOC_ROOT} HEALTHCHECK --interval=1s --timeout=1s --retries=1 \ CMD wget -O - -q http://${IP:-0.0.0.0}:10080/ || kill 1 CMD ["/usr/sbin/nginx", "-g", "daemon off;"] ENTRYPOINT ["/bin/entrypoint.sh"]
SHELL:指定用哪一個shell去運行RUN,CMD,ENTRYPOINT的命令,默認是/bin/sh -c。
STOPSIGNAL:【docker stop 容器名】默認是個PID爲1的進程發送15號信號。STOPSIGNAL能夠指定別的信號。
ARG:
在build時,經過【--build-arg】傳入到dockerfile裏面的變量
dockerfile裏能夠有多個ARG
語法: ARG <name>[=<default value>]
能夠在dockerfile裏定有ARG的默認值
ARG version=1.14
例子:
FROM nginx:alpine ARG author="MageEdu <mage@magedu.com>" LABEL maintainer=${author}
確認結果:build時,沒有使用--build-arg
# docker build -t mynginx:v002 ./ # docker image inspect mynginx:v002 "Labels": { "maintainer": "MageEdu <mage@magedu.com>" },
確認結果:build時,使用--build-arg
# docker build --build-arg author="abc <asd@sd.com>" -t mynginx:v002 ./ # docker image inspect mynginx:v002 "Labels": { "maintainer": "abc <asd@sd.com>" },
ONBUILD