一、命令詳解
Dockerfile構建鏡像是以基礎鏡像為基礎的,Dockerfile是一個文本文件,內容是用戶編寫的一些docker指令,每一條指令構建一層,因此每一條指令的內容,就是描述該層應當如何構建。
Dockerfile的基本指令有十三個,分別是:FROM、MAINTAINER、RUN、CMD、EXPOSE、ENV、ADD、COPY、ENTRYPOINT、VOLUME、USER、WORKDIR、ONBUILD
類型 | 命令 |
---|---|
基礎鏡像信息 | FROM |
維護者信息 | MAINTAINER |
鏡像操作指令 | RUN、COPY、ADD、EXPOSE、WORKDIR、ONBUILD、USER、VOLUME等 |
容器啟動時執行指令 | CMD、ENTRYPOINT |
1.1、FROM :指定基礎鏡像
所謂定制鏡像,那一定是以一個鏡像為基礎,在其上進行定制。就像我們之前運行了一個nginx鏡像的容器,再進行修改一樣,基礎鏡像是必須指定的。而FROM就是指定基礎鏡像,因此一個Dockerfile中FROM是必備的指令,並且必須是第一條指令。
如:指定ubuntu的14版本作為基礎鏡像
FROM ubuntu:14
1.2、 RUN:執行命令
RUN指令在新鏡像內部執行的命令,如:執行某些動作、安裝系統軟件、配置系統信息之類,
格式如下兩種:
1)shell格式:RUN< command > ,就像直接在命令行中輸入的命令一樣。
如在nginx里的默認主頁中寫”hello“:
RUN echo 'hello ' >/etc/nginx/html/index.html
2)exec格式:RUN ["可執行文件", "參數1", "參數2"]
如在新鏡像中用yum方式安裝nginx:
RUN ["yum","install","nginx"]
注:多行命令不要寫多個RUN,原因是Dockerfile中每一個指令都會建立一層.多少個RUN就構建了多少層鏡像,會造成鏡像的臃腫、多層,不僅僅增加了構件部署的時間,還容易出錯,RUN書寫時的換行符是\
1.3、COPY:復制文件
COPY命令用於將宿主機器上的的文件復制到鏡像內,如果目的位置不存在,Docker會自動創建。但宿主機器用要復制的目錄必須是和Dockerfile文件統計目錄下。
格式:
COPY [--chown=<user>:<group>] <源路徑>... <目標路徑>
COPY [--chown=<user>:<group>] ["<源路徑1>",... "<目標路徑>"]
如把宿主機中的package.json文件復制到容器中/usr/src/app/目錄下:
COPY package.json /usr/src/app/
1.4、CMD:容器啟動命令
CMD命令用於容器啟動時需要執行的命令,CMD在Dockerfile中只能出現一次,如果出現多個,那么只有最后一個會有效。
其作用是在啟動容器的時候提供一個默認的命令項。如果用戶執行docker run的時候提供了命令項,就會覆蓋掉這個命令,沒提供就會使用構建時的命令。
格式:
shell 格式:CMD <命令>
exec 格式:CMD ["可執行文件", "參數1", "參數2"...]
如容器啟動時進入bash:
CMD /bin/bash
也可以用exec寫法:
CMD ["/bin/bash"]
1.5 、MAINTAINER:指定作者
用來指定dockerfile的作者名稱和郵箱,主要作用是為了標識軟件的所有者是誰。
語法:
MAINTAINER <name> <email>
如:
MAINTAINER autor_jiabuli 6766633@qq.com
1.6、EXPOSE:暴露端口
EXPOSE命名適用於設置容器對外映射的容器端口號,如tomcat容器內使用的端口8081,則用EXPOSE命令可以告訴外界該容器的8081端口對外,在構建鏡像時
用docker run -p可以設置暴露的端口對宿主機器端口的映射。
語法:
EXPOSE <端口1> [<端口2>...]
如:
EXPOSE 8081
EXPOSE 8081 其實等價於 docker run -p 8081 當需要把8081端口映射到宿主機中的某個端口(如8888)以便外界訪問時,則可以用docker run -p 8888:8081
1.7、WORKDIR:配置工作目錄
WORKDIR命令是為RUN、CMD、ENTRYPOINT指令配置工作目錄。其效果類似於Linux命名中的cd命令,用於目錄的切換,但是和cd不一樣的是:如果切換到的目錄不存在,WORKDIR會為此創建目錄。
語法:
WORKDIR path
如需要在nginx目錄下創建一個hello.txt的文件:
##進入/usr/local/nginx目錄下
WORKDIR /usr/local/nginx
##進入/usr/local/nginx中的html目錄下
WORKDIR html
## 在html目錄下創建了一個hello.txt文件
RUN echo 'hello' > hello.txt
1.8、ENTRYPOINT:容器啟動執行命名
ENTRYPOINT的作用和用法和CMD一模一樣,但是ENTRYPOINT有和CMD有2處不一樣:
- CMD的命令會被docker run的命令覆蓋而ENTRYPOINT不會
- CMD和ENTRYPOINT都存在時,CMD的指令變成了ENTRYPOINT的參數,並且此CMD提供的參數會被 docker run 后面的命令覆蓋
1.9、VOLUME
VOLUME用來創建一個可以從本地主機或其他容器掛載的掛載點。例如我們知道tomcat的webapps目錄是放web應用程序代碼的地方,此時我們要把webapps目錄掛載為匿名卷,這樣任何寫入webapps中的心都不會被記錄到容器的存儲層,讓容器存儲層無狀態化。
格式:
VOLUME ["path"]
如創建tomcat的webapps目錄的一個掛載點
VOLUME /usr/local/tomcat/webapps
這樣,在運行容器時,也可以用過docker run -v來把匿名掛載點掛載都宿主機器上的某個目錄,如
docker run -d -v /home/tomcat_webapps:/usr/local/tomcat/webapps
1.10、 USER
USER命令用於指定當前望下執行的用戶,需要注意的是這個用戶必須是已經存在,否則無法指定。它的用法和WORKDIR有點像,切換用戶。
格式:
USER daemon
1.11、ADD
作用和使用方法和COPY一模一樣,在此不重復講述。 區別在於ADD指令不僅能夠將構建命令所在的主機本地的文件或目錄,而且能夠將遠程URL所對應的文件或目錄,作為資源復制到鏡像文件系統。但由於ADD指令不支持認證,如果從遠程獲取資源需要認證,則只能使用RUN wget或RUN curl替代。
RUN mkdir -p /usr/src/things && curl -SL http://example.com/big.tar.xz | tar -xJC /usr/src/things && make -C /usr/src/things all
1.12、ONBUILD
ONBUILD用於配置當前所創建的鏡像作為其它新創建鏡像的基礎鏡像時,所執行的操作指令。
意思就是:這個鏡像創建的時候不會執行ONBUILD的內容,如果其它鏡像以這個鏡像為基礎創建鏡像,就會先執行基礎鏡像的ONBUILD命令,通常用語構建基礎鏡像。
格式:
ONBUILD [INSTRUCTION]
#構建ONBUILD鏡像
FROM node:slim RUN
mkdir /app WORKDIR /app
ONBUILD COPY ./package.json /app
ONBUILD RUN [ "npm", "install" ]
ONBUILD COPY . /app/
CMD [ "npm", "start" ]
#使用
FROM my-node
1.13、ENV:設置環境變量
ENV命名用於設置容器的環境變量,這些變量以”key=value”的形式存在,在容器內被腳本或者程序調用,容器運行的時候這個變量也會保留。
格式:
- 1) 設置一個: ENV
- 2) 設置多個:ENV
= = ...
如設置一個環境變量JAVA_HOME,接下來的命名就可以使用這個變量:
ENV JAVA_HOME ``/opt/jdk``ENV PATH $PATH:$JAVA_HOME``/bin
在使用ENV設置環境變量時,有幾點需要注意:
- 1)具有傳遞性,也就是當前鏡像被用作其它鏡像的基礎鏡像時,新鏡像會擁有當前這個基礎鏡像所有的環境變量
- 2)ENV定義的環境變量,可以在dockerfile被后面的所有指令(CMD除外)中使用,但不能被docker run 的命令參數引用
如:
ENV tomcat_home_name tomcat_7``RUN ``mkdir` `$tomcat_home_name
3)除了ENV之外,docker run -e 也可以設置環境變量傳入容器內。
如:
docker run -d tomcat -e ``"tomcat_home_name=tomcat_7"
這樣我們進入容器內部用ENV可以看到tomcat_home_name這個環境變量。
二、示例
2.1、nodejs程序
制定node鏡像的版本
#FROM node:8.9-alpine
FROM node:10.15.3
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
ADD . /app
WORKDIR /app
#RUN npm install
EXPOSE 3000
CMD ["npm", "run", "public"]
2.2、python
FROM hub.ict.ac.cn/dev/python3.7:my
# auther
MAINTAINER rock
# set time zone;
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo '$TZ' > /etc/timezone
# Creating Application Source Code Directory
RUN mkdir -p /prometheusAPI
# Setting Home Directory for containers
WORKDIR /prometheusAPI
# Installing python dependencies
COPY requirements.txt /prometheusAPI
RUN pip install --user -r requirements.txt
# Copying src code to Container
COPY . /prometheusAPI
# Running Python Application
CMD ["sh", "/prometheusAPI/start.sh"]
三、打包
3.1、docker pull基礎鏡像
docker pull xxx:xx
3.2、編寫dockerfile文件
使用docker build構建鏡像,格式:docker build [OPTIONS] PATH | URL | -
OPTIONS有很多指令,下面列舉幾個常用的:
--build-arg=[] :設置鏡像創建時的變量;
-f :指定要使用的Dockerfile路徑;
--force-rm :設置鏡像過程中刪除中間容器;
--rm :設置鏡像成功后刪除中間容器;
--tag, -t: 鏡像的名字及標簽,通常 name:tag 或者 name 格式;
示例:
把dockerfile放到項目目錄內,cd到項目目錄,執行
docker build -t prometheusAPI:Vtest .
3.3、將打包好的鏡像上傳到鏡像庫(可選)
3.4、測試構建好的鏡像
docker run --rm hub.ict.ac.cn/dev/prmetheusapi:V1
注:使用cmd構造的鏡像,docker run測試的時候不能加任何命令:比如docker run --rm hub.ict.ac.cn/dev/prmetheusapi:V1 /bin/bash
/bin/bash 內容會覆蓋掉CMD。正確的命令應該是docker run --rm hub.ict.ac.cn/dev/prmetheusapi:V1