-
Dockerfile 中
COPY
指令和ADD
指令有什麼區別簡單來說,最主要的區別是
ADD
功能更為強大一些:ADD
允許<src>
是一個 URL- 如果
ADD
的<src>
引數是可以識別的壓縮格式存檔檔案,則對其進行解壓如果 ADD 帶一個 URL 是 xxx.tar.gz 的檔案的話,是不會對其進行解壓的
「書寫 Dockerfiles 的最佳實踐」推薦使用
COPY
指令而不是使用ADD
指令. -
Dockerfile 中
CMD
指令和ENTRYPOINT
指令有什麼區別Docker 有一個預設的「入口點」
/bin/sh -c
,但沒有一個預設的命令.這裡論述,感覺不對,主要看 Dockerfile 中的
CMD
和ENTRYPOINT
是基於 exec 還是 shell 模式
若是 shell 模式則是利用 /bin/sh -c 調起命令執行的,exec 模式則是直接執行命令當你這樣執行
docker
的時候:docker run -i -t ubuntu bash
,「入口點」就是預設的/bin/sh -c
,映象是ubuntu
,命令是bash
.
該命令是透過「入口點」執行的,實際上執行的是/bin/sh -c bash
. 這允許 Docker 依靠shell
的解析器快速實現RUN
.
後來,使用者要求能夠自定義它,因此引入了ENTRYPOINT
和--entrypoint
.在上面的示例中,
ubuntu
之後的內容都是命令並且傳遞給了「入口點」.
當使用CMD
指令的時候,實際上就跟docker run -i -t ubuntu <cmd>
一樣,<cmd>
就是「入口點」的引數.
你仍然會在容器中啟動一個 bash shell 是因為ubuntu
的Dockerfile
指定了一個預設的CMD
:CMD ["bash"]
因為所有內容都會傳遞到「入口點」,所以你可以從「映象」獲取到非常好的行為.
例如,把「映象」用作「二進位制」命令.
當把["/bin/cat"]
作為「入口點」並執行docker run img /etc/passwd
的時候,你將會得到,
由於/etc/passwd
是命令並傳遞給「入口點」,因此最終執行的只是/bin/cat /etc/passwd
.另外一個例子是將任何
cli
作為「入口點」.
假設有一個redis
映象,不用執行docker run redisimg redis -H something -u toto get key
,而是簡單定義ENTRYPOINT ["reids", "-H", "something", "-u", "toto"]
,然後執行類似這樣的命令將會得到相同的結果:docker run redisimg get key
. -
從主機複製檔案到 Docker 容器
cp
命令能夠用來複制檔案. 可以複製一個特定的檔案,如docker cp foo.txt mycontainer:/foo.txt docker cp mycontainer:/foo.txt foo.txt
特別強調,
mycontainer
是「容器」ID 而不是「映象」ID.資料夾
src
包含多個檔案可以使用以下方法複製到target
資料夾中docker cp src/. mycontainer:/target docker cp mycontainer:/src/. target
小於 Docker 1.8 的版本,只能將檔案從容器複製到主機,而不能從主機複製到容器.
-
如何移除舊的 Docker 容器
使用
docker container prune
.也可以使用
docker system prune
, 將會在一個命令中移除「容器」(containers),「映象」(images),「卷」(volumes)以及「網路」(networks). -
如何從主機獲取 Docker 容器的 IP 地址
inspect
的--format
選項可以獲取到.
現代 Docker 客戶端語法docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name_or_id
古代 Docker 客戶端語法
docker inspect --format '{{ .NetworkSettings.IPAddress }}' container_name_or_id
若是 windows 系統,則需要雙引號(“)而不是單引號(‘)
-
在不使用倉庫的情況下,如何將 Docker 映象從一臺主機複製到另一臺
首先,把映象儲存為一個
tar
檔案.docker save -o < path for generated tar file > < image name >
然後使用常規檔案傳輸工具(如
cp
或scp
)將映象複製到系統.
之後再將映象匯入到 Docker 中.docker load -i < path to image tar file >
-
如何處理 Docker 中的持久儲存(例如:資料庫)
使用 volume API
docker volume create --name hello docker run -d -v hello:/container/path/for/volume container_image my_command
這意味著必須放棄僅資料容器模式以支援新卷.
實際上
volume API
只是實現資料容器模式的更好的方法.如果使用
-v volume_name:/container/fs/path
建立容器,Docker 將自動為你建立一個命名卷,它可以- 透過
docker volume ls
列出來 - 透過
docker volume inspect volume_name
識別 - 備份為普通目錄
- 像以前一樣透過
--volumes-from
連線備份
新的
volume API
增加了一個有用的命令,能夠讓你識別出懸空的卷docker volume ls -f dangling=true
然後可以透過卷名移除
docker volume rm < volume name >
可以只透過一條命令移除所有懸空的卷
docker volume rm $(docker volume ls -f dangling=true -q) # Or using 1.13.x docker volume prune
- 透過
-
如何在 Docker 中列出容器
只顯示正在執行的「容器」
docker ps
顯示所有的「容器」
docker ps -a
顯示最新建立的「容器」(包括所有狀態)
docker ps -l
顯示 N 個最新建立的「容器」(包括所有狀態)
docker ps -n=-1
顯示總的檔案大小
docker ps -s
在新版本的 Docker, 命令有更新,新增了一些管理命令
列出正在執行的「容器」
docker container ls
列出所有的容器(不管狀態)
docker container ls -a
-
如何刪除 Docker 中的映象
使用
docker rmi node
列出所有建立的「容器」
docker ps -a
移除所有現有的「容器」(不是「映象」),執行
docker rm $(docker ps -aq)
-
如何進入 Docker 容器的 shell
使用
docker exec
, 例如docker exec -it < mycontainer > bash
-
Docker 映象儲存在主機那個位置
/var/lib/docker
目錄的內容主要依賴於 driver Docker is using for storage預設是
aufs
,但也可以為overlay
,overlay2
,btrfs
,devicemapper
或者zfs
,主要是取決於你的「核心」支援.
大多數情況下都會是aufs
,但是RedHats
的是devicemapper
.可以使用
-s
或者--storage-dirver=
選項為Docker daemon
手動設定儲存的驅動./var/lib/docker/{dirver-name}
包含了指定儲存驅動的映象內容/var/lib/docker/graph/{id}
僅包含映象的後設資料,儲存在json
和layersize
檔案
若是
aufs
/var/lib/docker/aufs/diff/{id}
包含了映象檔案內容/var/lib/docker/repositories-aufs
是一個JSON
檔案,包含了本地映象資訊. 可以使用docker images
命令檢視
若是
devicemapper
/var/lib/docker/devicemapper/devicemapper/data
儲存了映象/var/lib/docker/devicemapper/devicemapper/metadata
儲存了後設資料這些檔案是精簡配置的’稀疏‘檔案,因此不像它們看起來那麼大
-
Docker 容器和映象的區別
「映象」的執行例項被稱作「容器」.
一個「映象」,實質是一組
layer
層的描述. 當你啟動此「映象」,則會有一個執行此「映象」的「容器」. 可以建立許多同一個「映象」的執行「容器」.docker images
可以檢視所有的「映象」, 而docker ps
可以檢視所有執行中的「容器」,docker ps -a
檢視所有的「容器」.因此,「映象」的執行例項就是「容器」.
-
如何移除舊的不用的 Docker 映象
docker system prune
會刪除所有的懸空資料(例如:停止執行的「容器」,沒有「容器」的「卷」,沒有「容器」的「映象」),甚至不使用的資料,使用-a
選項.還可以使用:
- docker container prune
- docker image prune
- docker network prune
- docker volume prune
對於不使用的「映象」,使用
docker image prune -a
(刪除懸空和不使用的「映象」).不使用的「映象」是指未被任何「容器」引用
把
--filter
選項與docker xxx prune
組合使用,是一種限制prune
的好方法. -
如何將環境變數傳遞給 Docker 容器
使用
-e
選項.sudo docker run -d -t -i -e REDIS_NAMESPACE='staging' \ -e POSTGRES_ENV_POSTGRES_PASSWORD='foo' \ -e POSTGRES_ENV_POSTGRES_USER='bar' \ -e POSTGRES_ENV_DB_NAME='mysite_staging' \ -e POSTGRES_PORT_5432_TCP_ADDR='docker-db-1.hidden.us-east-1.rds.amazonaws.com' \ -e SITE_URL='staging.mysite.com' \ -p 80:80 \ --link redis:redis \ --name container_name dockerhub_id/image_name
或者,不想在
ps
命令列看到這樣賦值的引數,則可以這樣sudo PASSWORD='foo' docker run [...] -e PASSWORD [...]
如果有很多環境變數特別是它們出於安全考慮不能暴露的話,可以使用
env-file
.$ docker run --env-file ./env.list ubuntu bash
env.list
檔案每一行要符合VAR=VAL
這樣的格式 -
強制 Docker 不使用快取構建映象
使用
--no-cache
選項.docker build --no-cache -t u12_core .
-
Docker 如何修改倉庫名或者映象名
docker tag server:latest myname/server:latest
或者
docker tag d583c3ac45fd myname/server:latest
如果不要舊的名字,在重新標記之後可以移除它
docker rmi server
這僅僅移除
alias/tag
. 因為d583c3ac45fd
有其他名字,真實的「映象」不會被移除. -
在 Docker 中 expose 和 publish 有什麼不同
expose
是一種文件化的方式,與Dockerfile
相關.expose 只是定義了那些埠被使用,是一種文件化定義,實際上不進行埠對映或開啟埠的操作
--publish
(-p
) 是一種將主機埠對映到正在執行的容器埠的方法,與docker run
相關.-p 會告訴容器在網路介面開啟那些埠
-
如何 attach 和 detach Docker 程式
使用
CTRL-c
detach
「容器」,會導致 Docker 「容器」退出.使用
--sig-proxy
選項,可以避免「容器」退出.docker attach --sig-proxy=false 304f5db405ec
使用
CTRL-p CTRL-q
也可以detach
而「容器」不退出, 不過只有在「容器」是使用-t
和-i
選項啟動的時候,才會生效.$ docker run -i -t -d nginx af203c3e997b94c7a519463c26c9290c777942556be4682738a8892af1f7062b $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES af203c3e997b nginx "nginx -g 'daemon of…" 3 seconds ago Up 2 seconds 80/tcp keen_lumiere $ docker attach keen_lumiere read escape sequence # 這裡使用 CTRL-p CTRL-q detach 「容器」 $ docker ps # 「容器」沒有退出 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES af203c3e997b nginx "nginx -g 'daemon of…" 20 seconds ago Up 19 seconds 80/tcp keen_lumiere
也可以自定義
detach
鍵:--detach-keys
詳情參考:set your own detach sequence -
Docker daemon 日誌的位置
這主要取決於你的系統,以下是幾個位置以及包含幾個作業系統的命令.
- Ubuntu(使用
upstart
) -/var/log/upstart/docker.log
- Ubuntu(使用
systemd
) -journalctl -fu docker.service
- Amazon Linux AMI -
/var/log/docker
- Boot2Docker -
/var/log/docker.log
- Debian GNU/Linux -
/var/log/daemon.log
- CentOS -
/var/log/daemon.log | grep docker
- CoreOS -
journalctl -u docker.service
- Fedora -
journalctl -u docker.service
- Red Hat Enterprise Linux Server -
/var/log/messages | grep docker
- OpenSuSE -
journalctl -u docker.service
- Ubuntu(使用
-
Dockerfile 中如何更新 PATH 環境變數
ENV PATH="/opt/gtk/bin:${PATH}"
-
如何檢查
docker build
失敗的檔案系統Docker
每次從Dockerfile
成功執行一個RUN
指令,都會提交一個新的layer
層到「映象」檔案系統.
你可以方便地使用這些layer
層 ID 作為一個「映象」啟動一個新的「容器」.使用這樣的
Dockerfile
FROM busybox RUN echo 'foo' > /tmp/foo.txt RUN echo 'bar' >> /tmp/foo.txt
構建一個「映象」
$ docker build -t so-2622957 . Sending build context to Docker daemon 47.62 kB Step 1/3 : FROM busybox ---> 00f017a8c2a6 Step 2/3 : RUN echo 'foo' > /tmp/foo.txt ---> Running in 4dbd01ebf27f ---> 044e1532c690 Removing intermediate container 4dbd01ebf27f Step 3/3 : RUN echo 'bar' >> /tmp/foo.txt ---> Running in 74d81cb9d2b1 ---> 5bd8172529c1 Removing intermediate container 74d81cb9d2b1 Successfully built 5bd8172529c1
你可以使用
00f017a8c2a6
,044e1532c690
和5bd8172529c1
啟動一個新的「容器」.$ docker run --rm 00f017a8c2a6 cat /tmp/foo.txt cat: /tmp/foo.txt: No such file or directory $ docker run --rm 044e1532c690 cat /tmp/foo.txt foo $ docker run --rm 5bd8172529c1 cat /tmp/foo.txt foo bar
當
Dockerfile
中的一個指令執行失敗時,你需要做的是查詢上一個layer
層的 ID, 並在從該 ID 建立的「容器」中執行shell
docker run --rm -it <id_last_working_layer> bash -il
一旦進入到「容器」
- 嘗試失敗的命令,重現該問題
- 然後修復該命令並測試它
- 最後使用修復之後的命令更新你的
Dockerfile
若是想直接在失敗的
layer
層排查問題而不是在最後一個工作的layer
層,則可以:
首先,找到失敗的「容器」$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6934ada98de6 42e0228751b3 "/bin/sh -c './utils/" 24 minutes ago Exited (1) About a minute ago sleepy_bell
然後,把它提交到一個「映象」
$ docker commit 6934ada98de6 sha256:7015687976a478e0e94b60fa496d319cdf4ec847bcd612aecf869a72336e6b83
之後,執行這個「映象」
$ docker run -it 7015687976a4 [bash -il]
這樣,就處於構建失敗時的狀態了.
說明
文章主要是參考了 StackOverflow docker
標籤的問題列表
本作品採用《CC 協議》,轉載必須註明作者和本文連結