一、什么是dockerfile
Dockerfile是一個文本格式的配置文件,用戶可以使用Dockerfile自定義快速創建屬於自己的鏡像,Dockerfile是通過很多的參數指令編寫的文件,通過docker build 命令來創建鏡像
二、基本語法和結構
Dockerfile由一行行的命令語句組成,並且支持以#號注釋
一般情況,Dockerfile分為四部分:
- 基礎鏡像信息
- 維護者信息
- 鏡像操作指令
- 容器啟動執行的指令
其中,一開始必須指定所基於的鏡像信息名稱,接下來一般是說明的維護者信息,后面則是鏡像的操作指令,例如RUN指令,RUN指令將對鏡像執行跟隨的命令,每運行一條RUN指令,鏡像就會添加新的一層,並提交,最后是CMD指令,用來指定運行容器時操作的指令
三、參數指令說明
指令 | 說明 |
FROM | 指定創建鏡像的基礎鏡像 |
MAINTAINER | 指定維護者信息 |
RUN | 運行命令 |
CMD | 指定啟動容器時默認執行的命令 |
LABEL | 指定生成鏡像的元數據標簽信息 |
EXPOSE | 聲明鏡像內服務所監聽的端口 |
ENV | 指定環境變量 |
ADD | 復制指定的<src>路徑下的內容到容器中的<dest>下,<src>可以為URL,如果是tar文件,會自動解壓到<dest>路徑下 |
COPY | 復制本地主機的<src>路徑下的內容到鏡像中的<dest>路徑下,一般情況下這個常用 |
ENTRYPOINT | 指定鏡像的默認入口 |
VOLUME | 創建數據卷掛載點 |
USER | 指定運行容器的用戶名或者UID |
WORKDIR | 配置工作目錄 |
ARG | 指定鏡像內使用的參數(例如版本號等信息) |
ONBUILD | 配置當所創建的鏡像作為其他鏡像的基礎鏡像時,所執行的創建操作命令 |
STOPSIGNAL | 容器退出的信號值 |
HEALTHCHECK | 如何進行健康檢查 |
SHELL | 指定使用shell時默認shell類型 |
3.1. FROM (小寫 from)
指定所創建的鏡像的基礎鏡像,如果不存在,會去DockerHub去下載 格式: FROM<image> 或者 FROM<image>:<tag> 或者 FROM<image>@<digest> 任何Dockerfile中的第一條指令必須為FROM指令,並且如果在同一個Dockerfile中創建多個鏡像,可以使用多個FROM指令(每個鏡像各一條)
3.2. MAINTAINER (小寫 maintainer)
指定維護者信息 格式: MAINTAINER<name> 該信息會寫入到生成鏡像的Author屬性域中
例如:
MAINTAINER zhujingzhi@126.com
3.3. RUN (小寫 run)
運行指令命令 格式: RUN<command> 或者 RUN ["executable","paraml","param2"] 注意后一個指令會被解析為JSON的數組,因此必須要用雙引號 前者默認將在shell終端中運行命令,即/bin/sh -c 后者則是用exec執行,不會啟動shell環境 指定使用其他的終端類型可以用第二種方式,例如 RUN ["/bin/sh","-c","echo aaaa"] 每條RUN指令將在當前鏡像的基礎上執行指定命令,並提交為新的鏡像,命令長的時候可以使用 \ 來換行
例如:
RUN yum update \ && yum -y install net-tools openssh openssl \ && rm -rf /var/log/a.log
3.4. CMD (小寫 cmd)
CMD 指令用來指定啟動容器時默認執行的命令,有三種格式: 1、CMD ["executable","param1","param2"] 使用exec執行,推薦使用 2、CMD command param1 parma2 在/bin/sh中執行,提供給要交互的應用 3、CMD ["parma1","parma2"] 提供給ENTRYPOINT 的默認參數 每個Dockerfile只有一條CMD命令,如果指定了多條命令,只有最后一條會執行,如果啟動容器時手動指定了運行的命令(作為run的參數),會把CMD命令給覆蓋
3.5. LABEL (小寫 label)
LABEL 指令是用來指定生成鏡像的元數據標簽 格式: LABEL <key>=<value> <key>=<value> <key>=<value> .......
例如:
LABEL version="1.0" LABEL description="Zhu Jingzhi's mirror image"
3.6. EXPOSE (小寫 expose)
EXPOSE 聲明鏡像內服務監聽的端口 格式: EXPOSE <port> [<port>......] 注意,該指定是聲明的作用,不會自動的完成端口的映射 在啟動容器的時候需要使用-P 或 -p 來自動分配一個臨時端口或者指定具體的端口來做映射
例如:
EXPOSE 22 443 80
3.7. ENV (小寫 env)
ENV 指定環境變量,在鏡像生成的過程中會被后續的RUN 使用,在鏡像啟動的容器中也會存在 格式: ENV<key><value> 或者 ENV<key>=<value>....... 注意在 指令指定的環境變量在運行時可以被覆蓋掉 如: docker run --env <key>=<value> centos
例如:
ENV PY_VERSION 3.6.1 RUN curl -sSL http://python.org/ftp/python/3.6.1/Python-$PY_VERSION.tar.xz | tar -xJC /usr/src/python ENV PATH /usr/src/python=$PY_VERSION/bin:$PATH
3.8. ADD (小寫 add)
該命令將復制指定的<src>路徑下的內容到容器中的<dest>路徑下 格式: ADD <src> <dest> 其中<src>可以是Dockerfile所在目錄的一個相對路徑(文件或者目錄),也可以是URL,還可以是個tar文件(如果是tar文件,會自動解壓到<dest>路徑下),<dest>可以是鏡像內的絕對路徑,或者相對於工作目錄的相對路徑 路徑支持正則格式 例如: ADD *.tar /code/ tar壓縮包用這個還是很方便的
3.9. COPY (小寫 copy)
COPY 復制本地主機的<src>(為Dockerfile所在目錄的相對路徑、文件或者目錄)下的內容到鏡像中的<dest>目錄下,目錄不存在會自動創建 格式: COPY <src> <dest> 路徑同樣支持正則 當使用本地目錄為源目錄的時候,非常推薦使用戶CMD
例如:
COPY /opt/data/ /opt/
3.10. ENTRYPOINT (小寫 entrypoint)
ENTRYPOINT 指定鏡像的默認入口,該入口命令會在啟動容器時作為根命令執行,所有傳入值作為該命令的參數 格式: ENTRYPOINT ["executable","param1","param2"] 或者 ENTRYPOINT command param1 param2 此時,CMD指令指定的值將作為根命令的參數 每個Dockerfile 中只能有一個ENTRYPOINT 當指定多個的時候,只有最后一個生效 在運行時,可以被--entrypoint參數覆蓋
3.11. VOLUME (小寫volume)
VOLUME 創建一個掛載點 格式: VOLUME ["/data"] 可以從本地主機或者其他容器掛載數據卷,一般用來存放數據庫和需要保存的數據
3.12. USER (小寫 user)
USER 指定運行容器時的用戶名或UID ,后續的RUN指令也是使用指定的用戶 格式: USER daemon 當服務不需要管理員權限的時候,可以使用該命令指定運行用戶,並且可以在之前創建所需要的用戶 要臨時獲取管理員權限可以是用sudo
例如:
RUN groupadd -r nginx && useradd -r -g nginx nginx
3.13. WORKDIR (小寫 workdir)
WORKDIR 為后續的RUN CMD ENTRYPOINT 指令配置工作目錄 格式: WORKDIR /path/to/workdir 可以使用多個WORKDIR指令,后續命令如果參數是相對路徑,則會基於之前的命令指定路徑
例如:
WORKDIR /a WORKDIR b WORKDIR c 最終的路徑是 /a/b/c
3.14. ARG (小寫 arg)
ARG 指定一些鏡像內使用的參數(例如版本信息) 格式: ARG<name>=[=<default value>] 也可以用docker build --build-arg<name>=<value>來進行指定參數值
3.15. ONBUILD (小寫 onbuild)
ONBUILD 配置當所創建的鏡像作為其他鏡像的基礎鏡像時,所執行的創建操作指令 格式: ONBUILD [INSTRYCTION]
例如創建一個鏡像A:
[......] ONBUILD ADD ./app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src [......]
如果基於鏡像A創建新的鏡像,新的Dockerfile中使用FROM 鏡像A指定基礎鏡像,會自動執行鏡像A中的ONBUILD指令的內容,等價在后面添加了兩條指令
FROM 鏡像A # 等價於: ADD . /app/src RUN /usr/local/bin/python-build --dir /app/src
3.16. STOPSIGNAL (小寫 stopsignal)
STOPSIGNAL 指定所創建的鏡像啟動的容器接收的退出的信號值 例如: STOPSIGNAL signal
3.17. HEALTHCHECK (小寫 healthcheck)
HEALTHCHECK 配置所啟動容器如何進行健康檢查,Docker1.12 才開始支持 兩種格式: 1、HEALTHCHECK [OPTIONS] CMD command # 根據所執行命令的返回值是否為0來判斷 OPTIONS支持的參數: --interval=DURATION(默認30s) :過多久檢查一次 --timeout=DURATION(默認30s) : 每次檢查的超時時間 --retries=N(默認為:3) : 如果失敗了重試的次數 2、HEALTHCHECK NONE # 禁止基礎鏡像的中的健康檢查
3.18. SHELL (小寫 shell)
SHELL 指定其他命令使用shell時默認shell類型 格式: SHELL ["executable","parameters"] 默認值為["/bin/sh","-c"]
四、創建鏡像
創建完dockerfile文件后 可以使用docker build 命令來創建鏡像
基本的格式:
docker build [選項] Dockerfile路徑
該命令會讀取指定路徑下(包括子目錄)的Dockerfile,並將該路徑下的所有的內容發給docker服務端,由服務端來創建鏡像,因此建議除非生成鏡像需要,否則一般吧Dockerfile放到一個空的目錄中
兩點經驗:
- 如果使用非內容路徑下的Dockerfile,可以通過 -f 參數來指定路徑
- 要指定生成鏡像的標簽信息,可以使用 -t 參數
例如:
指定Dockerfile所在的路徑為/opt/docker_builder,並且希望生成鏡像的標簽為build_repo/image [root@nfs133 ~]# docker build -t zhujingzhi/nginx1.8.1 /root/docker_builder/ 如果是在Dockerfile的目錄下執行就是 [root@nfs133 ~]# docker build -t zhujingzhi/nginx1.8.1 . # 一定要加.呦
五、Dockerfile實戰文件
說了一堆的每個參數的語法格式,下面來做個實戰的dockerfile文件,來生成一個鏡像,並使用這個鏡像創建個容器,並運行起來,我們來使用nginx服務來做實戰
5.1. 下載基礎鏡像
[root@rsync131 ~]# docker pull centos Using default tag: latest Trying to pull repository docker.io/library/centos ... latest: Pulling from docker.io/library/centos 256b176beaff: Pull complete Digest: sha256:6f6d986d425aeabdc3a02cb61c02abb2e78e57357e92417d6d58332856024faf Status: Downloaded newer image for docker.io/centos:latest
5.2. 編寫Dockerfile文件
# 創建存儲Dockerfile文件的目錄 [root@rsync131 ~]# mkdir docker_builder [root@rsync131 ~]# cd /root/docker_builder/ # 下載需要的包 [root@rsync131 docker_builder]# wget http://nginx.org/download/nginx-1.8.1.tar.gz [root@rsync131 docker_builder]# wget http://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-7-11.noarch.rpm
編寫Dockerfile文件
[root@rsync131 ~]# cd /root/docker_builder/ [root@rsync131 docker_builder]# vim Dockerfile # This my first nginx Dockerfile # Version 1.0 # Base images 基礎鏡像 FROM centos #MAINTAINER 維護者信息 MAINTAINER zhujingzhi #ENV 設置環境變量 ENV PATH /usr/local/nginx/sbin:$PATH #ADD 文件放在當前目錄下,拷過去會自動解壓 ADD nginx-1.8.1.tar.gz /usr/local/ ADD epel-release-7-11.noarch.rpm /usr/local/ #RUN 執行以下命令 RUN rpm -ivh /usr/local/epel-release-7-11.noarch.rpm RUN yum install -y wget lftp gcc gcc-c++ make openssl-devel pcre-devel pcre && yum clean all RUN useradd -s /sbin/nologin -M nginx #WORKDIR 相當於cd WORKDIR /usr/local/nginx-1.8.1 RUN ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-pcre && make && make install RUN ln -s /usr/local/nginx/sbin/* /usr/local/sbin/ #EXPOSE 映射端口 EXPOSE 80 #CMD 運行以下命令 CMD ["nginx","-g","daemon off;"]
5.3. 構建鏡像並啟動容器
構建鏡像
[root@rsync131 docker_builder]# cd /root/docker_builder/ [root@rsync131 docker_builder]# docker build -t zhujingzhi/nginx1.8.1 . 過程就不粘貼了 因為太多了 大家執行自己看一下吧,會有Dockerfile的每一步的執行詳細信息
查看
[root@rsync131 docker_builder]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE zhujingzhi/nginx1.8.1 latest 236535a1cdd2 About a minute ago 350 MB docker.io/registry latest 2e2f252f3c88 12 days ago 33.3 MB docker.io/centos latest 5182e96772bf 6 weeks ago 200 MB 已經構建好了鏡像
啟動容器
[root@rsync131 docker_builder]# docker run -itd --name nginx1 -p 80:80 236535a1cdd2 8e23f4f849a33515c27e0bad92ff29442b7b2822be30dc235f30bf200d663f64 [root@rsync131 docker_builder]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8e23f4f849a3 236535a1cdd2 "nginx -g 'daemon ..." 2 seconds ago Up 2 seconds 0.0.0.0:80->80/tcp nginx1
5.4. 訪問測試
[root@rsync131 docker_builder]# curl 127.0.0.1 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>