前面介紹了怎么通過容器生成鏡像,這里來記錄一下 DockerFile 構建鏡像,學習參考來自 菜鳥教程 。
作者:IT王小二
博客:https://itwxe.com
一、DockerFile是什么
Dockerfile 是一個用來構建鏡像的文本文件,文本內容包含了一條條構建鏡像所需的指令和說明。
-- 摘自菜鳥教程
說人話就是 Docker 提供了一系列的指令,Docker 引擎可以通過這些指令來構建出鏡像。
二、DockerFile指令
1 FORM
FORM 基礎鏡像
必須放在 DOckerfile 的第一行,表示從哪個 基礎鏡像 開始構建。
2 MAINTAINET
MAINTAINET 作者名稱
指定維護者的信息。
3 COPY
COPY [--chown=<user>:<group>] <源路徑1>... <目標路徑>
COPY [--chown=<user>:<group>] ["<源路徑1>",... "<目標路徑>"]
[--chown=<user>:<group>]:可選參數,用戶改變復制到容器內文件的擁有者和屬組
<目標路徑>:鏡像內的指定路徑,該路徑不用事先建好,路徑不存在的話,會自動創建
復制文件到鏡像,例如:
COPY hom* /mydir/
COPY hom?.txt /mydir/
和 ADD 不一樣的是源路徑不能訪問網絡資源,也不會自動解壓壓縮包。
4 ADD
ADD 指令和 COPY 的使用格式一致(同樣需求下,官方推薦使用 COPY)。功能也類似,不同之處如下:
- ADD 的優點:在執行 <源文件> 為 tar 壓縮文件的話,壓縮格式為 gzip, bzip2 以及 xz 的情況下,會自動復制並解壓到 <目標路徑>,源路徑可以使用網絡資源
- ADD 的缺點:在不解壓的前提下,無法復制 tar 壓縮文件。會令鏡像構建緩存失效,從而可能會令鏡像構建變得比較緩慢。具體是否使用,可以根據是否需要自動解壓來決定
5 RUN
shell 格式:
RUN <命令行命令>
# <命令行命令> 等同於,在終端操作的 shell 命令
exec 格式:
RUN ["可執行文件", "參數1", "參數2"]
# RUN ["./test.sh", "param1", "param2"] 等價於 RUN ./test.sh param1 param2
構建鏡像時執行的命令,RUN用於在鏡像容器中執行命令
RUN指令創建的中間鏡像會被緩存,並會在下次構建中使用。如果不想使用這些緩存鏡像,可以在構建時指定 --no-cache
參數,如:docker build --no-cache
。
同時為了使構建出來的鏡像的文件層數盡量小,shell 命令最好一次執行多條,使用 &&
連接,例如:mkdir data && cd data
。
6 CMD
CMD <shell 命令>
CMD ["<可執行文件或命令>","<param1>","<param2>",...]
CMD ["<param1>","<param2>",...] # 該寫法是為 ENTRYPOINT 指令指定的程序提供默認參數
類似於 RUN 指令,但是 CMD 是容器啟動時執行的命令,並且定義多個 CMD 命令的時候,僅最后一個會生效。
菜鳥教程中指出,推薦使用第二種,第一種格式實際上在運行的過程中也會自動轉換成第二種格式運行,並且默認可執行文件是 sh。
7 ENTRYPOINT
ENTRYPOINT ["<executeable>","<param1>","<param2>",...]
類似於 CMD 指令,但其不會被 docker run 的命令行參數指定的指令所覆蓋,而且這些命令行參數會被當作參數送給 ENTRYPOINT 指令指定的程序。
但是, 如果運行 docker run 時使用了 --entrypoint
選項,將覆蓋 CMD 指令指定的程序。
在執行 docker run 的時候可以指定 ENTRYPOINT 運行所需的參數。
和 CMD 類似,如果 Dockerfile 中如果存在多個 ENTRYPOINT 指令,僅最后一個生效。
可以搭配 CMD 命令使用:一般是變參才會使用 CMD ,這里的 CMD 等於是在給 ENTRYPOINT 傳參。
示例:
假設已通過 Dockerfile 構建了 nginx:test 鏡像:
FROM nginx
ENTRYPOINT ["nginx", "-c"] # 定參
CMD ["/etc/nginx/nginx.conf"] # 變參
1、不傳參運行。
docker run nginx:test
容器內會默認運行以下命令,啟動主進程。
nginx -c /etc/nginx/nginx.conf
2、傳參運行。
docker run nginx:test -c /etc/nginx/new.conf
容器內會默認運行以下命令,啟動主進程(/etc/nginx/new.conf:假設容器內已有此文件)。
nginx -c /etc/nginx/new.conf
8 EXPOSE
EXPOSE <端口1> [<端口2>...]
告訴Docker服務端暴露端口,在容器啟動時需要通過 -p 做端口映射。
9 EVN
ENV <key>=<value>
設置環境變量,定義了環境變量,那么在后續的指令中,就可以使用這個環境變量。
10 WORKDIR
WORKDIR <工作目錄路徑>
指定工作目錄。用 WORKDIR 指定的工作目錄,會在構建鏡像的每一層中都存在。
WORKDIR 指定的工作目錄,必須是提前創建好的。
11 USER
USER <用戶名>[:<用戶組>]
用於指定執行后續命令的用戶和用戶組,這邊只是切換后續命令執行的用戶(用戶和用戶組必須提前已經存在)。
12 VOLUME
VOLUME ["<路徑1>", "<路徑2>"...]
VOLUME <路徑>
定義匿名數據卷。在啟動容器時忘記掛載數據卷,會自動掛載到匿名卷,通常用於 MySQL 等保存需要持久化數據,啟動容器時也可以通過 -v 掛載。
三、演示例子
1、創建目錄,下載好編譯好的 jdk 文件上傳,項目 jar 包上傳。
mkdir /itwxe/DockerFile && cd /itwxe/DockerFile
2、創建 Dockerfile 文件,名字必須叫 Dockerfile,添加內容。
vim Dockerfile
# 添加內容,為了盡量多使用點指令,基於 centos 鏡像來演示,當然如果為了運行 jar 當然首選 openjdk 為基礎鏡像
# 基礎鏡像是 centos
FROM centos
# 維護者 itwxe
MAINTAINER itwxe
# 復制JDK
COPY jdk1.8.0_202 jdk1.8.0_202
# 將項目的添加到鏡像中
COPY sunny-admin.jar docker-sunny.jar
# 配置jdk環境
ENV JAVA_HOME=/jdk1.8.0_202
ENV PATH=$JAVA_HOME/bin:$PATH
ENV CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib
# 容器對外提供服務的端口是 9002
EXPOSE 9002
# 啟動容器后啟動app.jar的應用
ENTRYPOINT ["java","-jar","docker-sunny.jar"]
3、注意目錄結構
4、編譯並生成鏡像
其中 .
代表上下文路徑,該目錄下的文件都會打包進鏡像,我們的 jdk 和 jar 包就是都放在這個目錄下,當需要 COPY 等操作時都是從這個目錄下查找。
docker build -t itwxe/sunny-admin .
打包過程如下,可以看到鏡像創建成功。
5、創建容器運行看下,項目是否正常。
docker run -d --name sunny -p 9002:9002 itwxe/sunny-admin
可以看到項目正常運行,這是我自己寫的一個基礎應用框架,該有的基礎都有了,就差業務開發了,以后准備寫一個系列搭建教程,找個好一點的方向。
至此就成功通過 Dockerfile 創建鏡像並運行了,但是這種方式過於麻煩,需要上傳 jar 包到 Docker 環境,而作為一個 Java 程序員,當然不想使用這么麻煩的打包方式,下一篇開始通過 maven 插件一鍵打包 SpringBoot 鏡像並發布到服務器。
都讀到這里了,來個 點贊、評論、關注、收藏 吧!