天天看點

Dockerfile及Docker-compose YamlDockerfileDocker-compose

Dockerfile

一、結構:

  1. 基礎鏡像資訊
  2. 維護者資訊
  3. 鏡像操作指令
  4. 容器啟動時執行指令
    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]