docker进阶
官網(wǎng):https://docs.docker.com/engine/reference/builder/
Docker的CMD 和 ENTRYPOINT
? CMD 和 ENTRYPOINT 指令都是用來(lái)指定容器啟動(dòng)時(shí)運(yùn)行的命令。大多數(shù)情況下基本功能相同。
exec 模式和 shell 模式
? CMD 和 ENTRYPOINT 指令都支持 exec 模式和 shell 模式的寫(xiě)法,所以要理解 CMD 和 ENTRYPOINT 指令的用法,就得先區(qū)分 exec 模式和 shell 模式。這兩種模式主要用來(lái)指定容器中的不同進(jìn)程為 1 號(hào)進(jìn)程。
exec 模式
? 使用 exec 模式時(shí),容器中的任務(wù)進(jìn)程就是容器內(nèi)的 1 號(hào)進(jìn)程
? exec 模式是建議的使用模式,因?yàn)楫?dāng)運(yùn)行任務(wù)的進(jìn)程作為容器中的 1 號(hào)進(jìn)程時(shí),我們可以通過(guò) docker 的 stop 命令優(yōu)雅的結(jié)束容器。
? exec 模式的特點(diǎn)是不會(huì)通過(guò) shell 執(zhí)行相關(guān)的命令,所以像 $HOME 這樣的環(huán)境變量是取不到的:
CMD [ "echo", "$HOME" ]? 通過(guò) exec 模式執(zhí)行 shell 可以獲得環(huán)境變量:
CMD [ "sh", "-c", "echo $HOME" ]shell 模式
使用 shell 模式時(shí),docker 會(huì)以 /bin/sh -c “task command” 的方式執(zhí)行任務(wù)命令。也就是說(shuō)容器中的 1 號(hào)進(jìn)程不是任務(wù)進(jìn)程而是 bash 進(jìn)程
CMD top1 號(hào)進(jìn)程執(zhí)行的命令居然是 /bin/sh -c top。而指定的 top 命令的進(jìn)程 ID 為 7。這是由 docker 內(nèi)部決定的,目的是讓我們執(zhí)行的命令或者腳本可以取到環(huán)境變量。
CMD 指令
CMD 指令的目的是:為容器提供默認(rèn)的執(zhí)行命令。
CMD 指令有三種使用方式,其中的一種是為 ENTRYPOINT 提供默認(rèn)的參數(shù):
另外兩種使用方式分別是 exec 模式和 shell 模式:
CMD ["executable","param1","param2"] # 這是 exec 模式的寫(xiě)法,注意需要使用雙引號(hào)。 CMD command param1 param2 # 這是 shell 模式的寫(xiě)法。注意命令行參數(shù)(即通過(guò)docker run 指定的)可以覆蓋 CMD 指令的設(shè)置,但是只能是重寫(xiě),卻不能給 CMD 中的命令通過(guò)命令行傳遞參數(shù)。實(shí)際上,命令行上的命令同樣會(huì)覆蓋 shell 模式的 CMD 指令。
ENTRYPOINT 指令
ENTRYPOINT 指令的目的也是為容器指定默認(rèn)執(zhí)行的任務(wù)。
ENTRYPOINT 指令有兩種使用方式,就是我們前面介紹的 exec 模式和 shell 模式:
exec 模式和 shell 模式的基本用法和 CMD 指令是一樣的。
指定 ENTRYPOINT 指令為 exec 模式時(shí),命令行(docker run)上指定的參數(shù)會(huì)作為參數(shù)添加到 ENTRYPOINT 指定命令的參數(shù)列表中。所以寫(xiě)entrypoint文件時(shí),要考慮輸入各種參數(shù)問(wèn)題。
覆蓋默認(rèn)的 ENTRYPOINT 指令
ENTRYPOINT 指令也是可以被命令行覆蓋的,只不過(guò)不是默認(rèn)的命令行參數(shù),而是需要顯式的指定 --entrypoint 參數(shù)。
docker run --rm --entrypoint commandDockerfile 中至少要有一個(gè)
如果鏡像中既沒(méi)有指定 CMD 也沒(méi)有指定 ENTRYPOINT 那么在啟動(dòng)容器時(shí)會(huì)報(bào)錯(cuò)。這不算是什么問(wèn)題,因?yàn)楝F(xiàn)在能見(jiàn)到的絕大多數(shù)鏡像都默認(rèn)添加了 CMD 或 ENTRYPOINT 指令。
同時(shí)使用 CMD 和 ENTRYPOINT 的情況
對(duì)于 CMD 和 ENTRYPOINT 的設(shè)計(jì)而言,多數(shù)情況下它們應(yīng)該是單獨(dú)使用的。當(dāng)然,有一個(gè)例外是 CMD 為 ENTRYPOINT 提供默認(rèn)的可選參數(shù)。
大概可以總結(jié)出下面幾條規(guī)律:
? 如果 ENTRYPOINT 使用了 shell 模式,CMD 指令會(huì)被忽略。
? 如果 ENTRYPOINT 使用了 exec 模式,CMD 指定的內(nèi)容被追加為 ENTRYPOINT 指定命令的參數(shù)。
? 如果 ENTRYPOINT 使用了 exec 模式,CMD 也應(yīng)該使用 exec 模式。
CMD和ENTRYPOINT差異:
| No CMD | error, not allowed | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry |
| CMD [“exec_cmd”, “p1_cmd”] | exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry exec_cmd p1_cmd |
| CMD [“p1_cmd”, “p2_cmd”] | p1_cmd p2_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry p1_cmd p2_cmd |
| CMD exec_cmd p1_cmd | /bin/sh -c exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd |
entrypoint入口文件詳解
#!/bin/bash set -eo pipefail shopt -s nullglob# if command starts with an option, prepend mysqld if [ "${1:0:1}" = '-' ]; thenset -- mysqld "$@" fi- set -e
bash如果任何語(yǔ)句的執(zhí)行結(jié)果不是true則應(yīng)該退出 。 set -o errexit 等同
- set -o pipefail
管道執(zhí)行過(guò)程中出現(xiàn)錯(cuò)誤立即退出
- shopt -s nullglob
在使用 Linux 中的通配符時(shí) * ?等 如果沒(méi)有匹配到任何文件, 不會(huì)報(bào) No such file or directory 而是將命令后面的參數(shù)去掉執(zhí)行
- set –
set --會(huì)將他后面所有以空格區(qū)分的字符串, 按順序分別存儲(chǔ)到$1, $2, $3 變量中
- exec "$@"
執(zhí)行了你沒(méi)有預(yù)料到的可執(zhí)行命令時(shí), 將會(huì)走到腳本的這最后一行, 去執(zhí)行用戶新的可執(zhí)行命令
ADD和COPY的區(qū)別
ADD
ADD指令的功能是將主機(jī)構(gòu)建環(huán)境(上下文)目錄中的文件和目錄、以及一個(gè)URL標(biāo)記的文件 拷貝到鏡像中。
其格式是: ADD 源路徑 目標(biāo)路徑1、如果源路徑是個(gè)文件,且目標(biāo)路徑是以 / 結(jié)尾, 則docker會(huì)把目標(biāo)路徑當(dāng)作一個(gè)目錄,會(huì)把源文件拷貝到該目錄下。如果目標(biāo)路徑不存在,則會(huì)自動(dòng)創(chuàng)建目標(biāo)路徑。
2、如果源路徑是個(gè)文件,且目標(biāo)路徑是不是以 / 結(jié)尾,則docker會(huì)把目標(biāo)路徑當(dāng)作一個(gè)文件。
如果目標(biāo)路徑不存在,會(huì)以目標(biāo)路徑為名創(chuàng)建一個(gè)文件,內(nèi)容同源文件;
如果目標(biāo)文件是個(gè)存在的文件,會(huì)用源文件覆蓋它,當(dāng)然只是內(nèi)容覆蓋,文件名還是目標(biāo)文件名。
如果目標(biāo)文件實(shí)際是個(gè)存在的目錄,則會(huì)源文件拷貝到該目錄下。 注意,這種情況下,最好顯示的以 / 結(jié)尾,以避免混淆。
3、如果源路徑是個(gè)目錄,且目標(biāo)路徑不存在,則docker會(huì)自動(dòng)以目標(biāo)路徑創(chuàng)建一個(gè)目錄,把源路徑目錄下的文件拷貝進(jìn)來(lái) ( 如果有子目錄,不會(huì)拷貝子目錄,僅拷貝子目錄下的文件,不分層級(jí))。如果目標(biāo)路徑是個(gè)已經(jīng)存在的目錄,則docker會(huì)把源路徑目錄下的文件拷貝到該目錄下。
4、如果源文件是個(gè)歸檔文件(壓縮文件),則docker會(huì)自動(dòng)幫解壓。
5、如果源路徑是url,則會(huì)下載文件到目標(biāo)。
COPY
COPY是ADD的簡(jiǎn)化版本,只是拷貝文件到指定位置。
COPY/ADD 復(fù)制文件夾的詭異行為
1、使用 * 作為 COPY/ADD 命令的源時(shí)候表示的是 ./*
2、cp 命令在執(zhí)行 cp * target 時(shí)會(huì)把文件夾當(dāng)成文件一股腦的復(fù)制到目標(biāo)路徑下,可以認(rèn)為復(fù)制了文件本身,而 docker 的 COPY/ADD 在復(fù)制文件夾時(shí)復(fù)制的是其內(nèi)容。
3、如果要遞歸拷貝目錄(包含子目錄),不要帶*
COPY ./scripts/ /workspace/scripts/這樣scripts下的目錄遞歸拷貝到目標(biāo)目錄下。
.dockerignore
忽略在構(gòu)造docker鏡像文件時(shí),不發(fā)送給 docker daemon 的文件。用于減少傳送量。
Docker 維護(hù)
yum install docker vi /etc/docker/daemon.json{"insecure-registries": ["192.168.1.XX"],"registry-mirrors": ["http://hub-mirror.c.163.com"] } systemctl start docker systemctl stop docker systemctl restart docker systemctl status docker systemctl enable dockerDocker問(wèn)題
掛載宿主機(jī)已存在目錄后,在容器內(nèi)對(duì)其進(jìn)行操作,報(bào)“Permission denied”。
可通過(guò)兩種方式解決:
1> 關(guān)閉selinux。
臨時(shí)關(guān)閉:# setenforce 0
永久關(guān)閉:修改/etc/sysconfig/selinux文件,將SELINUX的值設(shè)置為disabled。
2> 以特權(quán)方式啟動(dòng)容器
指定–privileged參數(shù)
如:# docker run -it --privileged=true -v /test:/soft centos /bin/bash
network被占用
提示1:service endpoint with name xxx already exists
docker network list docker network inspect xxx docker network disconnect --force XXX-network api-gateway總結(jié)
- 上一篇: Scala语言整理(一)
- 下一篇: webflux系列--reactor功能