列出docker鏡像
docker image ls
docker images
-
docker image ls -f dangling=true
(列出虛懸鏡像) docker image ls -a
docker image ls --format "{{.ID}}:{{.Repository}}"
docker image ls --digests
刪除docker鏡像
docker image rm
docker rmi
docker image rm $(docker image ls -q redis) 刪除所有 redis 鏡像
查看容器變化
docker diff <容器名>
docker commit
docker history
docker commmit [選項(xiàng)] <容器ID或容器名> [<倉庫名>[:<標(biāo)簽>]]
example :
docker commit \
--author "Tao Wang <twang2218@gmail.com>" \
--message "修改了默認(rèn)網(wǎng)頁" \
webserver \
nginx:v2
sha256:07e33465974800ce65751acc279adc6ed2dc5ed4e0838f8b86f0c87aa1795214
dockerfile
scratch鏡像
這個(gè)鏡像是虛擬的概念柳骄,并不實(shí)際存在耐薯,它表示一個(gè)空白的鏡像可柿。
FROM scratch
...
如果你以 scratch 為基礎(chǔ)鏡像的話复斥,意味著你不以任何鏡像為基礎(chǔ)目锭,接下來所寫的指令將作為鏡像第一層開始存在。
RUN 執(zhí)行命令
RUN 指令是用來執(zhí)行命令行命令的主儡。由于命令行的強(qiáng)大能力糜值,RUN 指令在定制鏡像時(shí)是最常用的指令之一寂汇。其格式有兩種:
shell 格式:RUN <命令>骄瓣,就像直接在命令行中輸入的命令一樣榕栏。剛才寫的 Dockerfile 中的 RUN 指令就是這種格式臼膏。
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
exec 格式:RUN ["可執(zhí)行文件", "參數(shù)1", "參數(shù)2"]渗磅,這更像是函數(shù)調(diào)用中的格式始鱼。
既然 RUN 就像 Shell 腳本一樣可以執(zhí)行命令医清,那么我們是否就可以像 Shell 腳本一樣把每個(gè)命令對(duì)應(yīng)一個(gè) RUN 呢会烙?比如這樣:
FROM debian:stretch
RUN apt-get update
RUN apt-get install -y gcc libc6-dev make wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.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
之前說過柏腻,Dockerfile 中每一個(gè)指令都會(huì)建立一層五嫂,RUN 也不例外沃缘。每一個(gè) RUN 的行為槐臀,就和剛才我們手工建立鏡像的過程一樣:新建立一層水慨,在其上執(zhí)行這些命令讥巡,執(zhí)行結(jié)束后掀亩,commit 這一層的修改舔哪,構(gòu)成新的鏡像欢顷。
而上面的這種寫法,創(chuàng)建了 7 層鏡像捉蚤。這是完全沒有意義的抬驴,而且很多運(yùn)行時(shí)不需要的東西,都被裝進(jìn)了鏡像里缆巧,比如編譯環(huán)境、更新的軟件包等等陕悬。結(jié)果就是產(chǎn)生非常臃腫题暖、非常多層的鏡像,不僅僅增加了構(gòu)建部署的時(shí)間捉超,也很容易出錯(cuò)胧卤。 這是很多初學(xué) Docker 的人常犯的一個(gè)錯(cuò)誤。
Union FS 是有最大層數(shù)限制的拼岳,比如 AUFS枝誊,曾經(jīng)是最大不得超過 42 層,現(xiàn)在是不得超過 127 層惜纸。
上面的 Dockerfile 正確的寫法應(yīng)該是這樣:
FROM debian:stretch
RUN buildDeps='gcc libc6-dev make wget' \
&& apt-get update \
&& apt-get install -y $buildDeps \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.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 支持 Shell 類的行尾添加 \ 的命令換行方式叶撒,以及行首 # 進(jìn)行注釋的格式。良好的格式耐版,比如換行祠够、縮進(jìn)、注釋等粪牲,會(huì)讓維護(hù)哪审、排障更為容易,這是一個(gè)比較好的習(xí)慣虑瀑。
dockerFile 定制鏡像
- dockerfile構(gòu)建
docker build [選項(xiàng)] <上下文路徑/URL/->
- git repo 構(gòu)建
這行命令指定了構(gòu)建所需的 Git repo湿滓,并且指定默認(rèn)的 master 分支滴须,構(gòu)建目錄為 /11.1/,然后 Docker 就會(huì)自己去 git clone 這個(gè)項(xiàng)目叽奥、切換到指定分支扔水、并進(jìn)入到指定目錄后開始構(gòu)建。
docker build https://github.com/twang2218/gitlab-ce-zh.git#:11.1
- tar包構(gòu)建
docker build http://server/context.tar.gz
如果所給出的 URL 不是個(gè) Git repo朝氓,而是個(gè) tar 壓縮包魔市,那么 Docker 引擎會(huì)下載這個(gè)包,并自動(dòng)解壓縮赵哲,以其作為上下文待德,開始構(gòu)建。
- 從標(biāo)準(zhǔn)輸入中讀取 Dockerfile 進(jìn)行構(gòu)建
docker build - < Dockerfile
或
cat Dockerfile | docker build -
如果標(biāo)準(zhǔn)輸入傳入的是文本文件枫夺,則將其視為 Dockerfile将宪,并開始構(gòu)建。這種形式由于直接從標(biāo)準(zhǔn)輸入中讀取 Dockerfile 的內(nèi)容橡庞,它沒有上下文较坛,因此不可以像其他方法那樣可以將本地文件 COPY 進(jìn)鏡像之類的事情。
- 從標(biāo)準(zhǔn)輸入中讀取上下文壓縮包進(jìn)行構(gòu)建
docker build - < context.tar.gz
如果發(fā)現(xiàn)標(biāo)準(zhǔn)輸入的文件格式是 gzip扒最、bzip2 以及 xz 的話丑勤,將會(huì)使其為上下文壓縮包,直接將其展開吧趣,將里面視為上下文法竞,并開始構(gòu)建。
Dockerfile 指令詳解
copy
COPY [--chown=<user>:<group>] <源路徑>... <目標(biāo)路徑>
COPY [--chown=<user>:<group>] ["<源路徑1>",... "<目標(biāo)路徑>"]
-
和
RUN
指令一樣强挫,也有兩種格式岔霸,一種類似于命令行,一種類似于函數(shù)調(diào)用纠拔。COPY
指令將從構(gòu)建上下文目錄中<源路徑>
的文件/目錄復(fù)制到新的一層的鏡像內(nèi)的<目標(biāo)路徑>
位置秉剑。比如:COPY package.json /usr/src/app/
<源路徑>
可以是多個(gè),甚至可以是通配符稠诲,其通配符規(guī)則要滿足 Go 的filepath.Match
規(guī)則侦鹏,如:COPY hom* /mydir/ COPY hom?.txt /mydir/
<目標(biāo)路徑>
可以是容器內(nèi)的絕對(duì)路徑,也可以是相對(duì)于工作目錄的相對(duì)路徑(工作目錄可以用WORKDIR
指令來指定)臀叙。目標(biāo)路徑不需要事先創(chuàng)建略水,如果目錄不存在會(huì)在復(fù)制文件前先行創(chuàng)建缺失目錄。此外劝萤,還需要注意一點(diǎn)渊涝,使用
COPY
指令,源文件的各種元數(shù)據(jù)都會(huì)保留。比如讀跨释、寫胸私、執(zhí)行權(quán)限、文件變更時(shí)間等鳖谈。這個(gè)特性對(duì)于鏡像定制很有用岁疼。特別是構(gòu)建相關(guān)文件都在使用 Git 進(jìn)行管理的時(shí)候。在使用該指令的時(shí)候還可以加上
--chown=<user>:<group>
選項(xiàng)來改變文件的所屬用戶及所屬組缆娃。COPY --chown=55:mygroup files* /mydir/ COPY --chown=bin files* /mydir/ COPY --chown=1 files* /mydir/ COPY --chown=10:11 files* /mydir/
ADD
比如 <源路徑>
可以是一個(gè) URL
捷绒,這種情況下,Docker 引擎會(huì)試圖去下載這個(gè)鏈接的文件放到 <目標(biāo)路徑>
去贯要。下載后的文件權(quán)限自動(dòng)設(shè)置為 600
暖侨,如果這并不是想要的權(quán)限,那么還需要增加額外的一層 RUN
進(jìn)行權(quán)限調(diào)整崇渗,另外字逗,如果下載的是個(gè)壓縮包,需要解壓縮显押,也一樣還需要額外的一層 RUN
指令進(jìn)行解壓縮扳肛。所以不如直接使用 RUN
指令傻挂,然后使用 wget
或者 curl
工具下載乘碑,處理權(quán)限、解壓縮金拒、然后清理無用文件更合理兽肤。因此,這個(gè)功能其實(shí)并不實(shí)用绪抛,而且不推薦使用资铡。
如果 <源路徑>
為一個(gè) tar
壓縮文件的話,壓縮格式為 gzip
, bzip2
以及 xz
的情況下幢码,ADD
指令將會(huì)自動(dòng)解壓縮這個(gè)壓縮文件到 <目標(biāo)路徑>
去笤休。
在使用該指令的時(shí)候還可以加上 --chown=<user>:<group>
選項(xiàng)來改變文件的所屬用戶及所屬組。
ADD --chown=55:mygroup files* /mydir/
ADD --chown=bin files* /mydir/
ADD --chown=1 files* /mydir/
ADD --chown=10:11 files* /mydir/
CMD
CMD
指令的格式和 RUN
相似症副,也是兩種格式:
-
shell
格式:CMD <命令>
-
exec
格式:CMD ["可執(zhí)行文件", "參數(shù)1", "參數(shù)2"...]
- 參數(shù)列表格式:
CMD ["參數(shù)1", "參數(shù)2"...]
店雅。在指定了ENTRYPOINT
指令后,用CMD
指定具體的參數(shù)贞铣。
之前介紹容器的時(shí)候曾經(jīng)說過闹啦,Docker 不是虛擬機(jī),容器就是進(jìn)程辕坝。既然是進(jìn)程窍奋,那么在啟動(dòng)容器的時(shí)候,需要指定所運(yùn)行的程序及參數(shù)。CMD
指令就是用于指定默認(rèn)的容器主進(jìn)程的啟動(dòng)命令的琳袄。
ENTRYPOINT
- //todo
ENV
ENV NODE_VERSION 7.2.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
&& grep " node-v$NODE_VERSION-linux-x64.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
&& tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components=1 \
&& rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs
在這里先定義了環(huán)境變量 NODE_VERSION
江场,其后的 RUN
這層里,多次使用 $NODE_VERSION
來進(jìn)行操作定制窖逗】富可以看到,將來升級(jí)鏡像構(gòu)建版本的時(shí)候滑负,只需要更新 7.2.0
即可在张,Dockerfile
構(gòu)建維護(hù)變得更輕松了。
下列指令可以支持環(huán)境變量展開: ADD
矮慕、COPY
帮匾、ENV
、EXPOSE
痴鳄、LABEL
瘟斜、USER
、WORKDIR
痪寻、VOLUME
螺句、STOPSIGNAL
、ONBUILD
橡类。
可以從這個(gè)指令列表里感覺到蛇尚,環(huán)境變量可以使用的地方很多,很強(qiáng)大顾画。通過環(huán)境變量取劫,我們可以讓一份 Dockerfile
制作更多的鏡像,只需使用不同的環(huán)境變量即可研侣。
ARG
//todo
VOLUME
格式為:
VOLUME ["<路徑1>", "<路徑2>"...]
VOLUME <路徑>
之前我們說過谱邪,容器運(yùn)行時(shí)應(yīng)該盡量保持容器存儲(chǔ)層不發(fā)生寫操作,對(duì)于數(shù)據(jù)庫類需要保存動(dòng)態(tài)數(shù)據(jù)的應(yīng)用庶诡,其數(shù)據(jù)庫文件應(yīng)該保存于卷(volume)中惦银,后面的章節(jié)我們會(huì)進(jìn)一步介紹 Docker 卷的概念。為了防止運(yùn)行時(shí)用戶忘記將動(dòng)態(tài)文件所保存目錄掛載為卷末誓,在 Dockerfile
中扯俱,我們可以事先指定某些目錄掛載為匿名卷,這樣在運(yùn)行時(shí)如果用戶不指定掛載基显,其應(yīng)用也可以正常運(yùn)行蘸吓,不會(huì)向容器存儲(chǔ)層寫入大量數(shù)據(jù)。
VOLUME /data
這里的 /data
目錄就會(huì)在運(yùn)行時(shí)自動(dòng)掛載為匿名卷撩幽,任何向 /data
中寫入的信息都不會(huì)記錄進(jìn)容器存儲(chǔ)層库继,從而保證了容器存儲(chǔ)層的無狀態(tài)化箩艺。當(dāng)然,運(yùn)行時(shí)可以覆蓋這個(gè)掛載設(shè)置宪萄。比如:
docker run -d -v mydata:/data xxxx
在這行命令中艺谆,就使用了 mydata
這個(gè)命名卷掛載到了 /data
這個(gè)位置,替代了 Dockerfile
中定義的匿名卷的掛載配置拜英。
EXPOSE
格式為 EXPOSE <端口1> [<端口2>...]
静汤。
EXPOSE
指令是聲明運(yùn)行時(shí)容器提供服務(wù)端口,這只是一個(gè)聲明居凶,在運(yùn)行時(shí)并不會(huì)因?yàn)檫@個(gè)聲明應(yīng)用就會(huì)開啟這個(gè)端口的服務(wù)虫给。在 Dockerfile 中寫入這樣的聲明有兩個(gè)好處,一個(gè)是幫助鏡像使用者理解這個(gè)鏡像服務(wù)的守護(hù)端口侠碧,以方便配置映射抹估;另一個(gè)用處則是在運(yùn)行時(shí)使用隨機(jī)端口映射時(shí),也就是 docker run -P
時(shí)弄兜,會(huì)自動(dòng)隨機(jī)映射 EXPOSE
的端口药蜻。
要將 EXPOSE
和在運(yùn)行時(shí)使用 -p <宿主端口>:<容器端口>
區(qū)分開來。-p
替饿,是映射宿主端口和容器端口语泽,換句話說,就是將容器的對(duì)應(yīng)端口服務(wù)公開給外界訪問视卢,而 EXPOSE
僅僅是聲明容器打算使用什么端口而已踱卵,并不會(huì)自動(dòng)在宿主進(jìn)行端口映射。
WORKDIR
格式為 WORKDIR <工作目錄路徑>
USER
又是一個(gè)搞不懂的命令
HEALRHCHECK
查看docker unhealthy 問題
docker inspect --format '{{json .State.Health}}' web
ONBUILD
//todo
操作容器
- Docker run
- Docker container start 啟動(dòng)已終止容器
- docker log
- -d 參數(shù)后臺(tái)運(yùn)行
- docker container ls
- Docker container logs [container ID or NAMES]
終止容器
- docker container stop
- docker container restart
進(jìn)入容器
attach命令
- docker attach
如果使用docker attach 啟動(dòng)的偽終端 exit腾夯,會(huì)導(dǎo)致容器的停止
exec命令
docker exec
后邊可以跟多個(gè)參數(shù)颊埃,這里主要說明 -i
-t
參數(shù)蔬充。
只用 -i
參數(shù)時(shí)蝶俱,由于沒有分配偽終端,界面沒有我們熟悉的 Linux 命令提示符饥漫,但命令執(zhí)行結(jié)果仍然可以返回榨呆。
當(dāng) -i
-t
參數(shù)一起使用時(shí),則可以看到我們熟悉的 Linux 命令提示符庸队。
- docker exec -it [id or name] bash
如果從這個(gè) stdin 中 exit积蜻,不會(huì)導(dǎo)致容器的停止。這就是為什么推薦大家使用 docker exec
的原因彻消。
導(dǎo)入和導(dǎo)出容器
導(dǎo)出容器
- docker export
docker export 7691a814370e > ubuntu.tar
倒入容器快照
$ cat ubuntu.tar | docker import - test/ubuntu:v1.0
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
test/ubuntu v1.0 9d37a6082e97 About a minute ago 171.3 MB
此外竿拆,也可以通過指定 URL 或者某個(gè)目錄來導(dǎo)入,例如
$ docker import http://example.com/exampleimage.tgz example/imagerepo
注:用戶既可以使用 docker load 來導(dǎo)入鏡像存儲(chǔ)文件到本地鏡像庫宾尚,也可以使用 docker import 來導(dǎo)入一個(gè)容器快照到本地鏡像庫丙笋。這兩者的區(qū)別在于容器快照文件將丟棄所有的歷史記錄和元數(shù)據(jù)信息(即僅保存容器當(dāng)時(shí)的快照狀態(tài))谢澈,而鏡像存儲(chǔ)文件將保存完整記錄,體積也要大御板。此外锥忿,從容器快照文件導(dǎo)入時(shí)可以重新指定標(biāo)簽等元數(shù)據(jù)信息。
刪除容器
- docker container rm
清除所有中止?fàn)顟B(tài)容器
- docker container prune
訪問倉庫
- docker login
- docker logout
- docker search
- docker pull
- docker push
自動(dòng)創(chuàng)建
自動(dòng)創(chuàng)建(Automated Builds)功能對(duì)于需要經(jīng)常升級(jí)鏡像內(nèi)程序來說怠肋,十分方便敬鬓。
有時(shí)候,用戶創(chuàng)建了鏡像笙各,安裝了某個(gè)軟件钉答,如果軟件發(fā)布新版本則需要手動(dòng)更新鏡像。
而自動(dòng)創(chuàng)建允許用戶通過 Docker Hub 指定跟蹤一個(gè)目標(biāo)網(wǎng)站(目前支持 GitHub 或 BitBucket)上的項(xiàng)目杈抢,一旦項(xiàng)目發(fā)生新的提交或者創(chuàng)建新的標(biāo)簽(tag)希痴,Docker Hub 會(huì)自動(dòng)構(gòu)建鏡像并推送到 Docker Hub 中。
要配置自動(dòng)創(chuàng)建春感,包括如下的步驟:
- 創(chuàng)建并登錄 Docker Hub砌创,以及目標(biāo)網(wǎng)站;
- 在目標(biāo)網(wǎng)站中連接帳戶到 Docker Hub鲫懒;
- 在 Docker Hub 中 配置一個(gè)自動(dòng)創(chuàng)建嫩实;
- 選取一個(gè)目標(biāo)網(wǎng)站中的項(xiàng)目(需要含
Dockerfile
)和分支; - 指定
Dockerfile
的位置窥岩,并提交創(chuàng)建甲献。
之后,可以在 Docker Hub 的 自動(dòng)創(chuàng)建頁面 中跟蹤每次創(chuàng)建的狀態(tài)颂翼。
數(shù)據(jù)卷
數(shù)據(jù)卷
是一個(gè)可供一個(gè)或多個(gè)容器使用的特殊目錄晃洒,它繞過 UFS,可以提供很多有用的特性:
-
數(shù)據(jù)卷
可以在容器之間共享和重用 - 對(duì)
數(shù)據(jù)卷
的修改會(huì)立馬生效 - 對(duì)
數(shù)據(jù)卷
的更新朦乏,不會(huì)影響鏡像 -
數(shù)據(jù)卷
默認(rèn)會(huì)一直存在球及,即使容器被刪除
注意:
數(shù)據(jù)卷
的使用,類似于 Linux 下對(duì)目錄或文件進(jìn)行 mount呻疹,鏡像中的被指定為掛載點(diǎn)的目錄中的文件會(huì)隱藏掉吃引,能顯示看的是掛載的數(shù)據(jù)卷
。
創(chuàng)建數(shù)據(jù)卷
docker volume create vol
docker volume ls
-
docker volume inspect vol
查看數(shù)據(jù)卷信息
刪除數(shù)據(jù)卷
docker volume rm vol
數(shù)據(jù)卷
是被設(shè)計(jì)用來持久化數(shù)據(jù)的刽锤,它的生命周期獨(dú)立于容器镊尺,Docker 不會(huì)在容器被刪除后自動(dòng)刪除 數(shù)據(jù)卷
,并且也不存在垃圾回收這樣的機(jī)制來處理沒有任何容器引用的 數(shù)據(jù)卷
并思。如果需要在刪除容器的同時(shí)移除數(shù)據(jù)卷庐氮。可以在刪除容器的時(shí)候使用 docker rm -v
這個(gè)命令宋彼。
無主的數(shù)據(jù)卷可能會(huì)占據(jù)很多空間弄砍,要清理請使用以下命令
$ docker volume prune
啟動(dòng)一個(gè)掛載數(shù)據(jù)卷的容器
在用 docker run
命令的時(shí)候颅筋,使用 --mount
標(biāo)記來將 數(shù)據(jù)卷
掛載到容器里。在一次 docker run
中可以掛載多個(gè) 數(shù)據(jù)卷
输枯。
下面創(chuàng)建一個(gè)名為 web
的容器议泵,并加載一個(gè) 數(shù)據(jù)卷
到容器的 /webapp
目錄。
$ docker run -d -P \
--name web \
# -v my-vol:/wepapp \
--mount source=my-vol,target=/webapp \
training/webapp \
python app.py
掛載主機(jī)目錄
Docker 掛載主機(jī)目錄的默認(rèn)權(quán)限是 讀寫
桃熄,用戶也可以通過增加 readonly
指定為 只讀
先口。
$ docker run -d -P \
--name web \
# -v /src/webapp:/opt/webapp:ro \
--mount type=bind,source=/src/webapp,target=/opt/webapp,readonly \
training/webapp \
python app.py
加了 readonly
之后,就掛載為 只讀
了瞳收。如果你在容器內(nèi) /opt/webapp
目錄新建文件碉京,會(huì)顯示如下錯(cuò)誤
/opt/webapp # touch new.txt
touch: new.txt: Read-only file system