- dokcer的基本組成
- 鏡像
相當于掛在了root文件系統的Linux。
- 容器
鏡像與容器的關系,就像是面向對象中的類和實體一樣。鏡像是靜態定義的,容器是鏡像運行時的實體。容器可以被創建、啟動、停止、刪除、暫停等操作。
容器的實質是進程。但是與直接宿主執行的進程不同,容器進程運行屬于自己的獨立的命名空間。
- 倉庫
Dockerfile的使用
Dockerfile是一個文本文件
- 如我們在某個目錄創建一個Dockerfile文件。
vi Dockerfile - Dockerfile最基本的格式如下:
FROM nginx
RUN echo "<h1>Hello world</h1>" /usr/share/nginx/html/index.html
- 指令說明
- FROM 指定鏡像 基礎鏡像是必須要指定的。作用就是在此鏡像的基礎上進行定制。在Dockerfile文件中,FROM是必備的命令,而且是第一條命令。
- eg
FROM centos
- 此外,除了選擇現有鏡像的基礎上,Docker還存在一個特殊的鏡像,名為scratch,這個鏡像是虛擬的概念,并不實際存在,他表示一個空白的鏡像
FROM scratch
...
- RUN 執行命令 ,它是用來執行命令行命令的,由于命令行強大的能力,RUN指令在定制鏡像時是最常用的命令之一。
- RUN命令后跟著的有兩種格式:
- 1、Shell格式:RUN <命令>
RUN echo "hello world"
-2、 exec格式:RUN ["可執行文件", "參數1", "參數2"],這更像是函數調用中的格式。
如果RUN執行了多條命令,則應該按照如下方式書寫,而不是每條命令都使用RUN執行一次。因為層數限制。
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
### 構建鏡像
- 首先創建一個Dockerfile 文件,vi Dockerfile,然后加入最簡單的命令:
FROM nginx
RUN echo "hello docker"
保存退出。
- 構建鏡像,在Dockerfile文件的當前目錄下執行
docker build -t nginx:v2 .
- 等待執行完畢
`說明:我們指定了鏡像名 -t nginx:v2`
- 最后,運行該容器
docker run -d -p 8085:80 nginx:v2
- 在瀏覽器中輸入localhost:8085即可看到輸出。
- 刪除鏡像
docker rmi -f 鏡像名
- docker build構建命令的格式為:
docker build [選項] <上下文路徑/URL/>
### 構建上下文路徑
- docker build命令最后面有個 . ,表示當前路徑,在當前路徑中尋找Dockerfile文件。
> 這就引入了上下文的概念。當構建的時候,用戶會指定構建鏡像上下文的路徑,docker build 命令得知這個路徑后,會將路徑下的所有內容打包,然后上傳給 Docker 引擎。這樣 Docker 引擎收到這個上下文包后,展開就會獲得構建鏡像所需的一切文件。
- 關于上下文
> 如果在 Dockerfile 中這么寫:
```COPY ./package.json /app/```
這并不是要復制執行 docker build 命令所在的目錄下的 package.json,也不是復制 Dockerfile 所在目錄下的 package.json,而是復制 上下文(context) 目錄下的 package.json。
因此,COPY 這類指令中的源文件的路徑都是相對路徑。這也是初學者經常會問的為什么 COPY ../package.json /app 或者 COPY /opt/xxxx /app 無法工作的原因,因為這些路徑已經超出了上下文的范圍,Docker 引擎無法獲得這些位置的文件。如果真的需要那些文件,應該將它們復制到上下文目錄中去。
現在就可以理解剛才的命令 docker build -t nginx:v3 . 中的這個 .,實際上是在指定上下文的目錄,docker build 命令會將該目錄下的內容打包交給 Docker 引擎以幫助構建鏡像。
如果觀察 docker build 輸出,我們其實已經看到了這個發送上下文的過程:
$ docker build -t nginx:v3 .
Sending build context to Docker daemon 2.048 kB
...
理解構建上下文對于鏡像構建是很重要的,避免犯一些不應該的錯誤。比如有些初學者在發現 COPY /opt/xxxx /app 不工作后,于是干脆將 Dockerfile 放到了硬盤根目錄去構建,結果發現 docker build 執行后,在發送一個幾十 GB 的東西,極為緩慢而且很容易構建失敗。那是因為這種做法是在讓 docker build 打包整個硬盤,這顯然是使用錯誤。
一般來說,應該會將 Dockerfile 置于一個空目錄下,或者項目根目錄下。如果該目錄下沒有所需文件,那么應該把所需文件復制一份過來。如果目錄下有些東西確實不希望構建時傳給 Docker 引擎,那么可以用 .gitignore 一樣的語法寫一個 .dockerignore,該文件是用于剔除不需要作為上下文傳遞給 Docker 引擎的。
那么為什么會有人誤以為 . 是指定 Dockerfile 所在目錄呢?這是因為在默認情況下,如果不額外指定 Dockerfile 的話,會將上下文目錄下的名為 Dockerfile 的文件作為 Dockerfile。
這只是默認行為,實際上 Dockerfile 的文件名并不要求必須為 Dockerfile,而且并不要求必須位于上下文目錄中,比如可以用 -f ../Dockerfile.php 參數指定某個文件作為 Dockerfile。
當然,一般大家習慣性的會使用默認的文件名 Dockerfile,以及會將其置于鏡像構建上下文目錄中。