前言
今晚整理整理dockerfile作為再戀筆記。
那誰沒事安心后隨筆整理,想想都心痛。
Dockerfile
? Dockerfile是用于自定義構建Docker鏡像的規則文件。編輯好了Dockerfile文件后,使用docker build
即可構建一個鏡像。構建一個怎樣的鏡像那就得看Dockerfile文件。我們來看看具體的Docker有哪些內容與規則。
基本結構
(1) 文件的編輯類似鍵值對
,一個鍵配置一個值,規范而言,鍵為大寫、值要小寫
(2) 使用#
注釋
(3) 整體分為四個部分:鏡像信息、作者信息、鏡像構建指令信息、容器啟動執行指令信息
指令說明
-
FROM
from
說明:指定構建的鏡像基于哪個鏡像,該指令必須位于Dockerfile的第一個指令,倘若不存在該鏡像,那就默認從Docker hub拉下來。
FROM <image> # or FROM <image><:tag>
示例 :基于debain的jessie版本
FROM debian:jessie
-
**MAINTAINER **
maintainer
說明:描述構建者的信息等等。
MAINTAINER <message>
示例:作者AlicFeng 郵箱alic@samego.com
MAINAINER AlicFeng <alic@samego.com>
-
**RUN **
run
說明:構建鏡像要執行的shell指令,默認通過/bin/sh解析器進行解析,也可以指定解析器。
RUN <command> # or RUN ["executable","param1","param2"]
示例 1 :更新源并安裝并安裝make,注意安裝時一定要使用-y,不然有時會出錯
RUN apt-get update \ apt-get install make
示例2:執行
ls -l
shell指令,并指定/bin/bash
解析器RUN ["/bin/bash","ls","-l"]
-
CMD
cmd
說明:構建的容器啟動時要執行的指令。注意主注意注意、cmd指令只能包含一條,多的話只執行最后一條。
CMD ["executable", "param1", "param2"] #將會調用exec執行,首選方式 # or CMD ["param1", "param2"] #當使用ENTRYPOINT指令時,為該指令傳遞默認參數 # or CMD <command> ["param1","param2"] #將會調用/bin/sh -c執行
示例 1:容器啟動時執行
/root/start.sh
腳本。CMD ["/root/start.sh"]
示例 2:執行
nginx -g daemon off
CMD ["nginx", "-g", "daemon off"]
-
ENTRYPOINT
entrypoint
說明:entrypoint與cmd指令類似,entrypoint在dockerfile中只能出現一次,否則只執行最后一條。它是配置容器啟動后執行的命令。
ENTRYPOINT ["executable", "param1", "param2"] #將會調用exec執行,首選方式 # or ENTRYPOINT <command> ["param1","param2"] #將會調用/bin/sh -c執行
*示例 *:執行
/etc/init.d/nginx restart
命令ENTRYPOINT ["/etc/init.d/nginx","restart"]
-
EXPOSE
expose
說明:指定暴露的端口,供容器之間聯系( -link )使用。
EXPOSE <port> [.....]
示例:暴露3306端口
EXPOSE 3306
-
ENV
env
說明:指定環境變量,容器運行時也可以指定,這里起到定義的作用。
ENV <key> <value> # or ENV <key>=<value>
示例 1:設置一個IP環境變量為127.0.0.1。
ENV IP=127.0.0.1
示例 2:設置一個ngixn_dir環境變量為/app/server/nginx。
ENV nginx_dir /app/server/nginx WORKDIR $nginx_dir
-
ADD
add
說明:拷貝文件,將src拷貝到dest目錄下。注意:src支持文件或目錄或遠程URL,同時src為當前目錄的相對目錄,而dest是容器的絕對路徑,默認拷貝后文件或目錄的權限為0775,要是src為容器可識別的壓縮文件,那么將會自動解壓,這點要注意!
ADD <src> <dest>
示例 1:拷貝一個遠程文件,該文件的URL為https://sise.samego.com/Linux/redis.tar.gz,注意,該文件為容器識別的文件,將會自動解壓。
ADD https://sise.samego.com/Linux/redis.tar.gz /app #執行之后dest為/app/redis/...
示例 2:將
/root/bak/conf/redis.conf
文件拷貝到/app/redis/
目錄下。ADD /root/bak/conf/redis.conf /app/redis/
-
COPY
copy
說明:copy與add類似,但是copy的功能比較簡潔,沒有add強大,不支持遠程URL,但是src源文件為容器本地文件或目錄的時候,推薦使用copy。
COPY <src> <dest>
示例:將
/root/bak/conf/redis.conf
文件拷貝到/app/redis/
目錄下。ADD /root/bak/conf/redis.conf /app/redis/
?
-
VOLUME
volume
說明:指定容器的掛載點,使容器中的一個目錄具有持久化存儲數據的功能,該目錄可以被容器本身使用,也可以共享給其他容器使用。我們知道容器使用的是AUFS,這種文件系統不能持久化數據,當容器關閉后,所有的更改都會丟失。當容器中的應用有持久化數據的需求時可以在Dockerfile中使用該指令。
VOLUME ["path",...]
示例 :掛載
/data/mysql/data
目錄。VOLUME ["/data/mysql/data/"]
-
WORKDIR
workdir
說明:指定工作目錄。有時執行RUN指令時需要切換目錄,那就通過workdir指令進行切換。切換目錄后在下一次切換之前都是在此目錄下。可以是相對目錄也可以是絕對路徑。
WORKDIR <path>
示例:將工作目錄切換至
/app/nginx
目錄。WORKDIR /app/nginx
-
USER
user
說明:指定容器運行執行RUN、CMD指令時的用戶,注意:在下一次切換用戶之前將一直使用該用戶。
USER <username | uid>
示例:切換用戶為same。
USER alic
-
ONBUILD
onbuild
說明:配置當所創建的鏡像作為其它新創建鏡像的基礎鏡像時,所執行的操作指令。
ONBUILD [INSTRUCTION]
示例:比如有這樣一個基礎鏡像
same:basic
,在構建same:latest
時,在basic基礎鏡像中使用ONBUILD聲明的ONBUILD RUN apt-get update
指令,構建latest版本也將會自動執行。# 這是same:basic ONBUILD RUN apt-get update
# 這是same:latest正在構建的鏡像 FROM same:basic # 構建時將自動執行基于basic鏡像使用ONBUILD的指令 如下 RUN apt-get update
構建鏡像示例
說明:基于alpine:3.5構建一個Redis鏡像。
FROM alpine:3.5 # 創建一個redis用戶組并創建一個redis用戶將其增加在redis用戶組 RUN addgroup -S redis && adduser -S -G redis redis # grab su-exec for easy step-down from root RUN apk add --no-cache 'su-exec>=0.2' # 定義環境變量 ENV REDIS_VERSION 3.2.8 ENV REDIS_DOWNLOAD_URL http://download.redis.io/releases/redis-3.2.8.tar.gz ENV REDIS_DOWNLOAD_SHA1 6780d1abb66f33a97aad0edbe020403d0a15b67f # for redis-sentinel see: http://redis.io/topics/sentinel RUN set -ex \ \ && apk add --no-cache --virtual .build-deps \ gcc \ linux-headers \ make \ musl-dev \ tar \ \ && wget -O redis.tar.gz "$REDIS_DOWNLOAD_URL" \ && echo "$REDIS_DOWNLOAD_SHA1 *redis.tar.gz" | sha1sum -c - \ && mkdir -p /usr/src/redis \ && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \ && rm redis.tar.gz \ \ # Disable Redis protected mode [1] as it is unnecessary in context # of Docker. Ports are not automatically exposed when running inside # Docker, but rather explicitely by specifying -p / -P. # [1] https://github.com/antirez/redis/commit/edd4d555df57dc84265fdfb4ef59a4678832f6da && grep -q '^#define CONFIG_DEFAULT_PROTECTED_MODE 1$' /usr/src/redis/src/server.h \ && sed -ri 's!^(#define CONFIG_DEFAULT_PROTECTED_MODE) 1$!\1 0!' /usr/src/redis/src/server.h \ && grep -q '^#define CONFIG_DEFAULT_PROTECTED_MODE 0$' /usr/src/redis/src/server.h \ # for future reference, we modify this directly in the source instead of just supplying a default configuration flag because apparently "if you specify any argument to redis-server, [it assumes] you are going to specify everything" # see also https://github.com/docker-library/redis/issues/4#issuecomment-50780840 # (more exactly, this makes sure the default behavior of "save on SIGTERM" stays functional by default) \ && make -C /usr/src/redis \ && make -C /usr/src/redis install \ \ && rm -r /usr/src/redis \ \ && apk del .build-deps # 還是RUN指令 RUN mkdir /data && chown redis:redis /data # 指定掛載目錄 VOLUME /data # 切換當前的目錄為/data WORKDIR /data # 拷貝文件 COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] # 暴露6379端口 EXPOSE 6379 # 容器啟動時執行redis-server命令 CMD [ "redis-server" ]
快要閉館了,快速借助redis托管在github的一個Dockerfile作為簡單的示例。
Alic say :****價值源于技術,貢獻源于分享****