在建置映像檔時,都可以注意到到其中一段紀錄:
=> [internal] load .dockerignore
每一次建置的過程中,其都會自動去讀取 .dockerignore 這個檔案,但在之前我們並沒有好好的介紹過。
其最主要的功能在於提前篩選掉不需要進入建置階段的檔案,例如常見的 README.md
或是一些開發環境的設定檔,對於建置階段以及運行容器沒有幫助的檔案,都應該放入 .dockerignore 內。
下面舉個簡單的例子,這是資料夾目前的結構。
.
├── main.js
├── Dockerfile
├── .dockerignore
├── README.md
接著在 .dockerignore 內寫入:
./README.md
./Dockerfile
接著來建置映像檔,這邊是 Dockerfile 的內容:
FROM alpine:latest
WORKDIR /app
COPY . .
CMD ["ls"]
接著一樣,建置這個映像檔:
$ docker image build --tag ignore .
+] Building 2.1s (8/8) FINISHED
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 94B 0.0s
=> [internal] load .dockerignore 0.1s
=> => transferring context: 34B 0.0s
=> [internal] load metadata for docker.io/library/alpine:latest 1.5s
=> CACHED [1/3] FROM docker.io/library/alpine:late.. 0.0s
=> [internal] load build context 0.1s
=> => transferring context: 58B 0.0s
=> [2/3] WORKDIR /app 0.1s
=> [3/3] COPY . . 0.1s
=> exporting to image 0.3s
=> => exporting layers 0.3s
=> => writing image sha256:ac7715c782f9dfcdd93c0dbc871ada.......... 0.0s
=> => naming to docker.io/library/ignore 0.0s
運行成容器看看輸出的結果是什麼?
$ docker container run ignore
main.js
可以注意到,我們使用了 COPY . .
的方式,也就是複製當前目錄內的所有資料進入到建置階段,但卻只有 main.js 被留下了,而 Dockerfile
以及 README.md
則都被篩選掉了。
這麼做的好處在哪呢?練習時,我們都可以直接 COPY 我們需要的檔案進入建置階段就好。
但在大型的框架之下,會有很多不必要進入建置階段的檔案,例如:測試的檔案、開發環境快取的檔案都不需要進入正式環境的映像檔,而這時候靠著一個一個去 COPY 則太過浪費時間。
所以使用 .dockerignore
則可以讓你放心的去使用 COPY . .
來達到 Dockerfile 撰寫的乾淨度、減少映像檔的容量,讓你透過一個檔案去管理所有不需要進入建置階段的檔案,是之後非常常用到的功能。
在經過了 28 天的鐵人賽,想必大家的電腦裡面應該都是充斥一些不需要的檔案,這時候可以先透過以下指令來查看目前各個 Docker 物件所佔據的容量:
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 63 0 13.25GB 13.25GB (100%)
Containers 0 0 0B 0B
Local Volumes 22 0 667.8MB 667.8MB (100%)
Build Cache 531 0 10.32GB 10.32GB
可以看到其實映像檔及快取就佔據了本機將近 25 GB 的空間,當然對於現代的硬碟大小,確實不算什麼,但有時候總會覺得這些是我現在有在使用的快取嗎?還是之前實驗的映像檔呢?
清理不需要的容器
這時候有幾個方式可以清除,除了前面很常使用,關於強制刪除所有容器的指令 ( 要記得這個是連在運行的容器都會刪除,通常都是我在實驗某些容器時才會使用的指令 )
$ docker container rm --force $(docker container ls -aq)
其實還有稍微文明一點的指令,可以不使用到 --force
這個選項便刪除停止運行的容器。
$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B
清理不需要的映像檔
關於清理映像檔的指令則和清理容器的雷同:
$ docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Deleted Images:
deleted: sha256:03552d52bd99ade4....
Total reclaimed space: 0B
其有提到只會刪除 dangling 的映像檔,而 dangling 則意味著標籤被奪走的映像檔。
以下示範什麼行為會製造出 dangling 的映像檔,這邊隨手建立一個 Dockerfile。
FROM alpine:latest
CMD [ "echo", "Hi" ]
接著建置映像檔:
$ docker image build --tag dangling .
[+] Building 0.2s (5/5) FINISHED
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 36B 0.1s
=> [internal] load .dockerignore 0.1s
=> => transferring context: 34B 0.0s
=> [internal] load metadata for docker.io/library/alpine:latest 0.0s
=> CACHED [1/1] FROM docker.io/library/alpine:latest 0.0s
=> exporting to image 0.3s
=> => exporting layers 0.3s
=> => writing image sha256:d7bcae79c0f6fff9fa7620078c122b6a65...... 0.0s
=> => naming to docker.io/library/dangling 0.0s
這時候我們列出映像檔,應該會看到剛剛建立好的映像檔。
$ docker image list
REPOSITORY TAG IMAGE ID CREATED SIZE
dangling latest d7bcae79c0f6 1 minutes ago 5.53MB
接著稍微的修改一下剛剛撰寫的 Dockerfile。
FROM alpine:latest
CMD [ "echo", "Hi, My name is Robert!" ]
在使用相同的標籤名字去建置映像檔。
$ docker image build --tag dangling .
[+] Building 0.2s (5/5) FINISHED
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 36B 0.1s
=> [internal] load .dockerignore 0.1s
=> => transferring context: 34B 0.0s
=> [internal] load metadata for docker.io/library/alpine:latest 0.0s
=> CACHED [1/1] FROM docker.io/library/alpine:latest 0.0s
=> exporting to image 0.3s
=> => exporting layers 0.3s
=> => writing image sha256:2892a0f830e770814c111d1f0fe1e66d66db2... 0.0s
=> => naming to docker.io/library/dangling 0.0s
在列出映像檔,就會看到 dangling 的映像檔,以 <none>
的方式顯示。
$ docker image list
REPOSITORY TAG IMAGE ID CREATED SIZE
dangling latest 2892a0f830e7 1 minutes ago 5.53MB
<none> <none> d7bcae79c0f6 2 minutes ago 5.53MB
這裡的 <none>
就是第一份建置的映像檔,因為標籤相同的關係,被第二次建置的映像檔奪走了標籤,轉變成 dangling 的映像檔,而在使用 docker image prune
的指令時,就會幫助你清除這些沒有標籤的映像檔。
而還有更暴力可以清理映像檔的方式,也就是在後方加上 --all
的指令,此指令將會清除所有沒有運行成容器的映像檔,換句話說,如果現在沒有在運行任何容器或是暫停的容器,那映像檔就會全部清空的意思。
$ docker image prune --all
WARNING! This will remove all images without at least one container associated to them.
Are you sure you want to continue? [y/N] y
.......
Total reclaimed space: 5.691GB
可以看到這邊清了 5.691 GB 的空間出來。
結語
今天介紹了 .dockerignore
的作用以及清理本機浪費的資源,明天則會介紹一下 Volume 該如何使用!