Dockerfile
一、結構:
- 基礎鏡像資訊
- 維護者資訊
- 鏡像操作指令
- 容器啟動時執行指令
Dockerfile及Docker-compose YamlDockerfileDocker-compose
FROM
指明建構的新鏡像是來自于哪個基礎鏡像,例如:
FROM centos:6
MAINTAINER
指明鏡像維護着及其聯系方式(一般是郵箱位址),例如:
MAINTAINER Edison Zhou <[email protected]>
不過,MAINTAINER并不推薦使用,更推薦使用LABEL來指定鏡像作者,例如:
LABEL maintainer="xxxxx.cn"
RUN
建構鏡像時運作的Shell指令,例如:
RUN ["yum", "install", "httpd"]
RUN yum install httpd
CMD
啟動容器時執行的Shell指令,例如:
CMD ["-C", "/start.sh"]
CMD ["/usr/sbin/sshd", "-D"]
CMD /usr/sbin/sshd -D
EXPOSE
聲明容器運作的服務端口,例如:
EXPOSE 80 443
ENV
設定環境内環境變量,例如:
ENV MYSQL_ROOT_PASSWORD 123456
ENV JAVA_HOME /usr/local/jdk1.8.0_45
ADD
拷貝檔案或目錄到鏡像中,例如:
ADD <src>...<dest>
ADD html.tar.gz /var/www/html
ADD https://xxx.com/html.tar.gz /var/www/html
***PS:***如果是URL或壓縮包,會自動下載下傳或自動解壓
COPY
拷貝檔案或目錄到鏡像中,用法同ADD,隻是不支援自動下載下傳和解壓,例如:
COPY ./start.sh /start.sh
ENTRYPOINT
啟動容器時執行的Shell指令,同CMD類似,隻是由ENTRYPOINT啟動的程式不會被docker run指令行指定的參數所覆寫,而且,這些指令行參數會被當作參數傳遞給ENTRYPOINT指定指定的程式,例如:
ENTRYPOINT ["/bin/bash", "-C", "/start.sh"]
ENTRYPOINT /bin/bash -C '/start.sh'
***PS:***Dockerfile檔案中也可以存在多個ENTRYPOINT指令,但僅有最後一個會生效。
VOLUME
指定容器挂載點到主控端自動生成的目錄或其他容器,例如:
VOLUME ["/var/lib/mysql"]
***PS:***一般不會在Dockerfile中用到,更常見的還是在docker run的時候指定-v資料卷。
USER
為RUN、CMD和ENTRYPOINT執行Shell指令指定運作使用者,例如:
USER <user>[:<usergroup>]
USER <UID>[:<UID>]
USER edisonzhou
WORKDIR
為RUN、CMD、ENTRYPOINT以及COPY和AND設定工作目錄,例如:
WORKDIR /data
HEALTHCHECK
告訴Docker如何測試容器以檢查它是否仍在工作,即健康檢查,例如:
HEALTHCHECK --interval=5m --timeout=3s --retries=3 \
CMD curl -f http:/localhost/ || exit 1
其中,一些選項的說明:
- –interval=DURATION (default: 30s):每隔多長時間探測一次,預設30秒
- – timeout= DURATION (default: 30s):服務響應逾時時長,預設30秒
- –start-period= DURATION (default: 0s):服務啟動多久後開始探測,預設0秒
- –retries=N (default: 3):認為檢測失敗幾次為當機,預設3次
一些傳回值的說明:
- 0:容器成功是健康的,随時可以使用
- 1:不健康的容器無法正常工作
- 2:保留不使用此退出代碼
ARG
在建構鏡像時,指定一些參數,例如:
FROM centos:6
ARG user # ARG user=root
USER $user
這時,在docker build時可以帶上自定義參數user了,如下所示:
二、注意事項:
建構鏡像最具挑戰性的一點是使鏡像體積盡可能的小
使用 .dockerignore 排除建構無關檔案
.dockerignore` 文法與 `.gitignore` 文法一緻。使用它排除建構無關的檔案及目錄,如 `node_modules
使用多階段建構
對于多階段建構,可以在 Dockerfile 中使用多個
FROM
語句。每個
FROM
指令都可以使用不同的基鏡像,并且它們都開始了建構的新階段,示例如下:
FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]
在這種模式下,第二個FROM會以alpine:latest鏡像為基礎,開始一個新的建構,其中**–from=0**意為将前一階段的建構工件複制到此新階段。Go SDK 和任何中間工件都會被留下,不會儲存在最終的鏡像中
為建構階段命名
FROM
指令從 0 開始,也可以通過添加一個
AS <NAME>
到
FROM
指令來命名階段,示例如下:
FROM golang:1.7.3 AS builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]
在特定的建構階段停止
在建構映像時,不必建構包括每個階段的整個 Dockerfile。你可以指定目标建構階段。以下指令假設你正在使用之前的
Dockerfile
,但是在名為
builder
的階段停止:
$ docker build --target builder -t alexellis2/href-counter:latest .
這可能非常強有力的幾個場景是:
- 調試一個特定的建構階段
- 使用一個啟用了所有調試符号或工具的
階段和一個精益的調試(debug)
階段生産(production)
- 使用一個
階段,在這個階段你的應用會被測試資料填充,但是在建構産品時,使用一個使用真實資料的不同階段。測試(testing)
使用外部鏡像作為“階段”
當使用多階段建構時,您不受限于從 Dockerfile 中先前建立的階段進行複制。您可以使用
COPY --from
指令從單獨的鏡像中進行複制,可以使用本地鏡像名稱、本地或 Docker 系統資料庫上可用的标簽或标簽 ID。Docker 用戶端會在必要時拉取鏡像并從中複制工件。文法是:
COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf
把以前的階段作為新的階段
在使用
FROM
指令時,您可以引用前一階段的内容。例如:
FROM alpine:latest as builder
RUN apk --no-cache add build-base
FROM builder as build1
COPY source1.cpp source.cpp
RUN g++ -o /binary source.cpp
FROM builder as build2
COPY source2.cpp source.cpp
RUN g++ -o /binary source.cpp
避免安裝不必要的包
減小體積,減少建構時間。如前端應用使用
npm install --production
隻裝生産環境所依賴的包。
一個容器隻做一件事
如一個web應用将會包含三個部分,web 服務,資料庫與緩存。把他們解耦到多個容器中,友善橫向擴充。如果你需要網絡通信,則可以将他們至于一個網絡下,示例如下:
version: '3'
services:
# 該鏡像會暴露出自身的 `header` 資訊
whoami:
image: containous/whoami
restart: always
labels:
# 設定Host 為 whoami.docker.localhost 進行域名通路
- "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"
# 使用已存在的 traefik 的 network
networks:
default:
external:
name: traefik_default
減少鏡像層數
- 隻有
,RUN
,COPY
會建立層數, 其它指令不會增加鏡像的體積ADD
- 盡可能使用多階段建構
使用以下方法安裝依賴
RUN yum install -y node python go
錯誤的方法安裝依賴,這将增加鏡像層數
RUN yum install -y node
RUN yum install -y python
RUN yum install -y go
将多行參數排序
便于可讀性以及不小心地重複裝包
RUN apt-get update && apt-get install -y \
bzr \
cvs \
git \
mercurial \
subversion
充分利用建構緩存
在鏡像的建構過程中
docker
會周遊
Dockerfile
檔案中的所有指令,順序執行。對于每一條指令,
docker
都會在緩存中查找是否已存在可重用的鏡像,否則會建立一個新的鏡像
我們可以使用
docker build --no-cache
跳過緩存
-
和ADD
将會計算檔案的COPY
是否改變來決定是否利用緩存checksum
-
僅僅檢視指令字元串是否命中緩存,如RUN
可能會有問題RUN apt-get -y update
如一個
node
應用,可以先拷貝
package.json
進行依賴安裝,然後再添加整個目錄,可以做到充分利用緩存的目的。
FROM node:10-alpine as builder
WORKDIR /code
ADD package.json /code
# 此步将可以充分利用 node_modules 的緩存
RUN npm install --production
ADD . /code
RUN npm run build
三、常用指令:
docker build
指令用于使用 Dockerfile 建立鏡像
docker build [OPTIONS] PATH | URL | -
--build-arg=[] :設定鏡像建立時的變量;
--cpu-shares :設定 cpu 使用權重;
--cpu-period :限制 CPU CFS周期;
--cpu-quota :限制 CPU CFS配額;
--cpuset-cpus :指定使用的CPU id;
--cpuset-mems :指定使用的記憶體 id;
--disable-content-trust :忽略校驗,預設開啟;
-f :指定要使用的Dockerfile路徑;
--force-rm :設定鏡像過程中删除中間容器;
--isolation :使用容器隔離技術;
--label=[] :設定鏡像使用的中繼資料;
-m :設定記憶體最大值;
--memory-swap :設定Swap的最大值為記憶體+swap,"-1"表示不限swap;
--no-cache :建立鏡像的過程不使用緩存;
--pull :嘗試去更新鏡像的新版本;
--quiet, -q :安靜模式,成功後隻輸出鏡像 ID;
--rm :設定鏡像成功後删除中間容器;
--shm-size :設定/dev/shm的大小,預設值是64M;
--ulimit :Ulimit配置。
--tag, -t: 鏡像的名字及标簽,通常 name:tag 或者 name 格式;可以在一次建構中為一個鏡像設定多個标簽。
--network: 預設 default。在建構期間設定RUN指令的網絡模式
示例如下,使用目前目錄的 Dockerfile 建立鏡像,标簽為 runoob/ubuntu:v1:
docker commit :
從容器建立一個新的鏡像
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
-a :送出的鏡像作者;
-c :使用Dockerfile指令來建立鏡像;
-m :送出時的說明文字;
-p :在commit時,将容器暫停。
示例如下:
docker commit -a "runoob.com" -m "my apache" a404c6c174a2 mymysql:v1
**docker tag **
标記本地鏡像,将其歸入某一倉庫
示例如下,将鏡像ubuntu:15.10标記為 runoob/ubuntu:v3 鏡像:
docker tag ubuntu:15.10 runoob/ubuntu:v3
Docker-compose
結構
docker-compose.yml組成一個project,project裡包括多個service,每個service定義了容器運作的鏡像(或建構鏡像),網絡端口,檔案挂載,參數,依賴等,每個service可包括同一個鏡像的多個容器執行個體,即 project 包含 service ,service 包含 container ,示例如下:
version:"3.7"
services:
webapp:
build:
context:./dir
dockerfile:Dockerfile-alternate
args:
buildno:1
version
指定 docker-compose.yml 檔案的寫法格式
services
多個容器集合environment:環境變量配置,可以用數組或字典兩種方式
image
指定服務所使用的鏡像
image: java
expose
暴露端口,但不映射到主控端,隻被連接配接的服務通路。
僅可以指定内部端口為參數(一般用來辨別鏡像使用的端口,友善用ports映射)
expose:
- "3000"
- "8000"
ports
定義主控端端口和容器端口的映射,可使用主控端IP+主控端端口進行通路 主控端端口:容器端口
ports: # 暴露端口資訊 - "主控端端口:容器暴露端口"
- "8763:8763"
- "8763:8763"
volumes
動态挂載,卷挂載路徑,定義主控端的目錄/檔案和容器的目錄/檔案的映射 主控端路徑:容器路徑
volumes:
# 隻需指定一個路徑,讓引擎建立一個卷
- /var/lib/mysql
# 指定絕對路徑映射
- /opt/data:/var/lib/mysql
# 相對于目前compose檔案的相對路徑
- ./cache:/tmp/cache
# 使用者家目錄相對路徑
- ~/configs:/etc/configs/:ro
# 命名卷
- datavolume:/var/lib/mysql
environment
添加環境變量,可以使用數組或字典兩種形式, 任何布爾值; true,false,yes,no需要用引号括起來,以確定它們不被YML解析器轉換為True或False
environment:
RACK_ENV: development
SHOW: 'true'
SESSION_SECRET:
environment:
- RACK_ENV=development
- SHOW=true
- SESSION_SECRET
depend_on
規定service加載順序,例如資料庫服務需要在背景服務前運作
version: '2'
services:
db:
image: postgres
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
extra_hosts
類似于docker裡的–add-host參數 配置DNS域名解析(域名和IP的映射)
extra_hosts:
- "somehost:162.242.195.82"
- "otherhost:50.31.209.229"
restart
預設值為
no
,即在任何情況下都不會重新啟動容器;當值為
always
時,容器總是重新啟動;當值為
on-failure
時,當出現
on-failure
報錯容器退出時,容器重新啟動
restart: "no"
restart: always
restart: on-failure
restart: unless-stopped
privileged: true
開啟特權模式
user: root
指定容器運作的使用者名
networks/links
指定容器名稱進行不同容器間的通信
-
web: links: - db - db:database - redis
logging
日志服務
logging:
driver: "gelf"
options:
gelf-address: "udp://graylogserver:12201"
tag: front-tomcat
network_mode
設定網絡模式
network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"
build
置建構時,Compose 會利用它自動建構鏡像,該值可以是一個路徑,也可以是一個對象,用于指定 Dockerfile 路徑
注:如果指定build同時也指定image,那麼會從build裡建構,鏡像的名字和tag将取image指定的
logging
日志服務
logging:
driver: "gelf"
options:
gelf-address: "udp://graylogserver:12201"
tag: front-tomcat
network_mode
設定網絡模式
network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"
build
置建構時,Compose 會利用它自動建構鏡像,該值可以是一個路徑,也可以是一個對象,用于指定 Dockerfile 路徑
注:如果指定build同時也指定image,那麼會從build裡建構,鏡像的名字和tag将取image指定的
command
覆寫容器啟動後預設執行的指令
command: bundle exec thin -p 3000
----------------------------------
command: [bundle,exec,thin,-p,3000]