Docker基礎

源自摘抄,留個記錄,防止再次被禁,不明白公開的純技術文檔也能享受這種待遇。

安裝

使用自動腳本安裝

# wget -qO- https://get.docker.com/ | sh
or
$ sudo curl -sSL https://get.docker.com/ | sh

國內方式,可以通過 --mirror 選項使用國內源進行安裝:

$ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh --mirror Aliyun
# $ sudo sh get-docker.sh --mirror AzureChinaCloud

啟動 Docker

$ sudo systemctl enable docker
$ sudo systemctl start docker

If you want to avoid typing sudo whenever you run the docker command, add your username to the docker group:

$ sudo groupadd docker
$ sudo usermod -aG docker ${USER}

Ubuntu

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
apt-cache policy docker-ce
sudo apt-get install -y docker-ce

Docker should now be installed, the daemon started, and the process enabled to start on boot. Check that it's running:

$ sudo systemctl status docker

國內方式

$ curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

$ echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io

測試 Docker 是否安裝正確

$ docker run --rm hello-world

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b8dfde127a29: Pull complete
Digest: sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24
Status: Downloaded newer image for hello-world:latest


Hello from Docker!
This message shows that your installation appears to be working correctly.
...

使用鏡像

Docker 運行容器前需要本地存在對應的鏡像,如果本地不存在該鏡像,Docker 會從鏡像倉庫下載該鏡像。

獲取鏡像

從 Docker 鏡像倉庫獲取鏡像的命令是 docker pull。其命令格式為:

$ docker pull [選項] [Docker Registry 地址[:端口號]/]倉庫名[:標簽]

具體的選項可以通過 docker pull --help 命令看到,這里我們說一下鏡像名稱的格式。

  • Docker 鏡像倉庫地址:地址的格式一般是 <域名/IP>[:端口號]。默認地址是 Docker Hub(docker.io)。
  • 倉庫名:如之前所說,這里的倉庫名是兩段式名稱,即 <用戶名>/<軟件名>。對于 Docker Hub,如果不給出用戶名,則默認為 library,也就是官方鏡像。

比如:

$ docker pull ubuntu:18.04
18.04: Pulling from library/ubuntu
92dc2a97ff99: Pull complete
be13a9d27eb8: Pull complete
c8299583700a: Pull complete
Digest: sha256:4bc3ae6596938cb0d9e5ac51a1152ec9dcac2a1c50829c74abd9c4361e321b26
Status: Downloaded newer image for ubuntu:18.04
docker.io/library/ubuntu:18.04

上面的命令中沒有給出 Docker 鏡像倉庫地址,因此將會從 Docker Hub (docker.io)獲取鏡像。而鏡像名稱是 ubuntu:18.04,因此將會獲取官方鏡像 library/ubuntu 倉庫中標簽為 18.04 的鏡像。docker pull 命令的輸出結果最后一行給出了鏡像的完整名稱,即: docker.io/library/ubuntu:18.04

列出鏡像

要想列出已經下載下來的鏡像,可以使用 docker image ls 命令。

$ docker image ls
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
redis                latest              5f515359c7f8        5 days ago          183 MB
nginx                latest              05a60462f8ba        5 days ago          181 MB
mongo                3.2                 fe9198c04d62        5 days ago          342 MB
<none>               <none>              00285df0df87        5 days ago          342 MB
ubuntu               18.04               329ed837d508        3 days ago          63.3MB
ubuntu               bionic              329ed837d508        3 days ago          63.3MB

列表包含了 倉庫名標簽鏡像 ID創建時間 以及 所占用的空間

其中倉庫名、標簽在之前的基礎概念章節已經介紹過了。鏡像 ID 則是鏡像的唯一標識,一個鏡像可以對應多個 標簽。因此,在上面的例子中,我們可以看到 ubuntu:18.04ubuntu:bionic 擁有相同的 ID,因為它們對應的是同一個鏡像。

鏡像體積

docker image ls 列表中的鏡像體積總和并非是所有鏡像實際硬盤消耗。由于 Docker 鏡像是多層存儲結構,并且可以繼承、復用,因此不同鏡像可能會因為使用相同的基礎鏡像,從而擁有共同的層。由于 Docker 使用 Union FS,相同的層只需要保存一份即可,因此實際鏡像硬盤占用空間很可能要比這個列表鏡像大小的總和要小的多。

你可以通過 docker system df 命令來便捷的查看鏡像、容器、數據卷所占用的空間。

$ docker system df

TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              24                  0                   1.992GB             1.992GB (100%)
Containers          1                   0                   62.82MB             62.82MB (100%)
Local Volumes       9                   0                   652.2MB             652.2MB (100%)
Build Cache                                                 0B                  0B

虛懸鏡像

上面的鏡像列表中,還可以看到一個特殊的鏡像,這個鏡像既沒有倉庫名,也沒有標簽,均為 <none>。:

<none>               <none>              00285df0df87        5 days ago          342 MB

這個鏡像原本是有鏡像名和標簽的,原來為 mongo:3.2,隨著官方鏡像維護,發布了新版本后,重新 docker pull mongo:3.2 時,mongo:3.2 這個鏡像名被轉移到了新下載的鏡像身上,而舊的鏡像上的這個名稱則被取消,從而成為了 <none>。除了 docker pull 可能導致這種情況,docker build 也同樣可以導致這種現象。由于新舊鏡像同名,舊鏡像名稱被取消,從而出現倉庫名、標簽均為 <none> 的鏡像。這類無標簽鏡像也被稱為 虛懸鏡像(dangling image) ,可以用下面的命令專門顯示這類鏡像:

$ docker image ls -f dangling=true
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
<none>              <none>              00285df0df87        5 days ago          342 MB

一般來說,虛懸鏡像已經失去了存在的價值,是可以隨意刪除的,可以用下面的命令刪除。

$ docker image prune

刪除本地鏡像

如果要刪除本地的鏡像,可以使用 docker image rm 命令,其格式為:

$ docker image rm [選項] <鏡像1> [<鏡像2> ...]

用 ID、鏡像名、摘要刪除鏡像

其中,<鏡像> 可以是 鏡像短 ID鏡像長 ID鏡像名 或者 鏡像摘要

## 鏡像短 ID
$ docker image rm 501

## 鏡像名
$ docker image rm centos

## 摘要
$ docker image ls --digests
REPOSITORY                  TAG                 DIGEST                                                                    IMAGE ID            CREATED             SIZE
node                        slim                sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228   6e0c4c8e3913        3 weeks ago         214 MB

$ docker image rm node@sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228
Untagged: node@sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228

用 docker image ls 命令來配合

像其它可以承接多個實體的命令一樣,可以使用 docker image ls -q 來配合使用 docker image rm,這樣可以成批的刪除希望刪除的鏡像。

比如,我們需要刪除所有倉庫名為 redis 的鏡像:

$ docker image rm $(docker image ls -q redis)

或者刪除所有在 mongo:3.2 之前的鏡像:

$ docker image rm $(docker image ls -q -f before=mongo:3.2)

使用 Dockerfile 定制鏡像

Dockerfile 內容

FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

FROM 指定基礎鏡像

所謂定制鏡像,那一定是以一個鏡像為基礎,在其上進行定制。就像我們之前運行了一個 nginx 鏡像的容器,再進行修改一樣,基礎鏡像是必須指定的。而 FROM 就是指定 基礎鏡像,因此一個 DockerfileFROM 是必備的指令,并且必須是第一條指令。

除了選擇現有鏡像為基礎鏡像外,Docker 還存在一個特殊的鏡像,名為 scratch。這個鏡像是虛擬的概念,并不實際存在,它表示一個空白的鏡像。

FROM scratch
...

如果你以 scratch 為基礎鏡像的話,意味著你不以任何鏡像為基礎,接下來所寫的指令將作為鏡像第一層開始存在。

不以任何系統為基礎,直接將可執行文件復制進鏡像的做法并不罕見,對于 Linux 下靜態編譯的程序來說,并不需要有操作系統提供運行時支持,所需的一切庫都已經在可執行文件里了,因此直接 FROM scratch 會讓鏡像體積更加小巧。使用 Go 語言 開發的應用很多會使用這種方式來制作鏡像,這也是有人認為 Go 是特別適合容器微服務架構的語言的原因之一。

RUN 執行命令

RUN 指令是用來執行命令行命令的。由于命令行的強大能力,RUN 指令在定制鏡像時是最常用的指令之一。其格式有兩種:

  • shell 格式:RUN <命令>,就像直接在命令行中輸入的命令一樣。剛才寫的 Dockerfile 中的 RUN 指令就是這種格式。
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
  • exec 格式:RUN ["可執行文件", "參數1", "參數2"],這更像是函數調用中的格式。

構建鏡像

Dockerfile 文件所在目錄執行:

$ docker build -t nginx:v3 .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM nginx
 ---> e43d811ce2f4
Step 2 : RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
 ---> Running in 9cdc27646c7b
 ---> 44aa4490ce2c
Removing intermediate container 9cdc27646c7b
Successfully built 44aa4490ce2c

這里我們使用了 docker build 命令進行鏡像構建。其格式為:

docker build [選項] <上下文路徑/URL/->

指定了最終鏡像的名稱 -t nginx:v3

鏡像構建上下文(Context)

如果注意,會看到 docker build 命令最后有一個 .. 表示當前目錄,而 Dockerfile 就在當前目錄,因此不少初學者以為這個路徑是在指定 Dockerfile 所在路徑,這么理解其實是不準確的。

首先我們要理解 docker build 的工作原理。Docker 在運行時分為 Docker 引擎(也就是服務端守護進程)和客戶端工具。Docker 的引擎提供了一組 REST API,被稱為 Docker Remote API,而如 docker 命令這樣的客戶端工具,則是通過這組 API 與 Docker 引擎交互,從而完成各種功能。因此,雖然表面上我們好像是在本機執行各種 docker 功能,但實際上,一切都是使用的遠程調用形式在服務端(Docker 引擎)完成。也因為這種 C/S 設計,讓我們操作遠程服務器的 Docker 引擎變得輕而易舉。

當我們進行鏡像構建的時候,并非所有定制都會通過 RUN 指令完成,經常會需要將一些本地文件復制進鏡像,比如通過 COPY 指令、ADD 指令等。而 docker build 命令構建鏡像,其實并非在本地構建,而是在服務端,也就是 Docker 引擎中構建的。那么在這種客戶端/服務端的架構中,如何才能讓服務端獲得本地文件呢?

這就引入了上下文的概念。當構建的時候,用戶會指定構建鏡像上下文的路徑,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
...

客戶端命令(docker)

客戶端命令選項

  • --config="":指定客戶端配置文件,默認為 ~/.docker
  • -D=true|false:是否使用 debug 模式。默認不開啟;
  • -H, --host=[]:指定命令對應 Docker 守護進程的監聽接口,可以為 unix 套接字 unix:///path/to/socket,文件句柄 fd://socketfd 或 tcp 套接字 tcp://[host[:port]],默認為 unix:///var/run/docker.sock
  • -l, --log-level="debug|info|warn|error|fatal":指定日志輸出級別;
  • --tls=true|false:是否對 Docker 守護進程啟用 TLS 安全機制,默認為否;
  • --tlscacert=/.docker/ca.pem:TLS CA 簽名的可信證書文件路徑;
  • --tlscert=/.docker/cert.pem:TLS 可信證書文件路徑;
  • --tlscert=/.docker/key.pem:TLS 密鑰文件路徑;
  • --tlsverify=true|false:啟用 TLS 校驗,默認為否。

客戶端命令

可以通過 docker COMMAND --help 來查看這些命令的具體用法。

  • attach:依附到一個正在運行的容器中;
  • build:從一個 Dockerfile 創建一個鏡像;
  • commit:從一個容器的修改中創建一個新的鏡像;
  • cp:在容器和本地宿主系統之間復制文件中;
  • create:創建一個新容器,但并不運行它;
  • diff:檢查一個容器內文件系統的修改,包括修改和增加;
  • events:從服務端獲取實時的事件;
  • exec:在運行的容器內執行命令;
  • export:導出容器內容為一個 tar 包;
  • history:顯示一個鏡像的歷史信息;
  • images:列出存在的鏡像;
  • import:導入一個文件(典型為 tar 包)路徑或目錄來創建一個本地鏡像;
  • info:顯示一些相關的系統信息;
  • inspect:顯示一個容器的具體配置信息;
  • kill:關閉一個運行中的容器 (包括進程和所有相關資源);
  • load:從一個 tar 包中加載一個鏡像;
  • login:注冊或登錄到一個 Docker 的倉庫服務器;
  • logout:從 Docker 的倉庫服務器登出;
  • logs:獲取容器的 log 信息;
  • network:管理 Docker 的網絡,包括查看、創建、刪除、掛載、卸載等;
  • node:管理 swarm 集群中的節點,包括查看、更新、刪除、提升/取消管理節點等;
  • pause:暫停一個容器中的所有進程;
  • port:查找一個 nat 到一個私有網口的公共口;
  • ps:列出主機上的容器;
  • pull:從一個Docker的倉庫服務器下拉一個鏡像或倉庫;
  • push:將一個鏡像或者倉庫推送到一個 Docker 的注冊服務器;
  • rename:重命名一個容器;
  • restart:重啟一個運行中的容器;
  • rm:刪除給定的若干個容器;
  • rmi:刪除給定的若干個鏡像;
  • run:創建一個新容器,并在其中運行給定命令;
  • save:保存一個鏡像為 tar 包文件;
  • search:在 Docker index 中搜索一個鏡像;
  • service:管理 Docker 所啟動的應用服務,包括創建、更新、刪除等;
  • start:啟動一個容器;
  • stats:輸出(一個或多個)容器的資源使用統計信息;
  • stop:終止一個運行中的容器;
  • swarm:管理 Docker swarm 集群,包括創建、加入、退出、更新等;
  • tag:為一個鏡像打標簽;
  • top:查看一個容器中的正在運行的進程信息;
  • unpause:將一個容器內所有的進程從暫停狀態中恢復;
  • update:更新指定的若干容器的配置信息;
  • version:輸出 Docker 的版本信息;
  • volume:管理 Docker volume,包括查看、創建、刪除等;
  • wait:阻塞直到一個容器終止,然后輸出它的退出符。

refs

https://yeasy.gitbook.io/docker_practice/install/ubuntu

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內容