一、簡介
- 使用現有的容器使用docker commit 生成鏡像
- 使用Dockerfile進行鏡像構建
二、Dockerfile介紹
語法規則
環境變量引用
docker build命令
- -t, --tag list 指定生成鏡像標簽,格式為name:tag
- -f, --file string 單獨指定Dockerfile文件位置
- --build-arg list 設置構建時的變量
- --no-cache 構建鏡像時候不使用緩存
快速開始
mkdir /opt/demo -p
cd /opt/demo/
FROM centos:latest #指定基礎鏡像為centos LABEL Author=“wd” #指明作者 RUN yum install -y yum epel-release && yum install -y nginx && echo "${HOSTNAME}-nginx server" > /usr/share/nginx/html/index.html #運行命令安裝Nginx CMD [ "/usr/sbin/nginx", "-g", "daemon off;", "-c", "/etc/nginx/nginx.conf”] #啟動容器運行的命令
[root@app51 demo]# docker build -t nginx:v1 ./ Sending build context to Docker daemon 2.048kB Step 1/4 : FROM centos:latest ---> 1e1148e4cc2c Step 2/4 : LABEL Author="wd" ---> Using cache ---> 8eb3ffcb8ba3 Step 3/4 : RUN yum install -y yum epel-release && yum install -y nginx && echo "${HOSTNAME}-nginx server" > /usr/share/nginx/html/index.html ---> Using cache ---> ac91999a716e Step 4/4 : CMD [ "/usr/sbin/nginx", "-g", "daemon off;", "-c", "/etc/nginx/nginx.conf"] ---> Running in 323afd4ac89d Removing intermediate container 323afd4ac89d ---> 6403c553fd04 Successfully built 6403c553fd04 Successfully tagged nginx:v1
[root@app51 demo]# docker run -d --name nginx-demo-c1 -p 8088:80 nginx:v1 08812b7def62c9ad7879dfa4182bc28a20f524e2dbc5eb6e4fe63d2b67be3cc9 [root@app51 demo]# curl http://127.0.0.1:8088 60e5de135132-nginx server #訪問成功 [root@app51 demo]#
三、指令詳解
FROM
FROM <repository> FROM <repository>[:<tag>] FROM <repository>@<digest>
FROM centos:latest
LABEL
LABEL <key>=<value> <key>=<value> <key>=<value> ...
示例:
LABEL "com.example.vendor"="ACME Incorporated” LABEL maintainer="SvenDowideit@home.org.au"
MAINTAINER (deprecated)
MAINTAINER <message>
MAINTAINER "wd <xxx@163.com>"
COPY
用於主機中的文件或者復制到鏡像中
語法:
COPY [--chown=<user>:<group>] <src>... <dest> COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
- 如果復制的src或dest中存在空格字符需使用第二種加雙引號方式
- src必須是 build的上下文目錄(Dockerfile同級目錄或子目錄),不能是父目錄或者絕對路徑
- 如果指定來多個src或者src中使用了通配符,則dest必須是一個目錄,且必須以/結尾
COPY hom* /mydir/ #拷貝以hom開頭的的所有文件 COPY hom?.txt /mydir/ #?代表占位符,可以拷貝
ADD
ADD指令類似於COPY,但是ADD比COPY更強大,支持TAR文件和URL路徑
語法:
ADD [--chown=<user>:<group>] <src>... <dest> ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
- 當src是URL時,如果dest不以/結尾,則src指定的文件將被下載並且被創建為dest,如果dest以/結尾,則src指定下載的文件會保存在dest目錄下。
- 當src是一個本地目錄的一個tar壓縮格式文件,其在容器中會被展開為目錄,類型與tar -x命令,通過URL下載的tar文件則不會被解壓。
- 如果指定來多個src或者src中使用了通配符,則dest必須是一個目錄,且必須以/結尾,多個文件一同被復制在dest目錄下
ADD hom* /mydir/
ADD hom?.txt /mydir/
WORKDIR
WORKDIR dirpath
示例:
WORKDIR /usr/local
ENV
用於為鏡像定義所需的環境變量,並可被Dockfile中位於其以后的指令所調用,如ADD、COPY、RUN等調用格式為$variable_name或者${variable_name},此外在啟動容器時候這些變量也是存在的。
語法:
ENV <key> <value>
ENV <key>=<value> ...
- 第一種格式中key之后的所有值會被作為value,因此一次只能設置一個變量
- 第二種格式可一次性設置多個變量,每個變量為一個key=value的鍵值對,如果value種包含空格,可以用反斜線(\)轉義,也可以通過對value加引號進行標識,此外反斜線也可用於續行,多個變量時候建議使用。
示例:
ENV myName="John Doe” \ myDog=Rex \ myCat=fluffy ENV myCat fluffy
RUN
用於在build過程中運行的程序,可以是任何指令,可以指定多個RUN
語法:
RUN <command> #shell 格式默認linux采用/bin/sh -c,windows采用cmd /S /C RUN ["executable", "param1", "param2”] #可執行程序格式
示例:
RUN yum install -y nginx RUN ["/bin/bash", "-c", "echo hello"]
EXPOSE
用於為容器暴露端口到外部,用於實現通訊,類似於docker run的-p選項
語法:
EXPOSE <port> [<port>/<protocol>...]
EXPOSE 8080
EXPOSE 8080/udp 8088/tcp
VOLUME
用於在image中創建一個掛載目錄,以掛載宿主機上的目錄
語法:
VOLUME <path> VOLUME ["path"]
VOLUME ["/var/log/“] VOLUME /myvol
CMD
CMD command param1 param2 #shell格式,含有shell環境 CMD ["executable","param1","param2”] #可執行程序格式 CMD ["param1","param2”] #第三種用於為ENTRYPOINT提供默認參數
注意:
- 在第一種格式中command 通常是一個shell命令,且默認以/bin/sh -c來運行它,這意味着此進程在容器的的PID不為1,不能接受unix信號,因此使用docker stop <container>命令停止容器時,此進程接受不到SIGTERM信號。
- 第二種格式是可執行程序運行方式,不會以"/bin/sh -c”來發起,無shell環境,所有shell變量不能引用,但是可以用"/bin/bash -c”作為啟動命令達到第一種格式效果
- 第三種格式需要結合ENTRYPOINT使用,作用是為其提供默認參數
ENTRYPOINT
ENTRYPOINT <command> ENTRYPOINT ["<executable>", "<param1>", "<param2>"]
- 與CMD類似,第一種方式默認會以/bin/sh -c 啟動,而第二種則不會,也就意味着沒有shell環境
- 通常ENTRPOINT用於使用ENTRPOINT腳本啟動
- 當CMD與ENTRYPOINT同時存在時,CMD的參數為ENTRYPOINT提供
示例:
[“nginx”,"-g","daemon off"]
USER
USER <user>[:<group>]
USER <UID>[:<GID>]
- 指定的USER或者GROUP必須在容器中存在,否則指令會運行失敗
USER nginx
STOPSIGNAL
語法:
STOPSIGNAL signal
示例:
STOPSIGNAL SIGKILL
- 向容器發送信號只能被PID=1的進程所接收,當PID=1進程不是應用進程時候,應用進程收不到終止信號。
HEALTHCHECK
HEALTHCHECK [OPTIONS] CMD command
其中OPTIONS有如下選項:
- --interval=DURATION 檢查間隔(默認: 30s)
- --timeout=DURATION 超時時間(默認t: 30s)
- --start-period=DURATION 等待檢查的時間,默認0s代表一啟動就檢查 (默認: 0s)
- --retries=N (default: 3) 重試次數
示例:
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost/ || exit 1
SHELL
將可執行程序運行為shell環境,默認以/bin/sh -c運行
語法:
SHELL ["executable", "parameters"]
示例:
SHELL ["echo", “hello"] #等價於 RUN echo hello
ARG
ARG <name>[=<default value>]
FROM nginx ARG CONF="/tmp/nginx.conf" LABEL Author=wd RUN touch "${CONF}"
構建鏡像:
[root@app51 ~]# docker build --build-arg CONF='/etc/test.conf' -t nginx:v15.2 ./ Sending build context to Docker daemon 225.6MB Step 1/4 : FROM nginx ---> f09fe80eb0e7 Step 2/4 : ARG CONF="/tmp/nginx.conf" ---> Using cache ---> ac081589c644 Step 3/4 : LABEL Author=wd ---> Using cache ---> 53b9b0ba4460 Step 4/4 : RUN touch "${CONF}" ---> Running in 50debe96f876 Removing intermediate container 50debe96f876 ---> d8680a2433bc Successfully built d8680a2433bc Successfully tagged nginx:v15.2
運行容器查看:
[root@app51 ~]# docker run --rm nginx:v15.2 ls /etc/test.conf -l -rw-r--r-- 1 root root 0 Feb 27 11:18 /etc/test.conf
ONBULD
用於在Dockerfile中定義一個觸發器,當制作出來的鏡像被別人用於基礎鏡像時候自動觸發。
語法:
ONBUILD [INSTRUCTION]
- ONBUILD不會觸發FROM指令。
- 在鏡像標簽中應明確指出onbuild關鍵字,以標記使用其基礎鏡像會觸發其他指令
示例:
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
四、使用multi-stage
FROM golang:1.7.3 WORKDIR /go/src/github.com/alexellis/href-counter/ RUN go get -d -v golang.org/x/net/html COPY app.go . RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/ COPY --from=0 /go/src/github.com/alexellis/href-counter/app . CMD ["./app"]
命名stage
默認情況下,stage未命名,可以通過整數來引用它們,第一個stage表示0,第二個表1以此類推。 但是,當有多個stage時候,這樣會顯得麻煩,Docker提供AS 語法可以為stage命名:
FROM golang:1.7.3 as builder
然后在另一個stage中使用:
COPY --from=builder /go/src/github.com/alexellis/href-counter/app .
使用本地stage
除了可以使用Dockerfile中的stage外,構建鏡像時候還可以直接使用本地已存在的環境和產物,例如:
COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf
構建鏡像建議
- 基礎鏡像盡量選擇比體積較小的鏡像,如每個官方發行的alpine鏡像。雖然這版本鏡像比較小,但是與之帶來的是利用該類鏡像運行的容器中排錯的命令很少;
- 使用RUN指令時候,盡量把多個RUN指令合並為一個,通常做法是使用&&符號;
- 通過multi-stage方法減少一些不必要使用的環境來減小鏡像;
- 安裝完成軟件同時刪除一些不需要的文件或目錄;