什麼是docker?
Docker是基於go語言實現的開源容器專案,誕生於2013年年初,最初發起者是,dotCloud公司。
Docker 專案已加入Linux基金會,並遵循Apache2.0協議,全部程式碼再github上維護。
Docker的構想是要實現Build Ship and Run Any app anywhere
即通過對應用的封裝,分發,佈署,執行生命週期進行管理,達到應用元件一次封裝,到處執行的目的。
這裡的應用元件不侷限於web應用,可以是一個編譯環境,可以是一個資料庫平臺服務,甚至可以是作業系統和叢集。
Docker的發展建立在Linux容器技術之上。
為什麼使用Docker?
在雲時代,應用程式可以脫離底層物理硬體的限制,在任何時間任何地點即可獲取。這樣子可以做到快速的分發和部署。通過Docker來打包應用,解耦應用和執行平臺。降低開發成本和部署風險。
Docker優點
- 更快速的交付和部署
- 更高效的資源利用
- 更輕鬆的遷移和擴充套件
- 更簡單地更新管理
Docker核心概念
映象: 只讀模板,包含一個基本的作業系統 容器: 一個輕量級的沙箱,容器是從映象建立的,應用的執行例項。可以啟動開始停止刪除,容器彼此間相互隔離。 倉庫: 類似於程式碼倉庫,是集中存放映象檔案的場所。
Docker Image - Docker映象
如何使用Docker映象
Docker執行容器前需要本地存在對應的映象,如果映象沒儲存在本地,Docker會嘗試先從預設映象倉庫下載。
使用docker pull
命令可以直接從Docker Hub映象源來下載映象。
docker pull NAME[:TAG]
NAME: 映象的名稱
TAG: 映象的版本
複製程式碼
eg: 綜上,一個映象需要的資訊就是名稱
+標籤
docker pull ubuntu:14.04
14.04: Pulling from library/ubuntu
bae382666908: Pull complete
29ede3c02ff2: Pull complete
da4e69f33106: Pull complete
8d43e5f5d27f: Pull complete
b0de1abb17d6: Pull complete
Digest: sha256:6e3e3f3c5c36a91ba17ea002f63e5607ed6a8c8e5fbbddb31ad3e15638b51ebc
Status: Downloaded newer image for ubuntu:14.04
複製程式碼
如果不顯示的指定TAG
,預設會選擇latest
標籤。會下載最新版的映象。
啟動映象
下載到本地後,可以利用該映象建立一個容器
docker run -it ubuntu:14.04 bash
/*
-i
-t
*/
root@4a9c106836e1:/#
複製程式碼
執行完成會進入bash介面,可以執行一些基本操作
檢視映象的資訊
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
calculatorapp latest 1dec489fae9a 12 hours ago 955MB
<none> <none> 2dab0d648733 6 days ago 755MB
node 6.11.1 1ffbfd4a58ec 2 months ago 656MB
引數
docker iamges
-a 列出所以映象
複製程式碼
使用Tag命令新增映象標籤
docker tag ubuntu:lastest myubuntu:lastest
REPOSITORY TAG IMAGE ID CREATED SIZE
myubuntu lastest dea1945146b9 2 weeks ago 188MB
ubuntu 14.04 dea1945146b9 2 weeks ago 188MB
複製程式碼
實際上看到IMAGE ID是一樣的,所以上實際指向同一個映象檔案。
刪除映象
1.通過標籤刪除
docker rmi IMAGE[IMAGE...]
複製程式碼
eg:
REPOSITORY TAG IMAGE ID CREATED SIZE
myubuntu lastest dea1945146b9 2 weeks ago 188MB
docker rmi myubuntu:latest
複製程式碼
2.通過ID刪除
docker rmi ID
複製程式碼
REPOSITORY TAG IMAGE ID CREATED SIZE
myubuntu lastest dea1945146b9 2 weeks ago 188MB
docker rmi dea1945146b9
複製程式碼
注意
在刪除時,如果沒有容器使用這個映象,那麼會直接刪除該映象及包含的所有層。
但是如果有容器使用了該映象,會得到該提示
docker rmi myubuntu:lastest
Error response from daemon: conflict: unable to remove repository reference "myubuntu:lastest" (must force) - container 4a9c106836e1 is using its referenced image dea1945146b9
複製程式碼
有兩種方式可以解決:
- 使用
-f
引數強制刪除(不推薦) - 先刪除容器,在刪除映象
建立映象
三種方式建立映象:
- 基於已有映象的容器建立
- 基於本地模板匯入
- 基於Dockerfile建立
Docker container - Docker 容器
容器是映象的一個執行例項。
容器建立
使用docker create
建立完畢的容器處於停止狀態,可以使用docker start命令來啟動
docker create
-d 是否在後臺執行
複製程式碼
eg:
docker create -it ubuntu:latest
bb821ea158758312d0832d2c971aab1665cce73541f04f22ca292f979c871e2e
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bb821ea15875 ubuntu:latest "/bin/bash" 3seconds ago Created adoring_archimedes
複製程式碼
啟動容器
使用docker start
命令來啟動一個已經建立的容器
docker start [container_name/container_id]
複製程式碼
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bb821ea15875 ubuntu:latest "/bin/bash" 3seconds ago Created adoring_archimedes
docker start bb821ea15875
or
docker start adoring_archimedes
複製程式碼
檢視執行的容器
使用docker ps
命令來檢視正在執行的容器
docker ps
-a 檢視所有的容器
複製程式碼
新建並啟動容器
docker run
= docker create
+ docker start
docker run
-i 讓容器的標準輸入保持開啟
-t 讓docker分配一個偽終端(pseudo-tty),並繫結到容器的標準輸入上
複製程式碼
eg:
docker run -it ubuntu:14.04 /bin/bash
在ubuntu14.04上啟動一個bash終端,並允許使用者互動
可以使用exit或者ctrl+d來退出容器
複製程式碼
守護態執行(後臺執行)
docker run -d ubuntu:14.04 /bin/bash
-d 後臺執行並輸出 container ID
複製程式碼
注意
如果是以後臺執行的,可以使用docker logs [container_name/container_id]
的方式來獲取容器的輸出資訊
終止容器
docker stop [container_name/container_id]
複製程式碼
進入容器
在使用-d
引數時,容器啟動會進入後臺。使用者無法看到容器中的資訊,也無法進行操作
三種方式解決:
attach
命令(不推薦使用)exec
命令(推薦使用)- nsenter工具(不推薦)
docker exec -it [container_name/container_id] /bin/bash
-i 開啟標準輸入接受使用者的輸入
-t 讓docker分配一個偽終端(pseudo-tty),並繫結到容器的標準輸入上
-u 執行命令的使用者
複製程式碼
刪除容器
docker rm [container_name/container_id]
-f 強制終止並刪除一個正在執行的容器
複製程式碼
Docker Repository - Docker 倉庫
倉庫:
- 公有倉庫
- 私有倉庫
docker hub:docker官方的公共映象倉庫
Docker 資料管理
容器管理資料有兩種方式:
- 資料卷(Data Volumes): 容器內的資料直接對映到本地主機環境
- 資料卷容器(Data Volume Containers): 使用特定容器維護資料卷
資料卷
什麼是資料卷? 可供容器使用的特殊目錄,它將主機作業系統目錄直接對映進容器
優勢:
如何建立資料卷?
三種方式:
- 容器內部建立一個資料卷
- 掛載一個主機目錄作為資料卷
- 掛載一個本地的主機檔案作為資料卷(不推薦)
容器內部建立一個資料卷
在容器內建立一個資料卷使用-v
引數,本質上就是容器內部建立了一個資料夾
docker run -it -v /webapp ubuntu
//在容器內部建立一個資料夾
-v Bind mount a volume
複製程式碼
eg:
docker run -it ubuntu
root@f22d574bb63f:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
docker run -it -v /webapp ubuntu
root@c3acf065e9c2:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var webapp
//多了一個webapp資料夾
複製程式碼
掛載一個主機目錄作為資料卷(推薦)
也是使用-v
引數,
docker run -it -v /src/webapp:/opt/webapp ubuntu
//將本地的/src/webapp目錄掛載到容器內部的/opt/webapp
複製程式碼
本地目錄路徑必須是絕對路徑
,如果目標目錄不存在,docker會自動建立。但是如果目標存在,???
Docker 掛載的資料卷預設許可權是讀寫(rw),也可以更改
資料卷容器
建立一個資料卷容器可以在多個容器之間共享一個持續更新的資料。
如何建立?
docker run -it --name dbdata -v /dbdata ubuntu
//建立一個dbdata的資料夾作為共享資料卷
--name 給容器起一個名字
複製程式碼
其他容器如何使用這個共享的資料卷?
docker run -it --volumes-from dbdata --name db1 ubuntu
//將一個container名字為dbdata的資料卷也掛載到當前的容器中
--volumes-from Mount volumes from the specified container(s) 從指定的container來掛載卷
複製程式碼
利用容器捲來做資料備份 1.備份
$ docker run --volumes-from dbdatasrc -v $(pws):/backup --name worker ubuntu tar cvf /back/backup.tar /dbdata
//將容器dbdatasrc內部的資料卷(/dbdata)掛載到新的ubuntu的容器上(起名為worker容器),此時worker容器內部會有/dbdata的資料卷.
//同時將/dbdata內部的所有資料壓縮打包到worker容器下的/back目錄下。 實現資料備份。
複製程式碼
埠對映和容器互聯
從外部訪問容器應用(埠對映)
在啟動容器的時候,如果不指定對應的引數,在容器外部是無法通過網路來訪問容器內的網路應用和服務的。
如何讓外部的訪問容器?
1.通過-P
大寫P
使用-P標記時,Docker會隨機對映一個49000~49900的埠到容器開放的網路埠:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5ad0d233c126 training/webapp "python app.py" 46 seconds ago Up 44 seconds 0.0.0.0:32768->5000/tcp dazzling_kirch
複製程式碼
2.通過-p
小寫p
可以指定要對映的埠
支援的格式
HostPort:Container | Ip:HostPort:Container | Ip::ContainerPort
複製程式碼
第一種HostPort:Container
, 將本地的埠對映到容器的指定埠
對映所有介面地址
docker run --name test1 -p 5000:5000 training/webapp python app.py
//將本地的5000埠對映到容器的5000埠
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f7f8a05e63a9 training/webapp "python app.py" 3 seconds ago Up 3 seconds 0.0.0.0:5000->5000/tcp ecstatic_einstein
docker run -p 5000:5000 -p 3000:80 ubuntu
複製程式碼
這時繫結的是所有IP段的5000埠
到容器的5000
埠
第二種IP:HostPort:ContainerPort
, 將本地的指定IP的埠對映到容器的指定埠
對映到指定地址的指定埠
docker run --name test2 -p 127.0.0.1:5000:5000 training/webapp python app.py
//將本地的ip僅為127.0.0.1的5000對映到容器的5000
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bd4e352c3b48 training/webapp "python app.py" 2 minutes ago Up 2 minutes 127.0.0.1:5000->5000/tcp test1
複製程式碼
第三種Ip::ContainerPort
,
對映到指定地址的任意埠
docker run --name test3 -p 127.0.0.1::5000 training/webapp python app.py
//繫結127.0.0.1的任意埠到容器的5000埠,本地主機會隨機分配一個埠
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b804acc891df training/webapp "python app.py" 5 seconds ago Up 3 seconds 127.0.0.1:32768->5000/tcp test3
複製程式碼
檢視埠對映配置情況
docker port [container_name/container_id]
eg:
docker port b804acc891df
5000/tcp -> 127.0.0.1:32768
//表示容器的5000對映在本地主機的127.0.0.1:32768
or:
docker port b804acc891df 5000
127.0.0.1:32768
複製程式碼
容器互連
容器互連是一種讓多個容器中的應用進行快速互動的方式。它會在源和接收容器之間建立連線關係,接收容器可以通過容器名
快速的訪問到源容器,而不用指定IP地址。
自定義容器命名,在建立容器的時候,使用--name
引數,否則系統會隨機生成一個名字。
使用--link
引數可以讓容器之間安全的進行互動。
eg:
1.建立一個新的資料庫容器
$ docker run -d --name db-container training/postgres
2.建立一個新的web容器可以訪問這個資料庫容器
$ docker run -d -P --name web --link db-container:db training/webapp python app.py
// --link name:alias
//name: 要連線的容器名稱
//alias: 連線的別名 (這個是啥意思?有什麼用?)
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c5797ccc4f95 training/webapp "python app.py" 2 hours ago Up 2 hours 0.0.0.0:32769->5000/tcp web
cdd159304af3 training/postgres "su postgres -c '/..." 2 hours ago Up 2 hours 5432/tcp db-container
複製程式碼
Docker 相當於在兩個互連的容器之間建立了一個虛擬通道,而且不用對映他們的埠到宿主主機上。
docker通過兩種方式為容器公開連線資訊:
- 更新環境變數
- 更新/etc/hosts檔案
我的理解:如果兩個容器互連,那麼他們之間肯定需要通過一些方式去聯通。此處的db-container 相當於父容器。
它的hosts資訊如下:
db-container
的/etc/hosts
:
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 cdd159304af3 <= 自己的容器的ID
複製程式碼
那與之相連的web
容器就不太一樣了
web
的/etc/hosts
:
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 db db-container cdd159304af3 <= --link 的引數db-container:db
172.17.0.3 c5797ccc4f95 <= 自己的容器的ID
複製程式碼
參考資料
書籍:《Docker 技術入門與實戰》