Dockerfile是用於構建docker鏡像的腳本文件,通過編寫腳本,可以實現自定義鏡像。
Dockerfile關鍵字
FROM
基礎鏡像,Dockerfile第一條指令必須是FROM。
例如,下列就表示使用ubuntu的最新版本最爲基礎鏡像。
FROM ubuntu:latest
MAINTAINER
鏡像作者,例如:
MAINTAINER [email protected]
LABEL
LABEL
爲鏡像增加元數據,一個LABEL
是鍵值對,多個鍵值對之間使用空格分開,命令換行時是使用反斜槓\
。
建議使用LABEL指令替換MAINTAINER指令,例如:
LABEL author="lixingwu"
LABEL email="[email protected]"
LABEL version="1.0"
LABEL description="This is my Dockerfile."
添加後可使用 docker inspect
指令查看到添加的信息。
RUN
構建容器時運行的shell腳本。
# 運行安裝net-tools命令
RUN yum install net-tools
每一行RUN指令會生成一層Layer,所以儘量減少使用使用RUN指令,可以用&&
把多個命令寫在同一個RUN指令中,以減少Layer的層數。例如:
RUN apt-get update && \
apt-get install -y wget && \
mkdir /home/temp && \
cd /home/temp && \
touch readme.md
EXPOSE
聲明對外暴露的端口,只起到聲明作用,告訴使用者,運行該鏡像可以映射的端口。只有在使用-p
指令映射端口後才能通過端口訪問到鏡像。
例如,nginx鏡像提供80和443端口,就可以在dockerfile文件中使用如下命令聲明:
EXPOSE 80
EXPOSE 443
WORKDIR
在進入容器時,默認的目錄,起到落腳點的作用。例如:
WORKDIR /home
此時,在進入啓動容器後,就會自動定位到指定的目錄/home
,主要用於快速定位到目標目錄。假設是nginx容器,我們希望進入容器後就直接定位到nginx所在的目錄,而不是讓我們手動切換過去。
USER
指定鏡像運行時的用戶,通常情況下,爲了保證容器的安全性,我們都不會使用直接使用容器裏面的root用戶。
因爲root用戶權限太高
,容易訪問系統文件,失誤修改到關鍵文件,容易導致容器崩潰
。
我們通常會爲容器創建一個非root的用戶,然後賦予我們工作目錄的操作權限,保證該用戶只會操作我們允許操作的目錄和文件。
在使用USER
指令時,我們需要先保證該用已經存在,如果不存在,可以手動創建用戶:
RUN useradd -m -d /home/nginx -s /bin/sh -f -1 -c "this is a nginx" nginx
USER nginx
在構建完成後,我們進入容器,登錄的用戶就是設置的nginx
用戶。
docker build -t mynginx:0.0.1 .
docker run -it mynginx:0.0.1
# 使用whoami可查看當前登錄用戶,
# 因爲我們在Dockerfile中使用USER指令指定了,所以登錄後就是我們指定的用戶
nginx@cd4ee8b6a39a:/$ whoami
nginx
ENV
容器運行時環境變量。
# 定義項目根目錄
ENV WORK_PAYH /usr/work
# 使用環境變量
WORKDIR $WORK_PAYH
這些定義的環境變量可在運行時被覆蓋,比如,我們在dockerfile文件中定義環境變量。
ENV BASE_URL lhttp://ocalhost:8888
然後我們在啓動時覆蓋掉,容器裏的環境變量就會被覆蓋
。
docker run -it -e BASE_URL=http://localhost:9999 mynginx:0.0.2
# 在容器中輸出BASE_URL環境變量,已被覆蓋
nginx@1fe788f36758:/$ echo $BASE_URL
http://localhost:9999
ADD
把宿主機下的文件拷貝到容器,如果是tar壓縮包會自動解壓
,url會自動下載
;
# 把文件 myhostconfig.conf ,加入到容器 /home/nginx/ 目錄下
ADD myhostconfig.conf /home/nginx/
# 把文件 myhostconfig.conf ,加入到容器 /home/nginx/ 目錄下,並重新命名爲 my.conf
ADD myhostconfig.conf /home/nginx/my.conf
# 把 app.tar.gz 解壓到容器 /home/app/ 目錄下
ADD app.tar.gz /home/app/
# 把網絡資源下載到 /home/java/ 目錄下
ADD https://files.cnblogs.com/files/lixingwu/app.tar.gz /home/app1/
# 把當前目錄所有文件拷貝到容器/home/temp/目錄下
ADD . /home/temp/
# 把當前目錄下的txt文件,複製到容器/home/txt/目錄下
ADD *.txt /home/txt/
# 把文件夾data下的內容拷貝到到/home/mydata/目錄下,拷貝的文件不能有反斜槓
ADD data /home/mydata/
# 如果需要複製文件夾,把目標目錄也設置爲同名文件夾即可
ADD data /home/data/
注意:
-
下載網絡資源的壓縮包不會自動解壓,而且還會使鏡像
文件變大
,如果需要解壓網絡資源,可以使用RUN指令下載、解壓、刪除操作。 -
在複製全部文件時,如果需要忽略其中的一些文件,可以定義
.dockerignore
文件進行排除,.dockerignore語法和.gitignore
語法一致。 -
文件名儘量不要出現
中文
,不然複製時會被轉碼。 -
指令只拷貝目錄中的內容而
不包含目錄自身
。
COPY
把宿主機下的文件,原封不同的複製到鏡像容器下。該指令只能複製本地的文件,而且也不會自動解壓壓縮包。大多數情況都是使用copy指令,只有需要自動下解壓和自動下載url時才需要add指令。
copy指令的規則和add指令一致,複製本地文件、文件夾可平替,而且copy語義
上也更符合我們的操作。
COPY app.tar.gz /home/copy/app/
COPY . /home/copy/temp/
COPY *.txt /home/copy/txt/
COPY data /home/copy/mydata/
COPY data /home/copy/data/
VOLUME
掛載容器卷,持久化數據庫到宿主機,效果和-v
一樣。
例如:需把主機的/tmp/nginx
掛在到容器的/tmp
就可以寫成
VOLUME ["/tmp/nginx","/tmp"]
CMD
用於指定默認的容器主進程啓動命令。
可以使用 shell 腳本的方式,例如:CMD java -jar app.jar
也可以使用exec的方式:例如:CMD["java", "-jar", "app.jar"]
cmd指令只能寫一個,存在多個只有最後一個生效。
如果在run時加入參數,CMD指令會被覆蓋,例如:
docker run -it -p 8080:8080 tomcat /bin/bash
此時,/bin/bash
參數會把CMD指令覆蓋,會導致app沒有啓動起來。
ENTRYPOINT
用於指定默認的容器主進程啓動命令,不會被run時加入參數覆蓋,會把參數傳遞給ENTRYPOINT
指令。
例如:ENTRYPOINT["java", "-jar", "app.jar"]
,在啓動時傳入參數:
docker run -it -p 8080:8080 tomcat --spring.profiles.active=test
此時,啓動參數就會變成:
java -jar app.jar --spring.profiles.active=test
構建鏡像
使用build
執行構建腳本,命令最後的一個點是表示構建市時的上下文,點表示在執行命令的當前目錄。
在構建時,docker會在上下文中找到Dockerfile
文件,然後根據文件編寫的腳本鏡像鏡像構建,其中imagename
表示鏡像的名字,tag
表示鏡像的版本,鏡像名字可用重複,但是標籤不可以,如果出現同名同標籤時會覆蓋存在的鏡像文件。
docker build -t [imagename]:[tag] .
文章使用腳本源碼:gitee