Docker详解
文章目錄
- 寫在篇前
- 基本概念
- Docker-Engine
- Docker三要素
- Docker-registries
- UnionFS
- 常用命令
- 幫助命令
- 鏡像命令
- 容器命令
- 容器數據卷
- 鏡像發布
- 鏡像加速
- 安裝與卸載
- 高級知識
- Swarm
- service
- stack
- 容器網絡
- Legacy Linking
- Brige Network
- DockerFile
寫在篇前
??Docker是應用程序developing, shipping, 和 running的開放平臺。Docker可將應用程序與應用環境分離,以便快速交付軟件。使用Docker,可以像管理應用程序一樣管理應用環境,利用Docker來快速傳送,測試和部署代碼,顯著減少編寫代碼和在生產中運行代碼之間的延遲。Docker提供了在稱為容器的松散隔離環境中打包和運行應用程序的功能。其隔離、安全的特性允許用戶在給定主機上同時運行多個容器。容器是輕量級的,因為它們不需要管理程序的額外負載,而是直接在主機內核中運行。這意味著可以在給定機器運行比使用虛擬機時更多的容器,甚至可以在實際虛擬機的主機中運行Docker容器!
??本片文章旨在整理匯總docker的重要概念以及常用操作命令,關于更系統的理解,依舊是推薦官方tutorial.
基本概念
Docker-Engine
??Docker-engine采用C/S架構,包括以下組件:
-
server (服務器),這其實是一個守護進程,負責創建和管理Docker對象,例如Images,Containers,Networks和Volumes,對應于dockerd
-
client(客戶端),就是負責和用戶交互的CLI(command line Interface),對應于docker
-
REST API, 負責客戶端與守護進程通信并指示其執行操作的接口。
Docker三要素
-
鏡像(Images)
??Image是一個只讀模板,其中包含有關創建Docker容器的說明;Image可以用來創建容器且一個鏡像可以創造多個容器。通常,一個Image基于另一個Image,并帶有一些額外的自定義。例如,您可以構建基于ubuntu Image的鏡像,但剩下其他的環境配置工作是你自己自定義的。要構建自己的Image也非常簡單,可以使用DockerFile語法創建Dockerfile(定義創建Image和運行Image所需的步驟)。Dockerfile中的每條指令都在Image中創建一個層(Layer)。值得注意的是,更改Dockerfile并重建Image時,僅重建已更改的那些層。因此與其他虛擬化技術相比,這是Docker Image輕量、小巧和快速的一個原因。
-
容器(Container)
??Container是Image的可運行實例,用戶可以使用Docker REST API或CLI創建,啟動,停止,移動或刪除容器,也可以將容器連接到一個或多個網絡、將存儲與之連接,甚至可以根據其當前狀態創建新映像。默認情況下,一個Container與其他Container及其主機相對隔離,可以方便控制容器的網絡等。Container和Image很相似,可以理解為類和對象的關系,同時需要注意Container最上面一層是可讀可寫的。
-
倉庫(Repository)
??集中存放Image的場所,Repository很容易和下面說的Registry(倉庫注冊服務器)混淆。通俗地說,它們的關系是Registry上往往存放著多個Repository,每個Repository存又放著一大堆Images,每個Image存在不同的標簽(Tag);用戶可以從通過注冊服務器從倉庫拉取(帶有某個tag的)Image,從而創建Container。
Docker-registries
??Docker registries是指存儲Docker Image的地方。如Docker Hub是任何人都可以使用的公共registries,這一性質類似于Github。Docker默認配置為在Docker Hub上查找你所需要的Image。注意和Repository進行區分。
UnionFS
??UnionFS(聯合文件系統)是一種分層、輕量級并且高性能的文件系統,它支持對文件系統的修改作為一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬文件系統下;UnionFS一次同時加載多個文件系統,但從外面看起來,只能看到一個文件系統,聯合加載會把各層文件系統疊加起來,這樣最終的文件系統會包含所有底層的文件和目錄。UnionFS是Docker鏡像的基礎,鏡像通過分層進行繼承,基于基礎鏡像(images that no parent image),可以制作各種具體應用的鏡像。
??因此,我們會想,那基礎鏡像是什么呢?答案就是bootfs(boot file system),其主要包含bootloader和kernel。bootloader主要是引導、加載Kernel。這一層和典型的Linux/Unix系統是一樣的,當boot加載完成之后整個內核就會在內存中了,此時內存的使用權已由bootfs交給Kernel,此時系統也會卸載bootfs。
??ok,那在bootfs之上,又是什么呢?其實也和典型Linux/Unix一樣,即是系統中的/dev、/proc、/bin、/etc等標準目錄和文件,這些文件稱為rootfs(root filesystem),是各種不同操作系統的發行版,如Centos、Ubuntu.Docker就是這樣一個創建精簡OS的工具,具有靈活遷移、部署的特性,因此廣受業界歡迎。其rootfs可以很小,只需要包括最基本的命令、工具和程序庫,因為底層直接使用Host的kernel。
常用命令
幫助命令
# 基本幫助命令$ sudo docker version $ sudo docker --version $ sudo docker info # Display system-wide information $ sudo docker --help # help command鏡像命令
$ docker images# -a 列出本地所有的鏡像(含中間映像層)# -q 只顯示images 的id# --digests 顯示鏡像摘要信息# --no-trunc 顯示完整的鏡像信息 $ docker image ls # 同上 $ docker search key_word# -s 列出star數不少于指定值的鏡像# --automated 只列出automated build類型的鏡像# --no-trunc 顯示完整的鏡像信息 $ docker pull image[:tag]$ docker history image_id 查看鏡像來源組成$ docker rmi < image | image_id [image | image_id]># -f 強制刪除# 技巧之刪除所有本地鏡像:docker rmi -f $(docker images -qa) $ docker commit -m=”desc” -a=”author” container_id new_image_name:[Tag] 提交新鏡像 $ docker log -f container_id # 查看容器日志容器命令
$ docker run [OPTIONS] images [COMMAND][ARG...] # 新建并啟動容器--name # 指定一個該新建容器的名字-d # 后臺運行容器并返回容器id,也即啟動守護式容器-i # 以交互模式運行容器,通常與-t合用-t # 為容器重新分配一個偽輸入終端,通常與-i合用-P # 隨機端口映射-p # 指定端口映射,有以下四種格式:ip: hostPort:containerPortip::containerPorthostPort:containerPortcontainerPort# 實例 $ docker run --name [Name of container] -it --cpus=2 -v $PWD:/paddle <imagename> /bin/bash $ docker run -d centos /bin/bash -c "while true;do echo hello;sleep 2;done"$ docker ps [OPTIONS] # 列出docker當前在運行的容器-a # 列出當前所有正在運行的容器+歷史上運行的-l # 顯示最近創建的容器-n # 顯示最近創建的n個容器-q # 靜默模式,只顯示容器編號--no-trunc # 不截斷輸出 $ docker container ls --all # 同上 $ docker kill < container | container _id> # 強制停止容器 $ docker stop < container | container _id> # 停止容器 $ exit # 容器停止退出 $ Ctrl+P+Q # 容器不停止退出 $ docker attach < container | container _id> # 重新進入容器 $ docker exec -t < container | container _id> ls /tmp # 在宿主機但傳入命令在容器中執行 $ docker exec -t < container | container _id> /bin/bash # 進入容器 # attach和exec區別:attach直接進入容器啟動命令的終端,不會啟動新進程;exec是在容器中打開新的終端,并可以啟動新的進程$ docker start < container | container _id> # 啟動容器 $ docker restart < container | container _id> # 重啟容器 $ docker rm [-f]< container | container _id> # 刪除容器# 技巧之刪除所有容器:docker rm -f $(docker ps -aq)docker ps -aq | xargs docker rm $ docker logs [-f -t –tail n] < container | container _id> # 查看容器日志-t # 加入時間戳-f # 跟隨最新的日志打印--tail # 顯示最后幾條 $ docker top < container | container _id> # 查看容器內運行的進程 $ docker inspect < container | container _id> # 查看容器內部結構 $ docker cp < container | container _id>:容器內路徑 目的主機路徑 # 將文件從容器中cp出,反之亦可容器數據卷
??Docker容器產生的數據,如果不通過commit生成新的鏡像,使得數據稱為鏡像的一部分保存下來,那么當容器刪除之后,數據自然也沒了。引入容器數據卷的目的便是:容器持久化;容器間繼承以及數據共享。如此一來,數據卷完全獨立于容器的生命周期,不會在容器刪除時刪除其掛載的數據。
??特點:
- 數據卷可以在容器之間共享或重用數據
- 卷中的更改可以直接生效
- 數據卷的更改不會包含在鏡像的更新之中
- 容器之間配置信息傳遞,數據卷的生命周期一直持續到沒有容器使用它為止
鏡像發布
# 首先自己編寫一個DockerFile $ cd dockerfile_dir $ docker build -f DockerFile -t image_name . $ docker login # 請登錄dockerhub賬號 $ docker tag <image_name> username/repository:tag # 建議加上tag $ docker push username/repository:tag鏡像加速
??https://cr.console.aliyun.com/cn-beijing/repositories, 登陸后可以獲取個人加速地址
sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' {"registry-mirrors": ["https://xxxxxx.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker安裝與卸載
# 卸載 $ sudo apt-get install docker.io $ sudo apt-get remove docker docker-engine docker.io高級知識
Swarm
??swarm 是一組運行 Docker 并且已加入集群中的機器(機器可以為物理機或虛擬機),簡單來說就是一個docker 集群(clustering),該集群由 swarm 管理節點統一管理。特別注意管理節點和工作節點的區別與聯系,一言以蔽之:管理節點是特殊的工作節點,即除了具備工作節點的功能外還具有對集群進行管理的特點。
關于虛擬機創建給出參考代碼:
# 請提前安裝virtualbox $ docker-machine create --driver virtualbox myvm1 $ docker-machine create --driver virtualbox myvm2$ docker-machine ssh myvm1 "docker swarm init" # 通過主機像虛擬機發送信息 $ docker-machine ssh myvm1 # 登錄虛擬機 $ docker-machine ls # 查看有多少虛擬機 $ docker-machine env myvm1 # 查看有關節點的基本信息關于Swarm操作常用代碼:
$ docker swarm init [--advertise-addr addr] [--listen-addr node_addr] # 啟用 swarm mode 并使當前機器成為swarm管理節點 $ docker info # 可以查看到swarm狀態 $ docker swarm join-token -q [worker|manager] # 查看加入令牌 $ docker swarm join --token token_str host:port [--advertise-addr addr] [--listen-addr node_addr]# 當前主機加入swarm,port按照慣例一般使用2377 $ docker swarm leave [--force] # 當前主機脫離swarm$ docker stack deploy -c <composefile> <appname> # 運行指定的 Compose 文件$ docker stack services <appname> # 列出與應用關聯的服務 $ docker stack ps <appname> # 列出與應用關聯的正在運行的容器 $ docker stack rm <appname> # 清除應用,清除應用后記得leave swarm $ docker stack ls # 列出此 Docker 主機上所有正在運行的應用,僅限于swarm情境下使用$ docker node ls # 查看哪些主機在當前swarm中 $ docker node inspect <node ID> # 檢查節點 $ docker node promote <node ID> # 將worker編程manager $ $ docker node ps node_ps # 查看節點進程??上面的話,就可以建立一個swarm,接下來就是在這個swarm上建立service或則stack:
service
?服務(service)實際上是“生產環境中的容器”。一項服務僅運行一個鏡像,但它會編排鏡像的運行方式 。擴展服務將更改運行該軟件的容器實例數,并將多個計算資源分配給進程中的服務。
# service基本操作 $ docker service create --name ** -p ** --replicas number imgae:tag # 啟動service $ docker service ls # 查看service $ docker service ps service_name # 查看service有哪些進程 $ docker service inspect service_name # 查看service詳情 # service擴展 $ docker service update --replicas number service_name $ docker service scale sevice_name=number# 如果是鏡像更新,可以參考以下代碼: $ docker network create -d overlay my-net-name $ docker service create --name service_name --network my-net-name -p ** --replicas number imgage:tag#update $ docker service update --image imgage:tag --update-parallelism 2 --update-delay 10s # 更新鏡像版本,update-parallelism等update參數可以在 docker service inspect 中查看stack
?stack是在服務上面的一層,也就是說stack是由一組服務構成,而服務是由一組容器構成。stack的定義可以用yaml文件來定義:
version:"3"services:web:# 將 username/repo:tag 替換為您的名稱和鏡像詳細信息image: username/repo:tagdeploy:replicas:5restart_policy:condition: on-failureresources:limits:cpus:"0.1"memory:50Mports:- "80:80"networks:- webnetvisualizer:image: dockersamples/visualizer:stableports:- "8080:8080"volumes:- "/var/run/docker.sock:/var/run/docker.sock"deploy:placement:constraints:[node.role == manager]networks:- webnetnetworks:webnet: docker stack deploy -c docker-compose.yml stack_name # 啟動stack docker stack ls # 查看當前集群有哪些stack docker stack services stack_name # 查看某個stack存在哪些service docker stack ps stack_name # 查看stack進程(這里所說進程都是指container)容器網絡
Legacy Linking
?LL方式使用容器名進行連接,實際上它創建了一個橋接網絡,在這個網絡里面,容器間可以進行通信。
- 運行一個container
- 通過container name 連接到另外一個正在運行的container
??docker run --link another-running-container
Brige Network
?是指把容器添加到橋接網絡(BN),這種方式則是創建了一個自定義的橋接網絡,它的類型是isolated network(隔離網絡),只有在這個網絡里的容器才能相互通信。
- 創建一個自定義橋接網絡
- 啟動容器,使容器運行于一個或多個橋接網絡之中,只有同一個橋接網絡的容器之間可以通信
DockerFile
??dockerfile是用來構建docker鏡像的構建文件,是由一系列命令和參數構成的腳本。一句話總結,Dockerfile是軟件的原材料,其是面向開發的;docker image是軟件的交付品,其是交付標準;docker container是軟件的運行態,其是面向部署和運維。三者缺一不可,合力充當docker體系的基石。
- 構建三步驟
- 編寫dockerfile
- docker build
- docker run
- 基本規范
- 每條保留字指令都必須為大寫字母且后面要跟隨至少一個參數
- 指令按照從上到下,順序執行
- #表示注釋
- 每條指令都會創建一個新的鏡像層,并對鏡像進行提交
- DockerFile執行順序
- docker從基礎鏡像運行一個容器
- 執行一條指令并對容器做出修改
- 執行類似docker commit的操作提交一個新的鏡像層
- docker再基于剛提交的鏡像運行一個新容器
- 執行dockerfile中的下一條指令直到所有的指令都執行完
- 保留字指令
總結
- 上一篇: 实用Linux命令
- 下一篇: Tensorflow Serving部署