安裝
首先在Docker的官方網站下下載相應的版本,由于默認宿主機均為Mac,所以直接下載Mac版本,其中Docker-Compose(Docker官方的Orchestration項目之一,主要負責快速在集群中部署應用)已經默認安裝在Mac版本的Docker中,所以無需再額外下載。
基本使用(Dockerfile)
docker build
假設基本已經知道了Docker的基本知識,直接進入主體。
首先,單個鏡像是基于Dockerfile來生成的,Dockerfile可以認為是描述這個鏡像的腳本,在其上下文環境中,使用docker build就可以運行Dockerfile生成鏡像。比如在文件test中,Dockerfile也是在這個文件中,運行build
docker build .
其中 (.) 代表著就是dockerfile所在的上下文環境。 (.) 不可缺少。 可以將上下文理解為傳入docker build中的參數,不一定是(.) 。也可以是路徑,甚至是URL。基本語法如下
#選項可以在官方文檔中查閱到
docker build [選項] <上下文路徑/URL/->
其他build用法如下,還可以直接用Git repository來構建
$ docker build https://github.com/twang2218/gitlab-ce-zh.git#:8.14 docker build https://github.com/twang2218/gitlab-ce-zh.git\#:8.14 Sending build context to Docker daemon 2.048 kB
Step 1 : FROM gitlab/gitlab-ce:8.14.0-ce.0
8.14.0-ce.0: Pulling from gitlab/gitlab-ce
aed15891ba52: Already exists
773ae8583d14: Already exists
...
這行命令指定了構建所需的 Git repo
,并且指定默認的 master
分支,構建目錄為 /8.14/
, 然后 Docker
就會自己去 git clone
這個項目、切換到指定分支、并進入到指定目錄后開始構建。
具體Dockerfile中命令如下
# 這行代表著我們制作的鏡像是基于官方的nodejs最新版本的,由FROM開頭,冒號之后代表的是版本號,如果不填寫,會默認為最新版(latest)
FROM node:latest
# 這行定義的是維護人和維護人郵箱,由MAINTAINER開頭
MAINTAINER lossp “richard.xxmxx@gmail.com”
# 第一行是定義運行創造/home/Service命令
#第二行是定義工作目錄為/home/Servive
RUN mkdir -p /home/Service
WORKDIR /home/Service
#第一行是從上下文環境中的/home/Service 復制文件,copy命令的源路徑都是相對路徑
#第二行是執行npm install 命令
COPY . /home/Service
RUN npm install
# 將端口3000暴露出來,可以供外界訪問,或者映射到宿主機的端口上去
EXPOSE 3000
CMD [ "npm", "start" ]
FROM
FROM - 其中FROM命令是必須的,但是不一定需要基于某一個鏡像,可以從0開始構建,此時就需要使用scratch,scratch代表著一個空白的鏡像。此時基本命令就是
FROM scratch
MAINTAINER
MAINTAINER - 就是將維護人信息添加到腳本文件中,不一定需要,可有可無。
RUN
RUN - RUN命令是用來執行基本命令的,基本格式有兩種,第一種是Shell格式,RUN <命令>;
RUN npm install
第二種是exec格式,如下
RUN ["可執行文件", "參數1", "參數2"]
第二種更像是函數中的調用格式。
由于Dockerfile每一個命令都會建立一層,RUN也不例外。
FROM debian:jessie
RUN apt-get update
RUN apt-get install -y gcc libc6-dev make
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" RUN mkdir -p /usr/src/redis
RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1
RUN make -C /usr/src/redis
RUN make -C /usr/src/redis install
類似上述例子,一共構建了7層鏡像,這是完全沒有意義的,而且很多運行時不需要的東西,都被裝進了鏡像里,比如編譯環境、更新的軟件包等等。結果就是產生非常臃腫、非常 多層的鏡像,不僅僅增加了構建部署的時間,也很容易出錯。
正確的編寫應該如下例子
FROM debian:jessie
RUN buildDeps='gcc libc6-dev make' \
&& apt-get update \
&& apt-get install -y $buildDeps \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.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
首先,之前所有的命令只有一個目的,就是編譯、安裝redis可執行文件。因此沒有必要建立 很多層,這只是一層的事情。因此,這里沒有使用很多個 RUN
對一一對應不同的命令,而是 僅僅使用一個RUN
指令,并使用 &&
將各個所需命令串聯起來。將之前的7層,簡化為了1層。其中每行命令后的 \ 代表著換行,使dockerfile的RUN命令更具有可讀性。
此外,命令的最后一行還有一個 --auto-remove
命令,這個為清理工作的命令,刪除了編譯所需要的軟件,清理下載以及展開的文件,并且還清理了apt
緩存文件。由于鏡像是一層一層構建的,每一層的多余東西并不會在下一層中被刪除掉,到后面,鏡像會越來越大。因此清理這些沒有用處的東西很有必要。
COPY
COPY - copy命令的源路徑都是相對路徑,比如
COPY ./package.json /app/
這并不是要復制執行 docker build
命令所在的目錄下的 package.json
,也不是復制 Dockerfile
所在目錄下的 package.json
,而是復制 上下文(context) 目錄下的 package.json
。
一般來說,應該會將 Dockerfile
置于一個空目錄下,或者項目根目錄下。如果該目錄下沒 有所需文件,那么應該把所需文件復制一份過來。如果目錄下有些東西確實不希望構建時傳 給 Docker
引擎,那么可以用.gitignore
一樣的語法寫一個.dockerignore
,該文件是用于 剔除不需要作為上下文傳遞給 Docker
引擎的。
這只是默認行為,實際上 Dockerfile
的文件名并不要求必須為 Dockerfile
,而且并不要求 必須位于上下文目錄中,比如可以用 -f ../Dockerfile.php
參數指定某個文件作為Dockerfile
CMD
CMD - CMD容器啟動命令。CMD命令和RUN命令相似,也是兩種格式,分別為shell命令格式和exec命令格式。
Docker 不是虛擬機,容器就是進程。既然是進程,那么在啟 動容器的時候,需要指定所運行的程序及參數。CMD 指令就是用于指定默認的容器主進程的 啟動命令的。
在exec命令格式上,一般會被解析成json數組格式,需要用雙引號,不能使用單引號!!!
Docker-compose
Compose的定位是定義和運行多個 Docker 容器的應用(Defining and running multi- container Docker applications)。
由于Dockerfile對于僅僅是單個鏡像而言,而在正常的開發環境中,我們需要多個容器協調合作來完成某一個工作,比如一個web項目,除了web本身以外,還需要均衡負載,數據庫等。
compose恰好能滿足這樣的要求,compose允許用戶通過一個docker-compose.yml模版文件來定義互相關聯的容器,來組成為一個項目。
compose中有如下兩個重要的概念
---服務(Service): 一個應用的容器,實際上可以包括若干運行相同鏡像的容器實例
---項目(project): 由一組關聯的應用容器組成的一個完整業務單元,在 docker- compose.yml 文件中定義。
compose默認的管理對象是項目,通過子命令對項目中的一組容器的生命周期進行便攜管理。
下面是具體例子說明
Dockerfile
version: "2.0"
services:
ubuntu:
image: ubuntu:16.04
restart: always
ports:
- "1234:1234"
nodejs:
image: mynodeapp
restart: always
ports:
- "3000:3000"
nginx:
image: nginx
restart: always
ports:
- "8080:80"
redis:
image: redis:latest
restart: always
ports:
- "6379:6379"
mysql:
image: mysql:5.7
restart: always
ports:
- "27017:27017"
由于其中mysql與redis沒有進行詳細配置,因此并不能完全工作,只是作為展示用,其中image代表著基本哪些基本鏡像。可以將image
替換為build
,build
相關鏡像,然后基于這個鏡像。每一個容器必須定一個image或者build。
以下為命令上訴例子命令解釋,更多命令參照官方文檔
---ports: 暴露端口信息,使用宿主端口:容器端口 (HOST:CONTAINER)
格式,或者僅僅指定容器的端口(宿主將會隨機 選擇端口)都可以
(當使用 HOST:CONTAINER
格式來映射端口時,如果你使用的容器端口小于 60 并且沒放 到引號里,可能會得到錯誤結果,因為 YAML 會自動解析 xx:yy 這種數字格式為 60 進制。 為避免出現這種問題,建議數字串都采用引號包括起來的字符串格式)
---volumes: 對于此命令,在上述例子中沒有,但是對于容器之間共享數據是不可獲取的,數據卷所掛載路徑設置。可以設置宿主機路徑 ( HOST:CONTAINER )
或加上訪問模式 ( HOST:CONTAINER:ro )
。volumes 關鍵字相當于 docker run
的-v
參數,用于配置數據卷。這里與之前的做法一 樣,將 app 目錄通過綁定掛載的方式掛載到容器,以便讓我們能夠從主機修
運行docker-compose
項目的時候使用如下命令
docker-compose up
Docker-compose的大致工作流程如下
---up: 啟動所有在 Compose 文件中定義的容器,并且把它們的日志信息匯集一起。通常會使 用 -d 參數使 Compose 在后臺運行
---build: 重新建造由 Dockerfile 構建的鏡像。除非鏡像不存在,否則 up 命令不會執行構建的動作,因此需要更新鏡像時便使用這個命令
---ps: 獲取由 Compose 管理的容器的狀態信息
---run: 啟動一個容器,并運行一個一次性的命令。被連接的容器會同時啟動,除非用了 --no- deps 參數
---logs: 匯集由 Compose 管理的容器的日志,并以彩色輸出
---stop: 停止容器,但不會刪除它們
結語
首先如果要定制自己的鏡像,首先流程想清楚--->Dockerfile腳本編寫--->在iterm中運行docker build -t <name> .
--->運行docker run -d -p 3000:3000 <name>
---->打開瀏覽器輸入localhost:3000即可
上述僅僅是示例流程,對于單個image而言。
如果是采用docker-compose方式
相關本地鏡像的構建,采用單個dockerfile然后build方式---->相關需求梳理,比如redis,mysql等---->編寫docker-compose腳本,確定各個容器依賴關系---->docker-compose up運行----->瀏覽器打開相應端口