目錄
- docker介紹
- 安裝與鏡像源配置
- CentOS7
- 安裝
- 設定鏡像源
- 補充:
- CentOS7
- 簡單使用例子
- 基礎概念
- 四個概念
- 鏡像概念補充:
- 容器概念補充:
- 常用命令:
- 查看docker資訊
- 鏡像操作
- 容器操作
- 補充:
- 關于環境變數:
- 容器內容補充:
- 資源節省方面:
- 自動狗帶
- 其他概念補充:
- Daemon守護行程
- 容器卷Volume
- 命令:
- 容器卷的資料傳遞
- 補充:
- 怎么制作docker鏡像
- 修改已有鏡像:
- 使用Dockerfile
- 實體的介紹:
- 常用命令:
- 補充:
- 嘗試使用Dockerfile創建鏡像
- 阿里云推送鏡像和拉取鏡像
- 1. 登錄阿里云Docker Registry
- 2. 將鏡像推送到Registry
- 3. 從Registry中拉取鏡像
發布時間:2020年3月25日
發布者:progor

docker介紹

- 官網
- docker 是一個開源的應用容器引擎,docker 可以讓開發者打包他們的應用以及應用的環境依賴到一個輕量級、可移植的容器中,然后發布到任何流行的 平臺(linux,windows)上,
- docker基于Go語言,
- docker的相關技術有docker swarm ,kubernates,Compose,這些都是比較熱門的容器技術,特別是k8s特別火,
docker是一種容器技術,為什么現在容器技術那么火?
容器能夠打包應用和隔離運行環境,這是出發點,
容器打包應用快速而高效,
容器的資源使用效率比VM高,在理論上,他肯定要比原本無容器下更消耗資源,但他換來的是與環境的隔離,避免了不同環境的問題,而他與另一種環境隔離技術--虛擬機技術相比又更加節省資源,因為虛擬機是虛擬出一臺完整的機器,容器使用宿主機硬體,不需要像虛擬機一樣虛擬硬體,docker使用宿主機的作業系統內核,不需要像虛擬機那樣重新創建一個內核(創建內核消耗時間較多),相應的,容器的啟動速度也要快于虛擬機,
容器可以部署在各種平臺,只要這個平臺能夠安裝docker,然后就可以在docker上部署容器,
容器的部署很快,如果你使用了一臺物理機來部署你的應用,如果某天你的物理機掛了,那么你需要在另外一臺機上安裝各種環境,然后再部署應用,但容器的話就像一套環境的模板,部署很快,
【最重要的一點】容器的打包是把環境一起打包的,就保證了每個應用的運行環境都會是一模一樣的,一次打包,多地運行,很多時候,BUG都是由于環境不同導致的,相同的環境可以避免一些BUG的產生,
現實使用意義:
docker由于其快速部署和一次構建多次部署的特性,使得根據服務器的壓力動態快速部署服務端成為可能,比人工部署服務端快速得多,
安裝與鏡像源配置
CentOS7
安裝
1.卸載可能存在的舊版的docker:
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
2.安裝所需的軟體包:
yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
3.設定下載docker的yum庫
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
4.安裝最新版docker-ce
yum install -y docker-ce
5.啟動docker
systemctl daemon-reload && systemctl start docker
6.查看docker資訊,如果列印成功,那么就是安裝成功了:
docker info
設定鏡像源
docker創建一個容器需要對應的鏡像,而鏡像通常都是從docker hub上下載的,docker hub的功能有點像github,都是一種倉庫,docker hub是存盤鏡像的倉庫,
但是docker hub是一個國外的網站,他的訪問速度不太行,github的不穩定大家應該也深有感受了,所以我們要修改docker 拉取鏡像的鏡像源,讓他從國內的一些鏡像網站來拉取鏡像,這些國內的鏡像都會依靠自己的穩定網路不斷同步docker hub,
編輯/etc/docker/daemon.json檔案,把里面registry-mirrors的值改成下面的:【還可以自行增加阿里云的源】
vi /etc/docker/daemon.json
{
"registry-mirrors": [
"http://hub-mirror.c.163.com",
"https://registry.docker-cn.com"
]
}
阿里的鏡像源還是比較穩定的,可以進入阿里云搜索容器鏡像服務,然后按照下圖來找到加速地址:

補充:
- 其他系統的安裝方式,可以參考官方檔案:Docker安裝
簡單使用例子
這是一個使用docker來創建一個包含了mysql的容器,我們借助這個例子來體驗docker創建應用容器的快速,
1.安裝之后,運行systemctl start docker啟動docker,然后執行以下命令:
docker pull mysql:5.7
當這樣顯示的時候就是代表成功了,

2.查看鏡像:
docker images

3.使用這個鏡像創建一個容器(也可以稱為鏡像實體):
語法:
docker run --name 這個鏡像實體的名字 -e MYSQL_ROOT_PASSWORD=mysql根用戶的密碼 -d -p 主機埠:容器內部的埠 mysql:標簽
(MYSQL_ROOT_PASSWORD=123456 =號不要有空格間隔)
(-d代表后臺運行,-p是為了把容器內部的mysql系結到外部埠進行使用)
具體示例:
docker run --name testmysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 -d mysql:5.7

4.查看容器運行狀態:
docker container ls

5.測驗連接,由于我們使用了-p 3306:3306,這是將容器內部的3306埠與主機的埠建立的連接,,所以可以直接通過連接主機Linux的埠來操作容器內部的mysql:
假設當前我的機器的IP是192.168.48.129,那么我需要連接192.168.48.129:3306來操作資料庫,請使用你的mysql連接工具來測驗吧??,
你做完這個實驗后,你應該能感受到你大大的節省了安裝mysql和部署mysql的功夫,而如果我們創建了一個包含了我們的應用的鏡像,那么部署我們的應用的人也能大大減少部署的難度和節省大量的時間,
另外,我們還引出了鏡像和容器的概念,這將在下面講,
基礎概念
四個概念
上面引出了鏡像和容器的概念,下面講一下,
- 鏡像之于容器,就好像類之于類物件,鏡像是生成多個容器的模板,有了鏡像,能很快地生成多個容器;
- Images: Images是鏡像的意思,鏡像里面是通常包含了應用及其應用運行所需要的環境,但他只是一些資源,并沒有運行起來,就好像安裝作業系統的時候需要IOS檔案,但IOS并不是作業系統,IOS只是一些檔案,只有通過一些對這些資源的軟體處理和硬體處理才可以運行成一個作業系統(在docker中,也需要對鏡像做類似的處理),
- Container:Container是容器的意思,鏡像啟動后的實體稱為容器,容器里面包含獨立運行的一個或多個應用,(從虛擬化角度來可,容器就是一個包含了服務端的運行起來的虛擬機,這就好比我在我的虛擬機上裝了一個我的應用,應用的環境什么的都裝好了,然后我把它的vmx檔案發給你,你再通過vmware把這些vmx啟動起來,)
- 只有將鏡像創建成容器后,里面得應用才是真正得運行起來得(這就好像在面向物件中,平時都是使用具體的類物件);
- Repository:Repository是倉庫的意思,倉庫保存了各種打包好的鏡像,我們需要從倉庫中拉取鏡像來創建容器,有些人或許會把倉庫和倉庫注冊中心弄亂了,這里以一個例子說明:假如我是tomcat鏡像的開發者,我創建了一個tomcat的倉庫,就像github的倉庫那樣,然后我第一次提交了一個tomcat 5.0的鏡像,第二次提交了一個tomcat 7.0的鏡像,這些鏡像都是屬于tomcat倉庫的,但這些鏡像都是屬于同一系列鏡像(當然了,你就是鐵頭娃的存盤了不同系列的鏡像那也沒什么好說的,一個倉庫里面最好還是存盤屬于同一個更新系列的鏡像比較好),如果你要獲取redis的鏡像,那么你要從redis倉庫獲取,而管理著多個倉庫的就是倉庫注冊服務器,
docker hub就是一個知名的倉庫注冊服務器,就好像github是個代碼托管中心一樣,
- Registry:倉庫注冊服務器,是倉庫注冊的地方,類比github來解釋,比如說github上面有私人的倉庫和公開的倉庫,私人的倉庫并不是誰都能拉取和推送的,所以github在實際上擔當了倉庫注冊服務器,它的下面再有私人倉庫和公開倉庫,我們指定獲取鏡像的倉庫時,其實首先要指定倉庫注冊服務器,這樣docker才知道我們的倉庫是在哪里的,平時我們指定的鏡像源地址,其實就是倉庫注冊服務器,因為可能會不同地址的倉庫注冊服務器,就好比git界的github與gitlab,鏡像倉庫網站
通過一個例子把上面的概念串聯起來:
假設我們需要拉取一個tomcat鏡像,
首先,我們指定這個鏡像的倉庫在docker hub,然后搜索一下是否有這個倉庫,然后指定從這個拉取鏡像的哪個版本(tag),然后把它從倉庫上拉取下來;
鏡像拉取下來之后,使用這個鏡像來生成一個容器,這個容器是怎么可以在docker上面運行的呢?這些鏡像都會帶有可以支撐它運行的作業系統,一個較小的作業系統也就10+M,這些作業系統運行在docker上,而里面的應用運行在各自的作業系統上,(你可以這樣類比,docker = vmware,鏡像 = vmx檔案,容器= vmware對vmx檔案運行起來之后的包含了我們的應用的作業系統)
上面的步驟運行起來了一個容器,你可以對這個容器進行操作,(就好像我在簡單使用例子一節中講述的那樣)假設你對了這個容器進行了修改,然后你想提交給別人,該怎么做呢?(這里只是文字概念,詳情參考下面的把鏡像推送到阿里云)
首先,你需要在一個倉庫注冊服務器中創建自己的倉庫,然后在docker中進行登錄操作,并基于修改的容器生成一個鏡像,把這個鏡像推送到倉庫上,然后別人就可以從你的倉庫中拉取下鏡像了,如果你的倉庫是個開放的倉庫的話,
鏡像概念補充:
- 鏡像用于生成容器,它就是生成容器的模板,
- 可以說鏡像就是停止的容器,在后面我們甚至可以學到通過容器來生成自定義的鏡像,
- 鏡像是應用與依賴環境的打包,鏡像里面的應用是需要運行在作業系統之上的,鏡像本身都會攜帶一個比較小型的作業系統,這些作業系統都去除了大多數無用的內容,比如一個簡單的linux鏡像 Alpine Linux 大約只有 10+MB, Ubuntu鏡像大概100+M,
- 其實上面說了,鏡像本質上還是一些檔案而已,不過這些檔案可以被docker以容器的方式運行起來,因為鏡像的檔案包含了作業系統,docker實質上就像是運行一個小型作業系統那樣運行容器,
- 鏡像是實質是一個檔案系統,由于現在還只是開頭,先不引入那么多概念了,而且這東西的概念性內容比較多,可能會后面再整理一章節來講,
容器概念補充:
- 容器用于運行應用或者服務,所以鏡像中必須包含應用或服務所必要的作業系統和應用檔案,
- 容器的運行要基于作業系統,為了在保證應用可以運行的同時節省資源,會對不必要的作業系統檔案和應用檔案進行了縮減,就好像以前的Linux作業系統其實很小,現在的Linux作業系統隨隨便便就幾百上千M,如果削減了一些不必要的功能,
常用命令:
查看docker資訊
- 查看本地docker版本:
docker version或者docker -v,會回傳安裝的docker的版本, - 查看本地docker資訊:
docker info
鏡像操作
- 搜索docker倉庫相關鏡像(或者應當說在倉庫注冊服務器搜索倉庫吧,不過我們下載的是鏡像而不是倉庫罷了):
docker search 鏡像關鍵字,例如docker search mysql,你除了在命令列中搜索,也可以在docker hub上搜索鏡像,docker search 鏡像關鍵字 -s 數字A:列出start數不小于指定數字A的鏡像,【如果提示--star過期,那么使用docker search 鏡像關鍵字 -filter=stars=數字A】【star類似于github中的star,也表示這個鏡像的受歡迎程度】docker search 鏡像關鍵字 --no-trunc:完整顯示鏡像的描述Descriptiondocker search 鏡像關鍵字 --automated:只列出automated build型別的鏡像,

如果你在docker hub上搜索鏡像, 那么首先進入docker hub(https://hub.docker.com/),然后里面有個搜索框,搜索mysql之后你可以看到mysql相關的鏡像,隨便點進去一個,你可以看到這個鏡像的Description(描述),Tags(可以看到有什么版本),Reviews(評價),而在鏡像的旁邊會有一個
docker pull xxxx(xxxx是鏡像的名字),這個就是教你怎么拉取鏡像,(拉取下面講)
- 從倉庫拉取鏡像:
docker pull 鏡像名:tag,:tag是可選的,tag表示標簽,多為軟體的版本,默認是latest,比如docker pull mysql:5.7就代表拉取5.7版本的mysql鏡像,
*tag表示標簽,多為軟體的版本,對于一個鏡像有什么tag,建議到docker hub上搜索這個鏡像,里面會顯示這個鏡像的tag,
- 查看所有本地已有鏡像:
docker imagesdocker images -a:顯示所有鏡像(包含中間映像層),中間映像層的意思是,一個鏡像可能是由多層鏡像層疊而來的,這中間的部分就是中間映像層,(這個知識與鏡像的實質有關,什么時候再寫一章單獨分析,)docker images -q: 只顯示ID,不顯示鏡像名,docker images --no-trunc: 顯示完整的鏡像資訊,主要是完整顯示了Image ID,就跟git的版本ID差不多,短的ID也可以用來標識鏡像,docker images --digests: 顯示鏡像的摘要資訊,每一個機器上拉取下來的同一個鏡像生成的鏡像ID是不一樣的,只有摘要才能判斷他們是否是同一個鏡像,

- 洗掉指定的本地鏡像:
docker rmi 鏡像的ID或者docker rmi 鏡像名:tag- 可以同時洗掉多個鏡像:
docker rmi 鏡像的ID1 鏡像的ID2或者docker rmi 鏡像名1:tag 鏡像名2:tag - 洗掉全部:
docker rmi ${docker images -qa},這是把docker images -qa的結果作為洗掉鏡像的引數, -f:強行洗掉鏡像
- 可以同時洗掉多個鏡像:
- 使用鏡像創建一個容器實體:
docker run [鏡像ID]或[鏡像名:tag]--name 容器的名字:定義容器的名字--detach或-d:讓容器后臺運行-p 主機的埠:容器的埠:將容器的埠系結到主機的埠- 除了
主機的埠:容器的埠,還可以是IP:主機的埠:容器的埠、IP::容器的埠、容器的埠
- 除了
-P:隨機對容器開放的埠進行系結,容器開放的埠是需要宣告的,比如tomcat鏡像中會宣告開放埠8080,隨機系結就會把宣告的埠隨機與主機埠系結,--env或-e:設定容器的環境變數,有些容器需要環境變數來設定一些資料,比如mysql的初始密碼,- 示例:
docker run --name testmysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 -d mysql:5.7 - 如果本地不存在這個鏡像,那么會從倉庫拉取,如果倉庫中也沒有,那么就會報錯,
- 同時執行命令:
docker run [鏡像ID]或[鏡像名:tag] 命令,這個會在啟動容器之后,幫我們執行我們指定的命令,比如docker run -t centos:7 top就會在啟動centos容器后,幫我們執行top,此處我沒用使用-i所以會當場看到top命令的執行,【這個小心使用吧,因為有時候可能會覆寫容器內部的一些命令,比如如果你在運行mysql鏡像時額外執行命令,那么將會導致這個容器無法運行,這將在Dockerfile處講解】
容器操作
- 查看正在運行的容器:
docker ps,docker ps -a查看所有容器,包括沒有在運行的,docker ps -l查看最近創建的容器(一個)docker ps -n 數字查看最近創建的n個容器docker ps -q:只顯示容器IDdocker ps --no-trunc:只顯示容器ID
- 查看容器日志:
docker logs 容器名稱或者容器的ID,有時候容器的啟動問題就要依靠日志來解決,容器的故障資訊都會顯示在日志中,有些應用會把應用的運行日志寫在容器日志中,但有些會寫在容器內的檔案中,docker logs -t 容器名稱或者容器的ID:加入時間戳docker logs -f 容器名稱或者容器的ID:持續列印docker logs --tail 數字 容器名稱或者容器的ID:顯示最后多少行日志docker logs --since 時間 容器名稱或者容器的ID:查看什么時間的日志,時間可以是30m,1h,或者2020-02-02,或者2013-01-02T13:23:37(UTC統一時間),是從什么時候開始的意思,會從指定時間取到現在,
- 停止容器:
docker stop 容器名稱或者容器的ID
- 啟動容器:
docker start 容器名稱或者容器的ID
- 洗掉指定容器:
docker contatiner rm 容器名稱或者容器的ID,容器必須先停止才能被洗掉- 洗掉所有容器:
docker rm -f ${docker ps -a -q} docker ps -a -q | xargs docker rm
- 洗掉所有容器:
- 向容器發命令:
docker exec 容器名稱或者ID 命令,- 發生命令并實時互動
docker exec -it 容器名稱或者ID linux命令:-it可以說是進入了互動界面,而沒有-it的時候只是發了一個請求,顯示的只是請求的結果,-t:在新容器內指定一個偽終端或終端,-i:允許你對容器內的標準輸入 (STDIN) 進行互動,it可以分開使用, - 有些命令是必須以-i模式互動的,比如現在的mysql連接的時候要求你在互動的時候輸入密碼,
- 示例:
docker exec testmysql echo hello
- 發生命令并實時互動
- 進入容器:
docker attach,與docker exec -it的效果有點類似,但它進入的其實是容器啟動時最后執行的命令,- 比如說
docker run -td centos:7 top,創建容器的時候執行了一個top命令,那么attach進入的就是這個top命令,如果你執行的是其他命令,attcach也是進去那個命令的情況下,所以可能有些容器你attach進去是一片空白,【當你在attach中關閉了這個容器最終運行的行程的時候(注意,是關閉,退出并不代表一定關閉),這個容器可能會自動關閉,因為你關閉了他的前臺行程,如果你是在終端命令下,可以使用ctrl+p+q來退出容器但不關閉終端,退出直接用exit,】 - 還有一個attach與exec的不同之處,exec是每次都執行新的命令的(也就是說命令是用新的行程來執行),并不影響原有的容器的前臺行程,而attach是進入了容器的前臺行程,
- 比如說
- 查看容器的埠系結情況:
docker port 容器名稱或者ID

- 查看容器內運行的行程:
docker top 容器名稱或者ID
- 查看容器的底層資訊:
docker inspect 容器名稱或者ID,會顯示容器名稱、容器資料存盤位置、網路設定、環境變數、容器卷等資訊,
- 從本地復制檔案到容器中:
docker cp 本地檔案路徑 容器ID:容器路徑
- 從容器復制檔案到本地:
docker cp 容器ID:容器路徑 本地檔案路徑
- 根據Dockerfile生成鏡像:
docker build【Dockerfile的內容,后面講】
- 根據容器來創建一個鏡像:
docker commit【生成新鏡像的內容,后面講】
補充:
- 命令幫助:
docker --help - 更多命令可以參考命令檔案,雖然他們的檔案講解很一般,
當你學完上述的命令的時候,你應該能理解之前的簡單使用例子中的那些命令的意義了,
上述命令講解中,簡單例子中沒用到的命令,也講述了基本用法,
下面將是一些稍微深入一點的內容,
- 比如容器卷
- 比如有如何制作docker鏡像,
- 比如有如何推送鏡像到阿里云,
- 以及會補充之前一些概念性的內容,
如果你還不是很了解鏡像的拉取、容器的創建和運行命令的話,建議先從各方面嘗試使用各種命令,做一些幫助自己了解的測驗,
關于環境變數:
- 鏡像可能會支持自己的一些引數,就比如說創建mysql鏡像實體的時候需要提供root賬號的初始密碼,這些引數通常通過環境變數來指定,
這一些都通常可以在docker hub中搜索鏡像的時候在鏡像的How to use this image模塊看到:

容器內容補充:
資源節省方面:
- 為了在保證應用可以運行的同時節省資源,會對不必要的作業系統檔案和應用檔案進行了縮減,比如下圖的mysql容器中也是有一個Linux系統,但從mysql的大小來看,我們可以猜到這個作業系統的大小還是遠小于正常的系統鏡像的:
- 查看mysql容器中作業系統核心:

- mysql容器的大小:

自動狗帶
當一個容器發現自己無事可做的時候就會自動狗帶(自殺),
比如說你運行centos容器:docker run centos:7
那么你會發現這個容器一啟動就自動停止了,這是因為centos內部并沒有前臺行程,如果docker檢測到這個容器沒有前臺行程,那么就會自動關閉這個容器,

docker run -td centos這句命令可以讓centos不自動停止,因為使用-t就為這個容器創建一個前臺行程/bin/bash,平時使用-it的時候,會直接進行互動,我們去掉-i和加上d,使得這個互動終端掛起,不馬上互動,
后面我們再想互動的時候,可以使用docker attach 容器ID或者docker exec -it 容器ID 命令來進行互動,
上面說了attach的使用注意事項,由于這里又涉及了attach,再說一遍:
- 進入容器:
docker attach,與docker exec -it的效果有點類似,但它進入的其實是容器啟動時最后執行的命令,- 比如說
docker run -td centos:7 top,創建容器的時候執行了一個top命令,那么attach進入的就是這個top命令,如果你執行的是其他命令,attcach也是進去那個命令的情況下,所以可能有些容器你attach進去是一片空白,【當你在attach中關閉了這個容器最終運行的行程的時候(注意,是關閉,退出并不代表一定關閉),這個容器可能會自動關閉,因為你關閉了他的前臺行程,如果你是在終端命令下,可以使用ctrl+p+q來退出容器但不關閉終端,退出直接用exit,】
解決自動狗帶這個問題的方法就是把你的應用以前臺的方式來運行,又或者創建一個額外的前臺行程,所以對于那些是后臺運行的應用要注意
其他概念補充:
Daemon守護行程
在執行docker命令的時候,有時候docker還沒啟動,那么可能會報一個這樣的錯誤,

你應該看到了一個docker daemon,daemon在計算機領域通常是守護行程的意思,下面我們來介紹一下這個的意義,
docker是一種Client-Server結構的系統,其實我們對于docker的所有操作都是守護行程來幫我們發送給docker的,我們平時運行命令其實是在Docker Client,Docker Client通過命令列與Docker Damon通信,完成Docker相關操作,
我們表面上操作docker,但實際上,我們只是操作守護行程,守護行程來幫我們發送命令,
容器卷Volume
- Volume主要用來共享主機和容器的資料,
- 在不使用容器卷的時候,容器內的硬碟資料是獨立的,主機無法直接讀取容器內的硬碟檔案(復制可以),而且這時候如果洗掉了容器,容器內的硬碟資料也會丟失,
- 而且因為這樣,資料與容器關聯性也變強了,我們不能根據這個容器來生成鏡像了,可能有時候也無法直接很方便的快速部署,所以外部持久化,把資料從容器中抽離出來就可以降低耦合性,
- 如果我們想要對容器內的資料進行外部持久化,那么就需要使用上容器卷了,
- Volume的效果有點像mount,把主機的某個檔案夾與容器內的檔案夾進行了映射,容器的關閉并不會清空主機上的檔案夾,從而把容器的資料持久化到了主機上,
命令:
- 創建容器的時候指定容器卷:
docker run -it -v /宿主機路徑:/容器內路徑 鏡像名- 當目錄并不存在的時候,會自動創建,
- 你可以試驗一下,在內部的指定容器卷目錄中創建一個有資料的檔案,然后再去主機看是否存在,并修改,看修改的內容容器中能否看到,
- 只讀模式:
docker run -it -v /宿主機路徑:/容器內路徑:ro 鏡像名,默認創建的容器卷是兩邊都可讀可寫的,加上ro之后,是容器只讀,主機可讀可寫,

- 創建一個Volume:
docker volume create 容器卷名稱- 此時將自動在主機的docker目錄下指定一個目錄作為容器卷在主機的目錄,比如
/var/lib/docker/volumes/hello/_data - 創建的容器卷的資訊可以使用
docker volume inspect 容器卷名稱來查看 - 容器卷名稱為空的時候將使用一個64位的隨機的名稱,
- 此時將自動在主機的docker目錄下指定一個目錄作為容器卷在主機的目錄,比如
- 查看Volume的詳細資訊:
docker volume inspect 容器卷名稱

- 顯示docker的Volume串列:
docker volume ls-q只顯示容器卷名稱
- 洗掉未使用的Volume:
docker volume prune,會移除沒有被容器使用的容器卷,
- 洗掉一個或多個Volume:
docker volume rm 容器卷名稱
容器卷的資料傳遞
可以使用--volumes-from來繼承另一個容器的容器卷,
比如:
先執行:docker run --name centos1 -itd -v /outpath:/containerpath centos:7
再執行:docker run --name centos2 -itd --volumes-from centos1 centos:7
然后再執行:docker exec -it centos2 cat /containerpath/a
你就可以看到centos2中也配置了容器卷/outpath:/containerpath,也就是說,centos2繼承了centos1的容器卷,
- 由于他們對應的都是主機的同一個目錄,centos1修改的centos2也能看到,反之也是,主機中修改的centos1和centos2都可以看到,
- 而且它的繼承只是配置資訊的傳遞罷了,雖然上面說的是centos2繼承了centos1的容器卷,但centos1關閉了也不會影響centos2讀寫容器卷的內容
- centos1是掛載了容器卷的容器,可以稱為資料卷容器,其他的容器通過繼承它的容器卷,就可以實作多個容器之間的資料共享,
補充:
- 容器卷除了這樣加,還可以使用Dockerfile來添加,這在后面講,
怎么制作docker鏡像
- 一種是通過拉取已有的鏡像創建容器,然后對容器內部進行修改,然后使用命令
docker commit通過容器來生成一個新的鏡像, - 一種是通過制作Dockerfile,然后
docker build來創建鏡像,
修改已有鏡像:
1.比如說我們可以拉取一個tomcat鏡像,然后生成一個容器;
docker pull tomcat:8.0
2.啟動這個容器:
docker run --name mytomcat -d -p 8888:8080 tomcat:8.0
3.對容器進行一些自定義的修改,我們這里把我們的一個非常簡單的應用部署到tomcat上,【這個war是我從一個structs的jar包下弄的,是一個很干凈的war,適合用來做實驗】war下載地址
- 通過
docker cp 本地檔案路徑 容器ID:容器路徑命令把我們的war包復制到tomcat中,
docker cp /struts2-blank.war mytomcat:/ - 進入容器:
docker exec -it mytomcat /bin/bash
把容器內的war包復制到容器的tomcat中:
root@9ce9d01569e6:/usr/local/tomcat# cp /struts2-blank.war webapps/
然后重啟容器:
docker restart mytomcat
【你這里可以玩一下,在cd /usr/local/tomcat/bin/下執行shutdown.sh,你就會發現沒過一會,容器就自動停止了,】
然后你在外部訪問http://主機地址:8888/struts2-blank就可以訪問到
那么現在,這個容器可以說已經有了我們的應用了,那么怎么基于這個容器來創建新的鏡像,以方便通過鏡像來方便部署到一臺臺機器上呢?
4.然后提交鏡像,
docker commit 可以提交容器副本,使之成為一個新的鏡像,
命令:docker commit -a "作者名" -m "提交說明" 容器名稱或id 打包的鏡像名稱:標簽
選項說明:
-a :提交的鏡像作者;
-c :使用Dockerfile指令來創建鏡像;
-m :提交時的說明文字;
-p :在commit時,將容器暫停,
[root@localhost /]# docker commit -a "progor" -m "簡單的新鏡像測驗" mytomcat mytomcat2:1.0
sha256:a3393dbf9326d0f065d6ee8d757c6d7c1050df8a513e6a52286b4af91154806b
5.查詢一下本地鏡像串列,可以看到我們剛剛創建的鏡像:

6.我們基于這個鏡像來創建一個新的容器看看,看是不是有我們的應用了:
docker run --name mytomcat2 -d -p 8889:8080 mytomcat2:1.0
7.然后再在外部訪問一下http://主機地址:8889/struts2-blank,可以訪問,證明了新的鏡像包含了我們之前部署的應用,
使用Dockerfile
使用Dockerfile其實也是通過修改已有鏡像來創建新鏡像,但它把修改的命令都存盤到Dockerfile中了,Dockerfile比手動修改更方便管理,
下面列一個mysql 5.7的示例Dockerfile,由于篇幅問題,這里就不直接列了,請參考下列鏈接,然后介紹一下之后,我們就學習相關的命令,
mysql/5.7/Dockerfile
實體的介紹:
上面的示例的內容也比較長,我不會所有都講,只會講基本流程,


從上面的流程來看,其實就是引入了一個基礎的鏡像之后,配置環境變數等各種引數,其實也就是講我們之前的手動的操作換成了換成命令寫在了Dockerfile了,
常用命令:
- FROM:用于指定一個基礎的鏡像,
- 通常FROM命令都是第一個命令,用來匯入基礎的鏡像,比如可能tomcat這個鏡像要基于jdk,如果要創建一個有tomcat的鏡像,那么這個鏡像的基礎必須得有jdk鏡像,所以如果我們要創建一個運行于tomcat上的Web應用的鏡像的話,我們首先需要一個tomcat作為基礎鏡像,
- 基礎鏡像涉及到了一些鏡像實質的知識,其實一個鏡像可以說是層層繼承下來的,比如說centos繼承一個根源鏡像,jdk繼承這個centos鏡像,tomcat繼承這個jdk鏡像,
- FROM 可以出現多次,用來繼承多個鏡像,這多個鏡像中,共同的部分只會繼承一次,
- 指定基礎鏡像的時候也需要指定tag,如果不指定,那么tag默認是latest,
- 示例:
FROM debian:buster-slim【來自 mysql/5.7/Dockerfile 】
- RUN:用來執行命令,
- 格式:
RUN 命令或者RUN ["可執行檔案"," 引數1","引數2"],例如:RUN ["/bin/bash", "-c", "echo hello"]RUN 命令是在shell中執行的,會做Shell處理,多行命令,可以使用\分行,RUN ["可執行檔案","引數1","引數2"]是非SHELL的,所以它不會進行背景關系變數決議,例如RUN [ "echo", "$HOME" ]
- RUN命令還有一些與中間映像層相關的,這將在后面單獨講,
- 示例:
RUN groupadd -r mysql && useradd -r -g mysql mysql【來自 mysql/5.7/Dockerfile 】
- 格式:
- ENV:用于為容器設定環境變數,
- ENV設定的環境變數,可以使用
docker inspect命令來查看, docker run --env 環境變數名=變數值可以在運行時指定環境變數,會覆寫默認的環境變數,- 可以使用
$變數名或者${變數名}來獲取指定環境變數的值, - 示例:
ENV TINI_VERSION 0.14.0【來自jenkins/Dockerfile 】 - 在獲取環境變數的時候,
${variable:-word}表示如果variable設定,則結果將是該值,如果variable未設定,則為word結果;如果variable設定了,則將是word結果,否則結果為空字串,word都可以是任何字串,包括其他環境變數,可以通過\來進行轉義:例如,\$foo或\${foo}將分別轉換為$foo和${foo}文字, - 環境變數可以使用在以下命令中:ADD,COPY,ENV,EXPOSE,FROM,LABEL,STOPSIGNAL,USER,VOLUME,WORKDIR,ONBUILD(1.4以前不支持環境變數),
- 如果你在ENV中既修改了變數又獲取了這個變數,獲取的變數的值會是舊的值,而不是設定的新的值,
ENV abc=bye def=$abc
- ENV設定的環境變數,可以使用
- USER:用來指定運行容器的時候使用的用戶以及可選的用戶組,默認使用ROOT用戶
- 格式:
USER <user>[:<group>]或者USER <UID>[:<GID>] - 示例:
USER ${user}【來自jenkins/Dockerfile 】
- 格式:
- WORKDIR:用來修改默認的作業目錄,也就是你剛進去容器的作業目錄,當容器啟動時,默認的作業目錄是
/- 對于作業目錄的修改,對后面的使用了相對路徑的Dockerfile命令也是有影響的,,
- 示例:
WORKDIR /data【來自 redis/6.0-rc/Dockerfile 】

- COPY:
- 格式:
COPY [--chown=<user>:<group>] <src> <dest>將檔案從路徑<src>復制到容器路徑<dest>中, - src是一個相對路徑,或者一個URL;dest是一個絕對路徑
- 示例:
COPY docker-entrypoint.sh /usr/local/bin/【來自 redis/6.0-rc/Dockerfile 】
- 格式:
- ADD:
ADD [--chown=<user>:<group>] <src> <dest>:將檔案從路徑<src>復制到容器路徑<dest>中,并解壓,[--chown=<user>:<group>]是可選的,用于修改檔案的所屬用戶或所屬組,但僅使用與Linux容器
*src是一個相對路徑,或者一個URL;dest是一個絕對路徑
- VOLUME:創建容器卷,這樣會隨機創建一個與容器內容器卷相對于的主機目錄,
- 示例:
VOLUME /data【來自 redis/6.0-rc/Dockerfile 】
- 示例:
- EXPOSE:
- EXPOSE指令通知Docker容器在運行時偵聽的埠,在上面的
docker run中有說到可以隨機埠系結,容器怎么知道為我們系結哪些容器內部的埠呢,就是通過expose知道的, EXPOSE <port> [<port>/<protocol>...]- 暴露埠的時候還可以指定埠的連接方式:比如
EXPOSE 80/tcp或EXPOSE 80/udp,默認使用TCP - 無論EXPOSE設定如何,都可以在運行時使用-p標志覆寫它們,
- 示例:
EXPOSE 6379【 redis/6.0-rc/Dockerfile 】
- EXPOSE指令通知Docker容器在運行時偵聽的埠,在上面的
- CMD:CMD也是用來執行命令的,但他只能生效一次,如果你有多個,那么最后指定的生效,
- 格式:
CMD ["可執行命令或檔案","param1","param2"],CMD ["param1","param2"],CMD 命令 param1 param2 - 示例:
CMD ["redis-server"],CMD [ "sh", "-c", "echo $HOME" ],CMD echo hello,CMD ls -a,CMD ["ls","-a"]
- 格式:
- ONBUILD:當將鏡像作為構建另一個鏡像的基礎時,也就是FROM的時候,ONBUILD才會觸發,他不會在自己構建鏡像時觸發,只會在別人FROM它的時候才會觸發,
- ONBUILD讓指令延遲到下一個使用FROM的Dcokerfile建立鏡像時才執行(只能傳一代,不會傳到孫子,也就是說只能延遲一次),
- ONBUILD 主要用于定制基礎鏡像,通過一系列命令來定制基礎鏡像,首先,你要判斷這些命令是應該在子代時執行,而基礎鏡像中不應該執行的,而且這些命令應該是基于子代的背景關系環境的,比如有一個代碼決議器,在父代的時候,他應該還不知道他要決議的代碼在那里,而在子代的時候才知道在哪里,你或許可以說可以在子代的Dockerfile中把決議器復制過去決議器的目錄下,但ONBUILD提供了一個更好的方案,如果你在基礎鏡像的ONBUILD中定義“把決議器復制過去決議器的目錄下”操作,由于ONBUILD的基礎時才運行,所以他使用了子代的背景關系環境,它就知道了代碼檔案在哪里,然后他再“把決議器復制過去決議器的目錄下,
- 示例:
ONBUILD RUN echo hello
ONBUILD的使用例子,沒有結合場景的
- LABEL:用來添加一些鏡像元資料,用來指定鏡像的所有者/創建者、版本等各種元資訊,這些元資訊對于鏡像沒有影響,僅用于標識,
- 格式:
LABEL <key>=<value> <key>=<value> <key>=<value> ... - 指定創建人,以前使用
MAINTAINER 創建者現在推薦使用LABEL maintainer="創建者" - 指定鏡像所有者,
LABEL OWNER="所屬者" - 要查看LABEL資訊,可以使用
docker inspect命令, - 示例:
LABEL maintainer="[email protected]"【官方檔案示例】

- 格式:
- ENTRYPOINT:用于指定通過鏡像創建或運行容器時,要執行的命令或者檔案,
- 示例:
ENTRYPOINT ["docker-entrypoint.sh"]【來自 redis/6.0-rc/Dockerfile 】 - 那么它與CMD的區別呢?有時候我們能在Dockerfile中看到ENTRYPOINT命令之后還有CMD命令,
- 當你在RUN中附加命令的時候,會附加在ENTRYPOINT后面,并覆寫CMD.
- CMD應該用作ENTRYPOINT在容器中定義命令或執行臨時命令的默認引數的方式,
- 示例:
- ARG:
- ARG是docker1.9 版本才新加入的指令,
- ARG 定義的變數只在建立 image 時有效,建立完成后變數就失效消失,
- ARG定義的變數可以在Dockerfile中使用
${group}來獲取, - 同名的ENV環境變數始侄訓覆寫ARG同名變數
ARG user=jenkins【來自jenkins/Dockerfile 】

補充:
- 可以在Dockerfile中使用#來做單行注釋,例如
# add gosu for easy step-down from root - 你應該可以看到上面的RUN命令的時候通常會執行很多命令,這些命令使用
\來分行, - 另外,在使用環境變數或者ARG變數的時候,如果變數值有空格,要要使用""包裹,例如
cd "$OPENSSL_PATH" - 說一下RUN,CMD,ENTRYPOINT的區別:
- RUN它用于執行命令,做的主要是一些準備作業,比如創建用戶、創建目錄、安裝程式,并不直接與應用的啟動相關,
- ENTRYPOINT用于指定創建和運行容器時要執行的命令,所以你可以在ENTRYPOINT中指定創建容器的時候要運行的一些命令,或者可以說,它是RUN的組合,但ENTRYPOINT更具有
應用意義,RUN可以隨便創建一個目錄,或許做的只是一些運行的前置作業;但ENTRYPOINT里面應該與這個容器前臺行程(應用)的運行更加相關,比如定義如何啟動應用,當然你也可以使用RUN創建前臺行程??,,, - CMD也是用來指定容器的前臺行程的,但有了ENTRYPOINT的時候,它將作為ENTRYPOINT的引數,比如上面提到的MYSQL的例子中 mysql/5.7/Dockerfile ,最后的是
CMD ["mysqld"],而前面有ENTRYPOINT ["docker-entrypoint.sh"],這將會在執行docker-entrypoint.sh的最后執行mysqld,內部有沒有再處理mysqld,就要看具體的docker-entrypoint.sh了,這是一個流行用法,所以你可以在很多Dockerfile中看到"docker-entrypoint.sh"
- 基礎鏡像繼承相關:
- 環境變數會繼承下來,如果你知道基礎鏡像的環境變數的話,可以直接復用,
- 基礎鏡像的CMD會繼承下來,
- 容器卷會繼承下來,
- 官網Dockerfile檔案,只能說好過沒有
嘗試使用Dockerfile創建鏡像
先來解釋一下docker build的用法:
- 語法格式:
docker build Dockerfile檔案路徑,不要漏了檔案路徑,這個路徑同時也是Dockerfile的背景關系-f Dockerfile檔案名,默認情況下,檔案名默認是Dockerfile,如果你使用的不是默認的,需要使用-f指定-t 鏡像名:tag,如果你不指定鏡像名的話,那你就要留意后面構建完成的時候回傳給你的鏡像ID,比如Successfully built 0a9ee2fae0d0- 示例:
docker build -t mytomcat6:1.0 -f TomcatDockerfile .最后的.代表從當前目錄查找TomcatDockerfile;docker build -t mytomcat5:1.0 war會從當前目錄下的war目錄下查找Dockerfile - docker build還有很多配置引數,比如cpu,記憶體什么的,自查了解吧,
1.我們根據之前的“修改已有鏡像”的例子來寫一個Dockerfile:
# 繼承基礎鏡像
FROM tomcat:8.0
# 把war包拷貝進去
COPY struts2-blank.war /
# 把容器內的war包復制到容器的tomcat中
WORKDIR $CATALINA_HOME
RUN cp /struts2-blank.war webapps/
# 指定埠,埠也會繼承下來,由于我們也使用一樣的埠,其實可以省略EXPOSE
# EXPOSE 8080
# 啟動tomcat,基礎鏡像的CMD會繼承下來 所以其實下面的CMD可以省略,除非你要執行另外的命令
# CMD ["catalina.sh", "run"]
2.執行docker build 創建一個鏡像:
docker build -t mytomcat3:1.0 .
3.通過這個鏡像創建一個容器:
docker run --name mytomcat3container -d -p 8888:8080 mytomcat3:1.0
4.測驗訪問:
http://主機地址:8888/struts2-blank
5.結果是可以訪問的,說明我們使用Dockerfile實作了之前基于容器修改生成鏡像的效果,
阿里云推送鏡像和拉取鏡像
下面的基本來自阿里云的官網教程,只不過加了配圖,
1. 登錄阿里云Docker Registry
語法:
$ sudo docker login --username=用戶名 倉庫注冊服務器
示例:
$ sudo docker login --username=10086 registry.cn-shenzhen.aliyuncs.com

- 用于登錄的用戶名為阿里云賬號全名,
- 密碼為開通服務時設定的密碼,不是你阿里云的密碼,
- 您可以在訪問憑證頁面修改憑證密碼,
2. 將鏡像推送到Registry
語法:
1.登錄
$ sudo docker login --username=用戶名 倉庫注冊服務器
2.創建tag:
$ sudo docker tag 鏡像ID 倉庫注冊服務器/用戶名/鏡像名:[鏡像版本號]
3.推送鏡像:
$ sudo docker push 倉庫注冊服務器/用戶名/鏡像名:[鏡像版本號]
docker tag 用于重命名鏡像,下面的就把本地的一個鏡像重命名了,


然后你就可以在倉庫管理頁看到這個鏡像了,

3. 從Registry中拉取鏡像
語法:
$ sudo docker pull 鏡像地址
示例:
$ sudo docker pull registry.cn-shenzhen.aliyuncs.com/用戶名/鏡像名:[鏡像版本號]

這一篇文章,其實講的東西還是很淺的,還有很多東西都沒用講,
但對于基本使用場景應該還是可以應付的,(當然,??容器管理、swarm、k8s并沒有講)
還有很多技術沒講,后面有空再寫吧,,,咕咕咕,
- .dockerignore
- 命令的深層次應用啊
- 鏡像的實質:聯合檔案系統啊、容器的環境隔離技術啊
- ,,,,,
有興趣的可以自行去找書籍來了解更多底層的東西,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/10480.html
標籤:其他
上一篇:關與WebService的restful方式發布服務遇到的問題: HTTP response '404: Not Found'
