文章目錄
- 1 Dockerfile介紹
- 2 基本結構
- 2.1 Dockerfile分為四部分
- 3 Dockerfile 基礎知識
- 4 Dockerfile常用指令
- 4.1 FROM
- 4.2 LABEL MAINTAINER
- 4.3 RUN
- 4.4 CMD
- 4.5 EXPOSE
- 4.6 ENV
- 4.7 COPY
- 4.8 ADD
- 4.9 ENTRYPOINT
- 4.10 VOLUME
- 4.11 USER
- 4.12 WORKDIR
- 4.13 ONBUILD
- 5 構建鏡像注意事項
- 6 使用Dockerfile構建apache鏡像
1 Dockerfile介紹
前面的docker鏡像管理章節有說到,構建鏡像的方式有兩種:
- 一種是基于容器制作
- 另一種就是通過Dockerfile,Dockerfile其實就是我們用來構建Docker鏡像的原始碼,當然這不是所謂的編程原始碼,而是一些命令的組合,只要理解它的邏輯和語法格式,就可以撰寫Dockerfile了,
簡要概括Dockerfile的作用:它可以讓用戶個性化定制Docker鏡像,因為作業環境中的需求各式各樣,網路上的鏡像很難滿足實際的需求,
2 基本結構
-
Dockerfile 是一個文本格式的組態檔,用戶可以使用 Dockerfile 快速創建自定義鏡像,
-
Dockerfile 由一行行命令陳述句組成,并且支持以 # 開頭的注釋行,
-
Dockerfile整體就兩類陳述句組成
- Comment 注釋資訊
- Instruction arguments 指令 引數,一行一個指令
- Dockerfile檔案名首字母必須大寫,
- Dockerfile指令不區分大小寫,但是為方便和引數做區分,通常指令使用大寫字母,
-
Dockerfile中指令按順序從上至下依次執行,
-
Dockerfile中第一個非注釋行必須是FROM指令,用來指定制作當前鏡像依據的是哪個基礎鏡像,
-
Dockerfile中需要呼叫的檔案必須跟Dockerfile檔案在同一目錄下,或者在其子目錄下,父目錄或者其它路徑無效,
2.1 Dockerfile分為四部分
- 基礎鏡像資訊
- 維護者資訊
- 鏡像操作指令
- 容器啟動時默認要執行的指令
3 Dockerfile 基礎知識
指令的一般格式為INSTRUCTION arguments,指令包括:
FROM #基礎鏡像,一切從這里開始構建
MAINTAINER #鏡像是誰寫的,姓名+郵箱
RUN #鏡像構建的時候需要運行的命令
ADD #步驟,tomcat鏡像,這個tomcat的壓縮包!添加內容
WORKDIR #鏡像的作業目錄
VOLUME #掛載的目錄
EXPOSE #暴露埠配置
CMD #指定這個容器啟動的時候要運行的命令,只有最后一個會生效,可被替代
ENTRYPOINT #指定這個容器啟動的時候要運行的命令,可以追加命令
ONBUILD #當構建一個被繼承 Dockerfile 這個時候就會運行ONBUILD 的指令
COPY #類似ADD,將我們檔案拷貝到鏡像中
ENV #構建的時候設定環境遍量
//示例
#第一行必須指定基于的基礎鏡像
FROM centos
#維護人的資訊
LABEL MAINTAINER="CWT <161774597@qq.com>"
#安裝httpd軟體包
RUN yum -y update && \
yum -y install httpd
#開啟80埠
EXPOSE 80
#復制網站首頁檔案至鏡像中web站點下
ADD index.html /var/www/html/index.html
#復制該腳本至鏡像中,并修改其權限
ADD httpd.sh /httpd.sh
RUN chmod 775 /httpd.sh
#當啟動容器時默認要執行的動作
CMD ["/httpd.sh"]
其中,一開始必須指明所基于的鏡像名稱,接下來一般會說明維護者資訊,
后面則是鏡像操作指令,例如RUN指令,RUN指令將對鏡像執行跟隨的命令,每運行一條RUN指令,鏡像添加新的一層,并提交,
最后是CMD指令來指定運行容器時的操作指令,
4 Dockerfile常用指令
4.1 FROM
第一條指令必須為FROM指令,并且,如果在同一個Dockerfile中創建多個鏡像時,可以使用多個FROM指令(每個鏡像一次)
//語法格式:FROM <image>或FROM <imagge>:<tag>
//構建新鏡像是基于那個鏡像
FROM centos:7
4.2 LABEL MAINTAINER
指定維護者資訊
//語法格式: MAINTAINER <name email_address>
LABEL MAINTAINER='1@126.com'
4.3 RUN
RUN指令將對鏡像執行跟隨的命令
//RUN指令的語法格式有兩種:
shell格式:(默認用/bin/sh -c來執行)
RUN <command> RUN <命令列命令>
# <命令列命令> 等同于,在終端操作的 shell 命令,
exec格式:
RUN ["executable","param1","param2"] RUN ["可執行檔案", "引數1", "引數2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等價于 RUN ./test.php dev offline
注意: 每運行一條RUN指令,鏡像添加新的一層,并提交,所以過多無意義的層,會造成鏡像膨脹過大,所以當命令較長時可以使用 \ 來換行
RUN echo "hello world\nhello tom" > /tmp/abc && \
cat /tmp/abc
4.4 CMD
- 指定啟動容器時默認執行的命令,即:如果docker run沒有指定任何的執行命令或者dockerfile里面也沒有ENTRYPOINT,那么就會使用執行CMD指定的默認的命令
- 每個 Dockerfile 只能有一條 CMD 命令,如指定了多條,只有最后一條被執行
- 如果用戶啟動容器時指定了運行的命令,如:docker run xxx /bin/bash,則/bin/bash 會覆寫 CMD 指定的命令
//語法格式:
CMD ["executable","param1","param2"]使用exec執行,推薦方式
CMD command param1 param2在/bin/sh中執行,提供給需要互動的應用
CMD ["param1","param2"]提供給ENTRYPOINT的默認引數
例如:CMD ["nginx", "-g", "daemon off;"]
4.5 EXPOSE
EXPOSE用于告訴Docker服務器容器暴露的埠號,供互聯系統使用,
在啟動容器時通過-P,Docker主機會自動分配一個埠轉發到指定的埠,使用-p則可以具體指定哪個本地埠映射過來
//語法格式:EXPOSE <port> [<port>...]
例如:EXPOSE 80 443 22
4.6 ENV
指定一個環境變數,會被后續 RUN 指令使用,并在容器運行時保持
//語法格式:
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
例如:
ENV NODE_VERSION 7.2.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"
4.7 COPY
- 復制本地主機的(為Dockerfile所在目錄的相對路徑,檔案或目錄)為容器中的,目標路徑不存在時會自動創建
- 使用 COPY 指令,源檔案的各種元資料都會保留,比如讀、寫、執行權限、檔案變更時間等
- 如果是目錄,只復制目錄內容,而非目錄本身
//語法格式:
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
[--chown=<user>:<group>]:可選引數,用戶改變復制到容器內檔案的擁有者和屬組,
<源路徑>:源檔案或者源目錄,這里可以是通配符運算式,其通配符規則要滿足 Go 的 filepath.Match 規則,例如:
COPY hom* /mydir/
COPY hom?.txt /mydir/
4.8 ADD
-
該命令將復制指定的到容器中的,其中可以是Dockerfile所在目錄的一個相對路徑(檔案或目錄);也可以是一個URL;還可以是一個tar檔案(會自動解壓為目錄)
-
ADD 指令和 COPY 的使用格式一致(同樣需求下,官方推薦使用 COPY),功能也類似,不同之處如下
- ADD 的優點:在執行 <源檔案> 為 tar 壓縮檔案的話,壓縮格式為 gzip, bzip2 以及 xz 的情況下,會自動復制并解壓到 <目標路徑>,
- ADD 的缺點:在不解壓的前提下,無法復制 tar 壓縮檔案,會令鏡像構建快取失效,從而可能會令鏡像構建變得比較緩慢,具體是否使用,可以根據是否需要自動解壓來決定,
-
如果src是目錄,只復制目錄中的內容,而非目錄本身
-
如果src是一個 URL ,下載后的檔案權限自動設定為 600
//語法格式:
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
例如:
ADD test /absoluteDir/
ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/
ADD --chown=1 files* /somedir/
ADD --chown=10:11 files* /somedir/
ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz
4.9 ENTRYPOINT
- 類似于 CMD 指令,但其不會被 docker run 的命令列引數指定的指令所覆寫,如果在docker run的后面提供了引數會被當作引數傳遞給 ENTRYPOINT 指令指定的程式,
- 每個Dockerfile中只能有一個ENTRYPOINT,當指定多個ENTRYPOINT時,只有最后一個生效,
- 但是, 如果運行 docker run 時使用了 --entrypoint 選項,此選項的引數可當作要運行的程式覆寫 ENTRYPOINT 指令指定的程式,
//語法格式:
ENTRYPOINT ["executable","param1","param2"]
ENTRYPOINT command param1 param2(在shell中執行)
例如:
FROM nginx
ENTRYPOINT ["nginx", "-c"] # 定參
CMD ["/etc/nginx/nginx.conf"] # 變參
運行容器:docker run nginx:test #沒有傳參
容器內會默認運行以下命令,啟動主行程,
nginx -c /etc/nginx/nginx.conf
docker run nginx:test -c /etc/nginx/new.conf #傳參
容器內會默認運行以下命令
nginx -c /etc/nginx/new.conf
4.10 VOLUME
創建一個可以從本地主機或其他容器掛載的掛載點,一般用來存放資料庫和需要保持的資料等
//語法格式:
VOLUME ["<容器內路徑1>", "<容器內路徑2>"...]
VOLUME <路徑>
//例如
VOLUME /data
4.11 USER
- 指定運行容器時的用戶名或 UID,后續的 RUN 也會使用指定用戶
- 這個用戶必須是事先建立好的,否則無法切換
- 要臨時獲取管理員權限可以使用 gosu,而不推薦 sudo
- 當服務不需要管理員權限時,可以通過該命令指定運行用戶,并且可以在之前創建所需要的用戶
//語法格式:
USER <user>[:<group>]
USER <UID>[:<GID>]
例如:
RUN groupadd -r mysql && useradd -r -g mysql mysql
USER mysql
4.12 WORKDIR
-
指定作業目錄,用 WORKDIR 指定的作業目錄,會在構建鏡像的每一層中都存在,(WORKDIR 指定的作業目錄,必須是提前創建好的),
-
docker build 構建鏡像程序中的,每一個 RUN 命令都是新建的一層,只有通過 WORKDIR 創建的目錄才會一直存在,
-
可以使用多個WORKDIR指令,后續命令如果引數是相對路徑,則會基于之前命令指定的路徑,
//語法格式:
WORKDIR <作業目錄路徑>
例如:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
最終路徑為/a/b/c
4.13 ONBUILD
用于延遲構建命令的執行,簡單的說,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次構建鏡像的程序中不會執行(假設鏡像為 test-build),當有新的 Dockerfile 使用了之前構建的鏡像 FROM test-build ,這是執行新鏡像的 Dockerfile 構建時候,會執行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令,
//語法格式:ONBUILD [INSTRUCTION]
例如,Dockerfile使用如下的內容創建了鏡像test-build
[...]
ONBUILD ADD nginx.conf /usr/local/nignx/nginx.conf
ONBUILD RUN mkdir /data
[...]
此時,如果基于test-build創建新的鏡像時,新的Dockerfile中使用FROM test-build指定基礎鏡像時,會自動執行ONBUILD指令的內容,等價于在后面添加了兩條指令,
FROM test-build
# Automatically run the following
ADD nginx.conf /usr/local/nignx/nginx.conf
RUN mkdir /data
5 構建鏡像注意事項
-
撰寫完成Dockerfile后,可以通過docker build命令來創建鏡像,
-
基本的格式為docker build [選項] 路徑,該命令將讀取指定路徑下(包括子目錄)的Dockerfile,并將該路徑下所有內容發送給Docker服務端,由服務端來創建鏡像,因此一般建議放置Dockerfile的目錄為空目錄,
-
另外,可以通過 .dockerignore 檔案(每一行添加一條匹配模式)來讓Docker忽略路徑下的目錄和檔案,
-
要指定鏡像的標簽資訊,可以通過-t選項,
-
例如,指定Dockerfile所在路徑為/tmp/docker_builder/,并且希望生成鏡像標簽為build_repo/first_image,可以使用下面的命令
docker build -t build_repo/first_image /tmp/docker_builder/
6 使用Dockerfile構建apache鏡像
//創建目錄
[root@docker ~]# ls
anaconda-ks.cfg
[root@docker ~]# mkdir /apache
[root@Docker ~]# cd /apache/
[root@Docker apache]# touch Dockerfile
[root@Docker apache]# ls
Dockerfile
[root@Docker apache]# mkdir packages
[root@Docker apache]# cd packages/
[root@Docker packages]# mv /usr/src/apr-1.7.0.tar.gz .
[root@Docker packages]# mv /usr/src/apr-util-1.6.1.tar.gz .
[root@Docker packages]# mv /usr/src/httpd-2.4.48.tar.gz .
[root@Docker ~]# tree
.
├── anaconda-ks.cfg
└── apache
├── Dockerfile
└── packages
├── apr-1.7.0.tar.gz
├── apr-util-1.6.1.tar.gz
└── httpd-2.4.48.tar.gz
/撰寫dockerfile
[root@Docker ~]# cat apache/Dockerfile
[root@docker apache]# cat Dockerfile
# 第一行必須指定基于的基礎鏡像
FROM centos
# 維護者資訊
LABEL MAINIAINER='123@qq.com'
# 將原始碼包傳到指定檔案,并會自動解壓
ADD packages/* /usr/src/
# 切換到當前所在目錄
WORKDIR /usr/src/
# 鏡像操作指令
# 下載所需的安裝包
RUN yum -y install openssl-devel pcre-devel pcre expat-devel libtool gcc gcc-c++ make && \
# 編譯安裝apr
cd apr-1.7.0 && sed -i '/$RM "$cfgfile"/d' configure && \
./configure --prefix=/usr/local/apr && make && make install && \
# 編譯安裝apr-util
cd ../apr-util-1.6.1 && \
./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr && \
make && make install && \
# 編譯安裝httpd
cd ../httpd-2.4.48 && \
./configure --prefix=/usr/local/apache \
--enable-so \
--enable-ssl \
--enable-cgi \
--enable-rewrite \
--with-zlib \
--with-pcre \
--with-apr=/usr/local/apr \
--with-apr-util=/usr/local/apr-util/ \
--enable-modules=most \
--enable-mpms-shared=all \
--with-mpm=prefork && \
make && make install
sed -i '/#ServerName/s/#//g' /usr/local/apache/conf/httpd.conf
#設定存盤卷
VOLUME ["/usr/local/apache/htdocs/"]
#啟動命令
CMD ["/usr/local/apache/bin/apachectl","-D","FOREGROUND"]
//創建鏡像
[root@Docker ~]# docker build -t caiaoc/apache:v1.0 /apache/
[root@docker apache]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
caiaoc/apache v1.0 b1386d62fb74 2 hours ago 701MB
nginx latest f652ca386ed1 5 days ago 141MB
busybox latest d23834f29b38 7 days ago 1.24MB
httpd latest ad17c88403e2 2 weeks ago 143MB
centos latest 5d0da3dc9764 2 months ago 231MB
//使用剛剛創建的鏡像啟動容器,開放埠,創建容器
[root@docker apache]# docker run --name apache1 -itd -p 80:80 caiaoc/apache:v1.0
7e6e7a2bc6b460eba55d55a61acdf89ac8d9e316ffa73ca0e541fddf378d9791
[root@docker apache]# docker exec -it apache1 /bin/bash
[root@7e6e7a2bc6b4 src]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:80 0.0.0.0:*
通過網頁訪問測驗

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/377028.html
標籤:其他
