Docker與Dockerfile極簡入門文件

m53469發表於2021-09-09

配置docker不需要sudo


剛裝好的docker每次使用docker命令都需要sudo,比較麻煩,可以透過以下命令省去sudo:

sudo usermod -aG docker 當前使用者名稱

然後一定要記得重新登入該使用者才能生效。

docker核心概念


要理解docker,最核心的是理解三個概念,分別是:倉庫(Registry)、映象(image)和容器(Container)。我們結合一些常見的Docker命令對這些概念進行講解。

倉庫(Registry)

所謂倉庫,其實是個映象倉庫,裡面有很多別人已經打包好的映象,可以直接使用docker pull命令將倉庫中的映象拉到本地,預設的倉庫Docker的官方倉庫。

因為牆的緣故,官方倉庫的速度會比較慢,可以配一個,方法是:修改 /etc/docker/daemon.json,加上如下的鍵值:

{  "registry-mirrors": [""]
}

之後重啟docker服務即可生效。

使用以下命令可以去倉庫中搜尋含有tutorial關鍵字的映象:

docker search tutorial

輸出如下:

NAME                                          DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
learn/tutorial                                                                                38                                      georgeyord/reactjs-tutorial                   This is the backend of the React comment box…   5                                       [OK]
chris24walsh/flask-aws-tutorial               Runs a simple flask webapp demo, with the op…   1                                       [OK]
......(以下省略)

可以使用docker pull命令從倉庫中拉取剛剛搜尋到的映象到本地,這裡為了避免learn/tutorial那個映象被取消,我自己重建了一個一樣的,這裡拉取我建立的那個映象:

docker pull ddfddf/tutorial

輸出如下:

Using default tag: latest
latest: Pulling from ddfddf/tutorial271134aeb542: Pull complete 
483756d37259: Pull complete 
Digest: sha256:4615baf428c61a6feafd8f77f91e0cadc7f8f080710cc82362ac89a5f66a329c
Status: Downloaded newer image for ddfddf/tutorial:latest

ddfddf/tutorial為剛剛搜尋到映象名,預設情況下會拉去最新版本的映象,即ddfddf/tutorial:latest,你也可以用:指定某個特定版本的映象,比如docker pull ubuntu:14.04。其實冒號後面的這個東西的官方術語叫做tag,這個tag可以是一串數字(比如unbantu:14.04的tag是14.04),也可以是一個單詞(比如debian:stretch的tag是stretch),latest也只是一個普通的tag而已,只是當docker pull不去專門指定tag時,預設會去下載tag為latest的映象,透過在中搜尋你想要的映象,點進去之後可以檢視到有哪些tag可以提供下載,如下圖:

圖片描述

搜尋映象的tag

映象(Image)

透過docker images命令可以看到本地已有的映象:

REPOSITORY                              TAG                 IMAGE ID            CREATED             SIZE
ddfddf/tutorial                         latest              48a0196af3c3        3 hours ago         140MB

每個映象都有一個IMAGE ID作為唯一標識,可以看出這個映象的IMAGE ID為48a0196af3c3,使用映象的id可以將它刪除,命令如下:

docker rmi 映象id

這裡先不要著急把剛剛拉下來的映象刪掉,待會實驗還要用。

容器(Container)

然後使用docker run來執行這個映象(執行之後映象就變成一個容器):

docker run ddfddf/tutorial apt-get install -y ping

這個命令會在docker容器中執行"apt-get install -y ping",也就是安裝一個ping命令,執行完之後容器就自動退出了。之後使用docker ps命令可以檢視所有當前正在執行的容器,輸出如下:

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

空的,沒有任何一個容器正在執行,之所以會這樣是因為剛剛容器執行完命令後就退出了。使用docker ps -a命令可以檢視到所有容器,不管它正在執行還是已經退出,輸出如下:

CONTAINER ID        IMAGE                COMMAND                  CREATED             STATUS                      PORTS               NAMES
0299878039f0        ddfddf/tutorial       "apt-get install -y …"   1 minutes ago      Exited (0) 11 minutes ago                       peaceful_wozniak

每個容器也會有一個ID作為唯一標識,從上面的輸出中可以看出CONTAINER ID0299878039f0.

我們嘗試一下如下的命令:

docker run ddfddf/tutorial ping 

這個命令會報如下的錯誤:

docker: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: "ping": executable file not found in $PATH": unknown.

"ping": executable file not found in $PATH這句話中可以看出是因為ping命令沒有裝導致的,剛剛明明裝過ping命令了,為什麼沒有呢?這是因為在容器中的修改並不會影響映象,透過docker commit命令可以將這個容器提交成一個新的映象。命令如下:

docker commit 0299878039f0 ddfddf/ping

命令中0299878039f0是之前用docker ps -a查詢出來的容器ID。

試一下我們新提交的映象learn/ping:

docker run ddfddf/ping ping 

輸出如下:

PING  (111.13.100.92) 56(84) bytes of data.64 bytes from promote.cache-dns.local (111.13.100.92): icmp_req=1 ttl=127 time=60.3 ms64 bytes from promote.cache-dns.local (111.13.100.92): icmp_req=2 ttl=127 time=61.8 ms
......(以下省略)

可見ping命令可以使用了。在上面這個現象的背後,容器其實只是在映象上面新增一個可寫層,每當對這個容器進行修改都會在可寫層標明與原本映象的不同之處,當你使用docker commit命令時,只是提交了一個可寫層,將它變成一個不可寫的映象層,而這個新的映象和原本的映象共享原本映象的所有層,這就是所謂的docker分層機制,其實每個docker映象都是由好多層構成的,這個機制能極大地縮小映象佔用的硬碟空間,如下圖:

圖片描述

docker分層機制

剛剛我們執行ping命令的時候都是在前臺執行的,在它執行的時候我們命令列做不了別的事情,只能眼睜睜地看它輸出,使用如下命令可以讓它後臺執行:

docker run -d ddfddf/ping ping 

這個時候在控制檯就看不到它的輸出,使用docker ps可以看到這個容器的id,它是目前唯一正在執行的容器,如果想看它的輸出的話可以使用docker logs 容器ID的方式檢視。

使用docker stop命令可以停止這個後臺執行的容器:

docker stop 2f371d67d92d

2f371d67d92d為這個容器在我的電腦上的ID

如果你想繼續讓這個容器執行,可以使用docker start命令:

docker start 2f371d67d92d

這個容器又會從剛才停止的地方重新執行,在初學的時候總是會搞混docker startdocker run命令,其實在理解了容器與映象的區別之後,就很容易理解了,docker run使用來啟動映象的,而docker start是用來重新啟動被停止的容器的。
只要映象被執行了一次啊,都會生成一個新的容器,所以此時用docker -a會看到好多廢棄的容器,可以使用docker rm 容器ID的方式將他們刪除掉,也可以使用如下的小技巧一次性刪除所有容器:

docker rm $(docker ps -a -q)

不用擔心,這裡只是刪除所有容器而已,映象還完好無損的保留在那裡。

這裡把容器和映象容易混淆的命令總結在了下表中:


刪除 啟動
映象 docker rmi docker run
容器 docker rm docker start

上文中一直使用容器ID來標明容器,其實在啟動的時候可以透過--name選項來指定一個別名,之後就可以使用這個別名來代替容器ID使用,注意這個別名必須在本臺機器中唯一,示例如下:

docker run -d --name=test ddfddf/ping ping 
docker stop testdocker rm test

上面的命令中給容器起了一個叫做test的別名,然後使用它的別名將其停止與刪除。

如果有些情況下不得已要進入容器內部進行操作的話,可以使用如下命令進入容器內部的shell:

docker run -d --name=test ddfddf/tutorial ping 
docker exec -ti test /bin/bash

docker exec用於在正在執行的容器中執行命令,-ti選項表示分配一個虛擬終端。注意docker exec只能在“正在執行”的容器中執行命令,所以在docker run的時候執行ping就是為了讓這個容器一直執行,而不是立即退出。

再聊聊倉庫(Registry)

之前講過,Docker Hub Registry是Docker的官方倉庫,其實這是一個有點類似於Github的地方,任何人都可以在上面提交與下載映象,我們可以先去上面註冊一個賬戶(地址:),註冊賬戶時會有谷歌的人機認證系統,所以需要一些科學上網技巧。
註冊完成後可以用如下命令在shell中登入:

docker login -u 使用者名稱 -p 密碼

在將映象push到自己新建的賬戶之前,要用docker tag重新命名一下,將映象命名你的使用者名稱/映象名這種形式,不然會push認證不透過,程式碼如下:

docker tag ddfddf/tutorial 你的使用者名稱/tutorial

docker tag並沒有幹太多的事情,只是建立了一個到ddfddf/tutorial映象的引用。之後就可以使用docker push命令將自己的映象推送到賬戶中去了,方便自己和別人的使用:

docker push 你的使用者名稱/tutorial

搞定之後就可以使用以下命令登出了:

docker logout

登入上Docker Hub,你將能看到剛剛你push上去的映象。

總結

最後我再總結一下Docker的三個核心概念間的關係:

圖片描述

docker核心概念及其關聯



作者:燃燒杯
連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2819/viewspace-2818677/,如需轉載,請註明出處,否則將追究法律責任。

相關文章