Dockerfile 常用指令,對docker進行簡單操作

  • FROM
  • RUN
  • COPY
  • ADD
  • CMD
  • ENTRYPOINT
  • EVN
  • ARG
  • VOLUME
  • EXPOSE
  • WORKDIR
  • USER
  • HEALTHCHECK
  • ONBUILD

FROM

	定製鏡像一定是以一個鏡像爲基礎,在其上進行定製。比如定義 nginx 鏡像,基礎鏡像是必須指定的。 FROM 就是指定 基礎鏡像,在基礎鏡像的基礎上進行修改nginx內容。常見的基礎鏡像:	nginx、redis、mongo、mysql、httpd、php、tomcat 等。除此之外還包括一個特殊鏡像` scratch ` (空白的鏡像),如果你以 scratch 爲基礎鏡像的話,意味着你不以任何鏡像爲基礎,接下來所寫的指令將作爲鏡像第一層開始存在。
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

RUN

RUN 指令是用來執行命令行命令的。命令行的強大能力,RUN 指令在定製鏡像時是最常用的指令之一,。其格式有兩種:
注意  :::每個RUN都是一個新的容器。
shell 格式:RUN <命令>,就像直接在命令行中輸入的命令一樣。
		RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
exec 格式:RUN ["可執行文件", "參數1", "參數2"],這更像是函數調用中的格式。
FROM debian:stretch

RUN buildDeps='gcc libc6-dev make wget' \
    && apt-get update \
    && apt-get install -y $buildDeps \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && mkdir -p /usr/src/redis \
    && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
    && make -C /usr/src/redis \
    && make -C /usr/src/redis install \
    && rm -rf /var/lib/apt/lists/* \
    && rm redis.tar.gz \
    && rm -r /usr/src/redis \
    && apt-get purge -y --auto-remove $buildDeps

** 添加了清理工作的命令 **

COPY

COPY [--chown=<user>:<group>] <源路徑>... <目標路徑>
COPY [--chown=<user>:<group>] ["<源路徑1>",... "<目標路徑>"]

COPY 指令將從構建上下文目錄中 <源路徑> 的文件/目錄複製到新的一層的鏡像內的 <目標路徑> 位置。

CMD

CMD 指令的兩種格式:
	shell 格式:CMD <命令>
	推薦 ** exec 格式:CMD ["可執行文件", "參數1", "參數2"...]
參數列表格式:CMD ["參數1", "參數2"...]。在指定了 ENTRYPOINT 指令後,用 CMD 指定具體的參數。

使用shell 格式:

CMD echo $HOME  ===>運行時轉化爲:CMD [ "sh", "-c", "echo $HOME" ]

如果需要執行可執行文件,可直接使用 CMD ["可執行文件名", "-g", "daemon off;"]

eg: CMD ["nginx", "-g", "daemon off;"]

ENTRYPOINT

 ENTRYPOINT 的目的是在指定容器啓動程序及參數。ENTRYPOINT 在運行時也可以替代,不過比 CMD 要略顯繁瑣,需要通過 docker run 的參數 --entrypoint 來指定。
FROM ubuntu:18.04
RUN apt-get update \
    && apt-get install -y curl \
    && rm -rf /var/lib/apt/lists/*
CMD [ "curl", "-s", "https://ip.cn" ]

$ docker run myip
當前 IP:61.148.226.66 來自:北京市 聯通

$ docker run myip -i
docker: Error response from daemon: invalid header field value "oci runtime error: container_linux.go:247: starting container process caused \"exec: \\\"-i\\\": executable file not found in $PATH\"\n".
------------------------------------------------------
FROM ubuntu:18.04
RUN apt-get update \
    && apt-get install -y curl \
    && rm -rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl", "-s", "https://ip.cn" ]

$ docker run myip
當前 IP:61.148.226.66 來自:北京市 聯通

$ docker run myip -i
HTTP/1.1 200 OK
Server: nginx/1.8.0
Date: Tue, 22 Nov 2016 05:12:40 GMT
Content-Type: text/html; charset=UTF-8
Vary: Accept-Encoding
X-Powered-By: PHP/5.6.24-1~dotdeb+7.1
X-Cache: MISS from cache-2
X-Cache-Lookup: MISS from cache-2:80
X-Cache: MISS from proxy-2_6
Transfer-Encoding: chunked
Via: 1.1 cache-2:80, 1.1 proxy-2_6:8006
Connection: keep-alive

當前 IP:61.148.226.66 來自:北京市 聯通
  1. 啓動鏡像需要參數時,使用ENTRYPOINT可直接傳入參數。
  2. 啓動主進程時需要進行配置;如下啓動redis前添加用戶
FROM alpine:3.4
...
RUN addgroup -S redis && adduser -S -G redis redis
...
ENTRYPOINT ["docker-entrypoint.sh"]

EXPOSE 6379
CMD [ "redis-server" ]

下列腳本的內容就是根據 CMD 的內容來判斷,如果是 redis-server 的話,則切換到 redis 用戶身份啓動服務器,否則依舊使用 root 身份執行。

#!/bin/sh
...
# allow the container to be started with `--user`
if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then
    chown -R redis .
    exec su-exec redis "$0" "$@"
fi

exec "$@"

可用一下代替:

$ docker run -it redis id
uid=0(root) gid=0(root) groups=0(root)

EVN

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

node鏡像dockerfile中的有如下代碼:
先定義了環境變量 NODE_VERSION,其後的 RUN 這層裏,多次使用 $NODE_VERSION 來進行操作定製。

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" \
  && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
  && grep " node-v$NODE_VERSION-linux-x64.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
  && tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components=1 \
  && rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \
  && ln -s /usr/local/bin/node /usr/local/bin/nodejs

ARG 構建參數

格式:ARG <參數名>[=<默認值>]
Dockerfile 中的 ARG 指令是定義參數名稱,以及定義其默認值。該默認值可以在構建命令 docker build 中用 --build-arg <參數名>=<值> 來覆蓋。

VOLUME 定義匿名卷

VOLUME ["<路徑1>", "<路徑2>"...]
VOLUME <路徑>
EG: VOLUME /data
/data 目錄就會在運行時自動掛載爲匿名卷,任何向 /data 中寫入的信息都不會記錄進容器存儲層,保證了容器存儲層的無狀態化。運行時可以覆蓋這個掛載設置。比如:

docker run -d -v mydata:/data xxxx

EXPOSE 聲明端口

格式爲 EXPOSE <端口1> [<端口2>...]。
EXPOSE 指令是聲明運行時容器提供服務端口,這只是一個聲明,在運行時並不會因爲這個聲明應用就會開啓這個端口的服務。
好處:
	一個是幫助鏡像使用者理解這個鏡像服務的守護端口,以方便配置映射;
	另一個用處則是在運行時使用隨機端口映射時,也就是 docker run -P 時,會自動隨機映射 EXPOSE 的端口。

EXPOSE 僅僅是聲明容器打算使用什麼端口而已,並不會自動在宿主進行端口映射
-p <宿主端口>:<容器端口>將容器的對應端口服務公開給外界訪問

WORKDIR 指定工作目錄

格式爲 WORKDIR <工作目錄路徑>。

USER 指定當前用戶

格式:USER <用戶名>[:<用戶組>]
切換用戶時,該用戶需要事先創建,否則無法切換。
RUN groupadd -r redis && useradd -r -g redis redis
USER redis
RUN [ "redis-server" ]

如果以 root 執行的腳本,在執行期間希望改變身份,比如希望以某個已經建立好的用戶來運行某個服務進程,建議使用 gosu。
# 建立 redis 用戶,並使用 gosu 換另一個用戶執行命令
RUN groupadd -r redis && useradd -r -g redis redis
# 下載 gosu
RUN wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.7/gosu-amd64" \
    && chmod +x /usr/local/bin/gosu \
    && gosu nobody true
# 設置 CMD,並以另外的用戶執行
CMD [ "exec", "gosu", "redis", "redis-server" ]

HEALTHCHECK 健康檢查

判斷容器的狀態是否正常

格式:

HEALTHCHECK [選項] CMD <命令>:設置檢查容器健康狀況的命令
HEALTHCHECK NONE:如果基礎鏡像有健康檢查指令,使用這行可以屏蔽掉其健康檢查指令

當在一個鏡像指定了 HEALTHCHECK 指令後,用其啓動容器,初始狀態會爲 starting,在 HEALTHCHECK 指令檢查成功後變爲 healthy,如果連續一定次數失敗,則會變爲 unhealthy。

HEALTHCHECK 支持下列選項:

--interval=<間隔>:兩次健康檢查的間隔,默認爲 30 秒;
--timeout=<時長>:健康檢查命令運行超時時間,如果超過這個時間,本次健康檢查就被視爲失敗,默認 30 秒;
--retries=<次數>:當連續失敗指定次數後,則將容器狀態視爲 unhealthy,默認 3 次。
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s \
  CMD curl -fs http://localhost/ || exit 1

ONBUILD 爲他人做嫁衣裳

ONBUILD 是一個特殊的指令,它後面跟的是其它指令,比如 RUN, COPY 等,而這些指令,在當前鏡像構建時並不會被執行。只有當以當前鏡像爲基礎鏡像,去構建下一級鏡像的時候纔會被執行。

將下列基礎鏡像的Dockerfile

FROM node:slim
RUN mkdir /app
WORKDIR /app
ONBUILD COPY ./package.json /app
ONBUILD RUN [ "npm", "install" ]
ONBUILD COPY . /app/
CMD [ "npm", "start" ]

其他鏡像的douckerfile在使用上述基礎鏡像時ONbuild將執行。

FROM my-node
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章