什么是Docker?
Docker 最初是dotCloud公司創始人Solomon Hykes在法國期間發起的一個公司內部項目,它是基於dotCloud公司多年雲服務技術的一次革新,並與2013年3月以Apache 2.0授權協議開源),主要項目代碼在GitHub上進行維護。Docker項目后來還加入了Linux基金會,並成立推動開放容器聯盟。
Docker 自開源后受到廣泛的關注和討論,至今其GitHub項目已經超過3萬6千個星際和一萬多個fork。甚至由於Docker項目的火爆,在2013年底,dotCloud公司決定改名為Docker。Docker最初在Ubuntu12.04上開發實現的;Redhat則從RHEL6.5開始對Docker進行支持;Google也在其PaaS產品中廣泛應用Docker。Docker使用Google公司推出的Go語言進行開發實現,基於Linux內核的cgroup,namespace,以及AUFS類的Union FS等技術,對進程進行封裝隔離,屬於操作系統層面的虛擬化技術。由於隔離的進程獨立於宿主和其它的隔離的進程,因此也稱其為容器。最初實現是基於LXC,從0.7以后開始去除LXC,轉而使用自行開發的libcontainer,從1.11開始,則進一步演進為使用runC和containerd。
Docker 的基本概念
Docker 容器是資源分割和調度的基本單位,封裝整個服務的運行時環境,用於構建、發布和運行發布式應用的一個框架。它是一個跨平台,可移植並且簡單易用的容器解決方案。
Docker 容器可以快速自動化地部署應用,並通過操作系統內核技術(namespaces、cgroups等)為容器提供資源隔離與安全保障。Docker 作為輕量級的虛擬化方式,實現了PaaS平台高效部署、運行和維護。
Docker 在容器的基礎上,進行了進一步的封裝,從文件系統、網絡互聯到進程隔離等待,極大的簡化了容器的創建和維護。使得Docker技術比虛擬機技術更為輕便,快捷。
- 傳統虛擬機技術是虛擬出一套硬件后,在其上運行一個完整操作系統,在該系統上再運行所需應用進程;
- 而容器內的應用進程直接運行於宿主的內核,容器內沒有自己的內核,而且也沒有進行硬件虛擬化。因此容器要比傳統虛擬機更為輕便。
傳統虛擬化結構對比Docker結構
為什么要使用Docker?
- 更高效的利用系統資源
由於容器不需要進行硬件虛擬化以及運行完整操作系統等額外開銷,Docker對系統資源的利用率更高。無論是應用執行速度、內存損耗或者文件存儲速度,都要比傳統虛擬機技術更高效。因此,相比虛擬機技術,一個相同配置的主機,往往可以運行更多數量的應用。
- 更快速的啟動時間
傳統的虛擬機技術啟動應用服務往往需要數分鍾,而Docker容器應用,由於直接運行於宿主機,無需啟動完整的操作系統,因此可以做到秒級、甚至毫秒級的啟動時間。大大的節約了開發、測試、部署的時間。
- 一致的運行環境
開發過程中一個常見的問題是環境一致性問題。由於開發環境、測試環境、生產環境不一致,導致有些bug並未在開發過程中被發現。而Docker的鏡像提供了除內核外完整的運行時環境,確保了應用運行環境一致性,從而不會再出現“這段代碼在我機器上沒問題啊”這類問題。
- 持續交付和部署
對開發和運維(DevOps)人員來說,最希望的就是一次創建或配置,可以在任意地方正常運行。
使用Docker可以通過定制應用鏡像來實現持續集成、持續交付、部署。開發人員可以通過Dockerfile來進行鏡像構建,並結合持續集成(Continuous lntegration)系統持續進行集成測試,而運維人員則可以直接在生產環境中快速部署該鏡像,甚至結合持續部署(Continuous Delivery/Deployment)系統進行自動部署。而使用Dockerfile使鏡像構建透明化,不僅僅開發團隊可以理解應用運行環境,也方便運維團隊理解應用運行所需條件,幫助更好的生產環境中部署該鏡像。
- 更輕松的遷移
由於Docker確保了執行環境的一致性,使得應用的遷移更加容易。Docker可以在很多平台上運行,無論是物理機、虛擬機、公有雲、私有雲,甚至是筆記本,其運行結果是一致的。因此用戶可以很輕易的將在一個平台上運行的應用,遷移到另一個平台上,而不用擔心運行環境的變化導致應用無法正常運行的情況。
- 更輕松的維護和擴展
Docker使用的分層存儲以及鏡像的技術,使得應用重復部分的復用更為容易,也使得應用的維護更新更加簡單,基於基礎鏡像進一步擴展鏡像也變得非常簡單。此外,Docker團隊同各個開源項目團隊一起維護了一大批高質量的官方鏡像,既可以直接在生產環境使用,又可以作為基礎進一步定制,大大降低了應用服務的鏡像制作成本。
Docker對比傳統虛擬機
特性 | 容器 | 虛擬機 |
啟動 | 秒級 | 分鍾級 |
磁盤使用 | 一般為MB | 一般為GB |
性能 | 接近原生 | 弱於 |
系統支持量 | 單機支持上千個容器 | 一般幾十個 |
Docker 體系結構簡介
Docker 是一個客戶/服務器(Client/Server,CS)架構(見上圖)。Docker客戶端是遠程控制器,可通過TCP REST向Docker Host 發送請求,包括創建容器、運行容器、保存容器、刪除容器等請求。Docker服務端的Daemon 對客戶端的請求進行相應的管理,隨后通過 driver轉發至容器中的libcontainer執行環境。libcontainer提供與不同Linux內核隔離的接口,類似命名空間及控制組。這種架構允許多個容器在共享同一個Linux內核的情況下完全隔離的運行。
Docker 鏡像(Images) | Docker 鏡像是用於創建 Docker 容器的模板。 |
Docker 容器(Container) | 容器是獨立運行的一個或一組應用。 |
Docker 客戶端(Client) | Docker 客戶端通過命令行或其他工具使用 Docker API (https://docs.docker.com/reference/api/docker_remote_api)與Docker 的守護進程通信。 |
Docker 主機(Host) | 一個物理或者虛擬的機器用來執行 Docker 守護進程和容器。 |
Docker 倉庫(Registry) | Docker 倉庫用來保存鏡像,可以理解為代碼控制中的代碼倉庫。Docker Hub(https://hub.docker.com)提供了龐大的鏡像集合供使用。 |
Docker Machine | Docker Machine 是一個簡化Docker安裝的命令行工具,通過一個簡單的命令即可在響應的平台上安裝Docker,比如VirtualBox、Digital Ocean、Microsoft Azure。 |
Docker 8大應用場景
(1)、簡化配置
這是Docker公司宣傳的 Docker 的主要使用場景。Docker 能將運行環境和配置放在代碼中然后部署,同一個 Docker 的配置可以在不同的環境中使用,這樣就降低了硬件要求和應用環境之間耦合度。
(2)、代碼流水線(Code Pipeline)管理
代碼從開發者的機器到最終生產環境上的部署,需要經過很多的中間環境。而每一個中間環境都有微小的差別,Docker 給應用提供了一個從開發到上線均一致的環境,讓代碼的流水線變得簡單不少。
(3)、提高開發效率
Docker 能提升開發者的開發效率。不同的開發環境中,Docker 都可以把兩件事做好,一是可以在開發環境、生產環境之間直接遷移,二是可以讓我們快速搭建開發環境。開發環境的機器通常內存比較小,之前使用虛擬機的時候,我們經常需要為開發環境的機器加內存,而使用Docker可以輕易的讓幾十個服務在Docker中跑起來。
(4)、隔離應用
有很多原因會讓我們選擇在一個機器上運行不同的應用,Docker 非常適合在較低的成本下實現多種應用的隔離。
(5)、整合服務器
Docker 隔離應用的能力使得Docker可以整合多個服務器以降低成本。由於沒有操作系統的內存占用,以及能在多個實例之間共享沒有使用的內存,Docker 可以比虛擬機提供更好的服務器整合解決方案。通常數據中心的服務器資源利用率只有30%,通過使用Docker 並進行有效的資源分配可以大幅度提高服務器資源的利用率。
(6)、調適能力
Docker 提供了很多的工具,包括可以為容器設置檢查點、設置版本和查看兩個容器之間的差別,這些特性可以幫助調試Bug。
(7)、多租戶環境
另外一個Docker 的使用場景是在多租戶的應用中,它可以避免關鍵應用的重寫。我們一個特別的關於這個場景的例子是為物聯網的應用開發一個快速、易用的多租戶環境。這種多租戶的基本代碼非常復雜,很難處理,重新規划這樣一個應用不但消耗時間,也浪費金錢。
使用Docker,可以為每一個租戶的應用層的多個實例創建隔離的環境,這不僅簡單而且成本低廉,當然這一切得益於Docker環境的啟動速度和高效的diff命令。
(8)、快速部署
在虛擬機之前,購入部署新的硬件資源需要消耗幾天的時間。虛擬化技術(Virtualization)將這個時間縮短到了分鍾級別。而Docker 通過為進程僅僅創建一個容器而無需啟動一個操作系統,再次將這個過程縮短到了秒級。這正式Google和Facebook 都看重的特性。我們可以創建銷毀Docker 容器而無需擔心重新啟動帶來的開銷。
Docker 三大核心概念
Docker 包括三個基本概念
- 鏡像(Image)
- 容器(Container)
- 倉庫(Repository)
Docker 鏡像(Image)
Docker 鏡像類似於虛擬機鏡像,可以將它理解為一個只讀的模板。例如,一個鏡像可以包含一個基本的操作系統環境,里面僅安裝了 Apache 應用程序(或用戶需要的其他軟件)。可以把它稱為一個 Apache鏡像。
鏡像是創建Docker 容器的基礎。通過版本管理和增量的文件系統,Docker提供了一套十分簡單的機制來創建和更新現有的鏡像,用戶甚至可以從網上下載一個已經做好的應用鏡像,並直接使用。
Docker 容器(Container)
Docker 容器類似於一個輕量級的沙箱,Docker 利用容器來運行和隔離應用。容器是從鏡像創建的應用運行實例。可以將其啟動、開始、停止、刪除,而這些容器都是彼此相互隔離的、互不相見的。
可以把容器看做是一個簡易版的Linux系統環境(包括root用戶權限、進程空間、用戶空間和網絡空間等)以及運行在其中的應用程序打包而成的盒子
Docker 倉庫(Repository)
Docker 倉庫類似於代碼倉庫,它是Docker集中存放鏡像文件的場所。
倉庫注冊服務器是存放倉庫的地方,其上往往存放着多個地方。每個倉庫集中存放某一類鏡像,往往包括多個鏡像文件,通過不同的標簽(tag)來進行區分。一個倉庫會包含同一個軟件不同版本的鏡像,而標簽就常用於對應改軟件的各個版本。我們可以通過 <倉庫名>:<標簽>的格式來指定具體是這個軟件哪個版本的鏡像。如果不給出標簽,將以 latest 作為默認標簽。以Nginx鏡像為例,nginx 是倉庫的名字,其內包含有不同的版本標簽,如,1.12.2,我們可以通過 nginx:1.12.2來指定需要哪個版本的鏡像。如果忽略了標簽,比如nginx ,那將視為 nginx:latest。
Docker 倉庫可以分為公開倉庫(Public)和私有倉庫(Private)兩種形式。目前最大的公開倉庫是Docker Hub, 存放了數量龐大的鏡像供用戶下載。國內還有(時速雲、阿里雲)等公開倉庫。
當用戶不希望公開自己的鏡像文件,Docker 也支持用戶在本地網絡內創建一個只能自己訪問的私有倉庫。當用戶創建了自己的鏡像之后就可以使用push命令將其上傳到指定的公有或者私有倉庫。這樣下次在另外一台機器上使用該鏡像時,只需要將其從倉庫上pull 下來就可以了。
Docker 實戰
Docker安裝
系統要求
Docker 對CentOS的版本: CentOS 7 (64-bit) CentOS 6.5 (64-bit)或者更高的版本 前提條件: Docker 運行在CentOS 7 上,要求系統為64位、系統內核為3.10以上 Docker 運行在CentOS-6.5 或更高的版本的 CentOS 上,要求系統為64位、系統內核版本為2.6.32-431 或者更高版本。
[root@server ~]# cat /etc/redhat-release # 查看系統版本號 CentOS Linux release 7.3.1611 (Core) [root@server ~]# uname -r # 查看內核 3.10.0-514.el7.x86_64
ps:使用yum直接安裝的是docker version 1.13.1
[root@server ~]# yum -y install docker # 安裝Docker(CentOS7系統CentOS-Extras庫中已帶Docker) [root@server ~]# systemctl start docker # 啟動Docker [root@server ~]# systemctl enable docker # 加入開機自啟動
yum安裝高版本
[root@server ~]# vim /etc/yum.repos.d/docker-ce.repo # 配置yum源 [root@server ~]# yum -y install docker-ce # 安裝docker [root@server ~]# systemctl start docker # 啟動Docker [root@server ~]# systemctl enable docker # 加入開機自啟動

[docker-ce-stable] name=Docker CE Stable - $basearch baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/$basearch/stable enabled=1 gpgcheck=1 gpgkey=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/gpg [docker-ce-stable-debuginfo] name=Docker CE Stable - Debuginfo $basearch baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/debug-$basearch/stable enabled=0 gpgcheck=1 gpgkey=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/gpg [docker-ce-stable-source] name=Docker CE Stable - Sources baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/source/stable enabled=0 gpgcheck=1 gpgkey=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/gpg [docker-ce-edge] name=Docker CE Edge - $basearch baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/$basearch/edge enabled=0 gpgcheck=1 gpgkey=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/gpg [docker-ce-edge-debuginfo] name=Docker CE Edge - Debuginfo $basearch baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/debug-$basearch/edge enabled=0 gpgcheck=1 gpgkey=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/gpg [docker-ce-edge-source] name=Docker CE Edge - Sources baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/source/edge enabled=0 gpgcheck=1 gpgkey=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/gpg [docker-ce-test] name=Docker CE Test - $basearch baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/$basearch/test enabled=0 gpgcheck=1 gpgkey=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/gpg [docker-ce-test-debuginfo] name=Docker CE Test - Debuginfo $basearch baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/debug-$basearch/test enabled=0 gpgcheck=1 gpgkey=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/gpg [docker-ce-test-source] name=Docker CE Test - Sources baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/source/test enabled=0 gpgcheck=1 gpgkey=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/gpg [docker-ce-nightly] name=Docker CE Nightly - $basearch baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/$basearch/nightly enabled=0 gpgcheck=1 gpgkey=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/gpg [docker-ce-nightly-debuginfo] name=Docker CE Nightly - Debuginfo $basearch baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/debug-$basearch/nightly enabled=0 gpgcheck=1 gpgkey=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/gpg [docker-ce-nightly-source] name=Docker CE Nightly - Sources baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/source/nightly enabled=0 gpgcheck=1 gpgkey=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/gpg
[root@server ~]# docker version # 查看docker版本信息 Client: # docker客戶端版本信息 Version: 18.09.0 API version: 1.39 Go version: go1.10.4 Git commit: 4d60db4 Built: Wed Nov 7 00:48:22 2018 OS/Arch: linux/amd64 Experimental: false Server: Docker Engine - Community Engine: # docker服務端版本信息 Version: 18.09.0 API version: 1.39 (minimum version 1.12) Go version: go1.10.4 Git commit: 4d60db4 Built: Wed Nov 7 00:19:08 2018 OS/Arch: linux/amd64 Experimental: false
centos6.x安裝:
[root@linux ~]# cat /etc/redhat-release CentOS release 6.9 (Final) [root@linux ~]# uname -r 2.6.32-696.el6.x86_64 [root@linux ~]# wget https://yum.dockerproject.org/repo/main/centos/6/Packages/docker-engine-1.7.0-1.el6.x86_64.rpm #下載軟件包 [root@linux ~]# yum -y install docker-engine-1.7.0-1.el6.x86_64.rpm #安裝
Docker 基礎命令
[root@docker ~]# docker --help Usage: docker [OPTIONS] COMMAND [arg...] docker daemon [ --help | ... ] docker [ --help | -v | --version ] A self-sufficient runtime for containers. Options: --config string Location of client config files (default "/root/.docker") #客戶端配置文件的位置 -D, --debug=false Enable debug mode #啟用Debug調試模式 -H, --host=[] Daemon socket(s) to connect to #守護進程的套接字(Socket)連接 -h, --help=false Print usage #打印使用 -l, --log-level string Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info") #設置日志級別 --tls Use TLS; implied by --tlsverify --tlscacert string Trust certs signed only by this CA (default "/root/.docker/ca.pem") #信任證書簽名CA --tlscert string Path to TLS certificate file (default "/root/.docker/cert.pem") #TLS證書文件路徑 --tlskey string Path to TLS key file (default "/root/.docker/key.pem") #TLS密鑰文件路徑 --tlsverify Use TLS and verify the remote #使用TLS驗證遠程 -v, --version Print version information and quit #打印版本信息並退出 Commands: attach Attach to a running container #當前shell下attach連接指定運行鏡像 build Build an image from a Dockerfile #通過Dockerfile定制鏡像 commit Create a new image from a container's changes #提交當前容器為新的鏡像 cp Copy files/folders from a container to a HOSTDIR or to STDOUT #從容器中拷貝指定文件或者目錄到宿主機中 create Create a new container #創建一個新的容器,同run 但不啟動容器 diff Inspect changes on a container's filesystem #查看docker容器變化 events Get real time events from the server #從docker服務獲取容器實時事件 exec Run a command in a running container #在已存在的容器上運行命令 export Export a container's filesystem as a tar archive #導出容器的內容流作為一個tar歸檔文件(對應import) history Show the history of an image #展示一個鏡像形成歷史 images List images #列出系統當前鏡像 import Import the contents from a tarball to create a filesystem image #從tar包中的內容創建一個新的文件系統映像(對應export) info Display system-wide information #顯示系統相關信息 inspect Return low-level information on a container or image #查看容器詳細信息 kill Kill a running container #kill指定docker容器 load Load an image from a tar archive or STDIN #從一個tar包中加載一個鏡像(對應save) login Register or log in to a Docker registry #注冊或者登陸一個docker源服務器 logout Log out from a Docker registry #從當前Docker registry退出 logs Fetch the logs of a container #輸出當前容器日志信息 pause Pause all processes within a container #暫停容器 port List port mappings or a specific mapping for the CONTAINER #查看映射端口對應的容器內部源端口 ps List containers #列出容器列表 pull Pull an image or a repository from a registry #從docker鏡像源服務器拉取指定鏡像或者庫鏡像 push Push an image or a repository to a registry #推送指定鏡像或者庫鏡像至docker源服務器 rename Rename a container #重命名容器 restart Restart a running container #重啟運行的容器 rm Remove one or more containers #移除一個或者多個容器 rmi Remove one or more images #移除一個或多個鏡像(無容器使用該鏡像才可以刪除,否則需要刪除相關容器才可以繼續或者-f強制刪除) run Run a command in a new container #創建一個新的容器並運行一個命令 save Save an image(s) to a tar archive #保存一個鏡像為一個tar包(對應load) search Search the Docker Hub for images #在docker hub中搜索鏡像 start Start one or more stopped containers #啟動容器 stats Display a live stream of container(s) resource usage statistics #統計容器使用資源 stop Stop a running container #停止容器 tag Tag an image into a repository #給源中鏡像打標簽 top Display the running processes of a container #查看容器中運行的進程信息 unpause Unpause all processes within a container #取消暫停容器 version Show the Docker version information #查看容器版本號 wait Block until a container stops, then print its exit code #截取容器停止時的退出狀態值 Run 'docker COMMAND --help' for more information on a command. #運行docker命令在幫助可以獲取更多信息
Docker 鏡像管理
搜索鏡像 docker search
[root@server ~]# docker search centos #搜索所有的centos的docker鏡像 NAME(名稱) DESCRIPTION(描述) STARS(下載次數) OFFICIAL(官方) AUTOMATED(自動化) centos The official build of CentOS. 5091 [OK] ansible/centos7-ansible Ansible on Centos7 119 [OK]

docker search 參數說明: --automated=true I false:僅顯示自動創建的鏡像,默認為否; --no-trunc=true | false:輸出信息不截斷顯示,默認為否; -s,--stars=X:指定僅顯示評價為指定星級以上的鏡像,默認為 0,即輸出所有鏡像。 例如,搜索所有自動創建的評價為 3+的帶 nginx 關鍵字的鏡像,如下所示: [root@server ~]# docker search --automated -s 3 nginx
獲取鏡像 docker pull
鏡像是運行容器的前提,官方的Docker Hub 網站已經提供了數十萬個鏡像供我們下載。可以使用Docker pull 從鏡像倉庫拉取鏡像
docker pull
docker pull [選項] [Docker Registry地址]<倉庫名>:<標簽>
[root@server ~]# docker pull centos #獲取centos鏡像 Using default tag: latest latest: Pulling from library/centos a02a4930cb5d: Pull complete Digest: sha256:184e5f35598e333bfa7de10d8fb1cebb5ee4df5bc0f970bf2b1e7c7345136426 Status: Downloaded newer image for centos:latest
# 新版本獲取鏡像 [root@server ~]# docker image pull nginx:1.11
查看鏡像 docker images
[root@server ~]# docker images #查看docker鏡像 REPOSITORY(來自哪個倉庫) TAG(標簽) IMAGE ID(唯一ID) CREATED(創建時間) SIZE(大小) nginx latest 7042885a156a 7 days ago 109MB centos latest 1e1148e4cc2c 4 weeks ago 202MB
# 新版本查看鏡像 [root@server ~]# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 7042885a156a 7 days ago 109MB centos latest 1e1148e4cc2c 4 weeks ago 202MB
列表包括了倉庫名、標簽、鏡像ID、創建時間以及所占用的空間。
鏡像ID則是鏡像的唯一標識,一個鏡像可以對應多個標簽。
刪除鏡像 docker rmi
docker rmi [選項] <鏡像1> [<鏡像2> ...]
使用docker rmi 刪除本地鏡像,后面可以跟鏡像ID或者標簽。(刪除鏡像之前先用docker rm 刪除依賴於這個鏡像的所有容器)。注意docker rm 命令是移除容器。
[root@server ~]# docker rmi imageID/imageName/ # 刪除docker鏡像
導出鏡像 docker save
如果要導出鏡像到本地,提供給另外一台機使用,可以使用docker save 或者docker image save 命令。
[root@server ~]# docker save centos > /tmp/docker_centos.tar #導出docker鏡像到本地 [root@server ~]# ll /tmp/docker_centos.tar -rw-r--r-- 1 root root 210186752 1月 5 16:05 /tmp/docker_centos.tar # 新版本也可用下面這種方法 [root@server ~]# docker image save nginx > /tmp/docker_nginx.tar #導出docker鏡像到本地 [root@server ~]# ll /tmp/docker_nginx.tar -rw-r--r-- 1 root root 190512640 1月 5 16:06 /tmp/docker_nginx.tar
導入鏡像 docker load
從本地文件中導入docker鏡像庫
[root@server ~]# docker load < /tmp/docker_centos.tar #導入本地鏡像到docker鏡像庫 [root@server ~]# docker image load < /tmp/docker_nginx.tar #新版本也可以用這種方法導入 [root@server ~]# docker image ls #查看導入的情況 REPOSITORY TAG IMAGE ID CREATED SIZE centos latest 1e1148e4cc2c 4 weeks ago 202MB nginx 1.11 5766334bdaa0 21 months ago 183MB
給鏡像打標簽 docker tag
利用docker tag可以給鏡像添加一個新的標簽,docker tag 原標簽 新標簽
[root@server ~]# docker image ls #打標簽前查看 REPOSITORY TAG IMAGE ID CREATED SIZE centos latest 1e1148e4cc2c 4 weeks ago 202MB nginx 1.11 5766334bdaa0 21 months ago 183MB [root@server ~]# docker tag centos centos:7.2 #給centos打一個新的標簽 [root@server ~]# docker image tag nginx:1.11 nginx:1.12 #給nginx打一個新的標簽 [root@server ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos 7.2 1e1148e4cc2c 4 weeks ago 202MB centos latest 1e1148e4cc2c 4 weeks ago 202MB nginx 1.11 5766334bdaa0 21 months ago 183MB nginx 1.12 5766334bdaa0 21 months ago 183MB
Docker 容器管理
啟動容器
啟動容器有兩種方式,一種是基於鏡像新建一個容器並啟動,另外一種是將在終止狀態(stopped)的容器重新啟動。
因為Docker的容器實在太輕量級了,很多時候用戶都是隨時刪除和新創建容器。所以主要命令還是docker run
新建容器 docker create
[root@server ~]# docker create -it centos /bin/bash #創建一個容器 a661c9dd447066f326e13389b4e11222f1430e1cbd56ef4c38416fdd51b1394e [root@server ~]# docker ps -a #查看容器狀態,可以看到通過create創建的容器處於停止狀態 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a661c9dd4470 centos "/bin/bash" 39 seconds ago Created angry_wu [root@server ~]# docker start a661c9dd4470 #根據ID啟動上面創建的容器 a661c9dd4470 [root@server ~]# docker ps -a #查看容器狀態,處於運行狀態 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a661c9dd4470 centos "/bin/bash" About a minute ago Up 3 seconds angry_wu [root@server ~]# docker attach a661c9dd4470 #根據ID進入到啟動的容器中 [root@a661c9dd4470 /]# ls anaconda-post.log bin dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var [root@a661c9dd4470 /]# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 08:35 pts/0 00:00:00 /bin/bash root 15 1 0 08:38 pts/0 00:00:00 ps -ef [root@a661c9dd4470 /]# exit #退出容器 exit [root@server ~]#
新建容器並啟動 docker run

-i, --interactive 交互式 -t, --tty 分配一個偽終端 -d, --detach 運行容器到后台 -a, --attach list 附加到運行的容器 --dns list 設置DNS服務器 -e, --env list 設置環境變量 --env-file list 從文件讀取環境變量 -p, --publish list 發布容器端口到主機 -P, --publish-all 發布容器所有EXPOSE的端口到宿主機隨機端口 -h, --hostname string 設置容器主機名 --ip string 指定容器IP,只能用於自定義網絡 --link list 添加連接到另一個容器 --network 連接容器到一個網絡 --mount mount 掛載宿主機分區到容器 -v, --volume list 掛載宿主機目錄到容器 --restart string,容器退出時重啟策略,默認no [always|on-failure] --add-host list 添加其他主機到容器中/etc/hosts -m,--memory 容器可以使用的最大內存量 --memory-swap 允許交換到磁盤的內存量--memory-swappiness=<0-100> 容器使用SWAP分區交換的百分比(0-100,默認為-1) --memory-reservation 內存軟限制,Docker檢測主機容器爭用或內存不足時所激活的軟 限制,使用此選項,值必須設置低於—memory,以使其優先 --oom-kill-disable當宿主機內存不足時,內核會殺死容器中的進程。建議設置了memory選項再禁用OOM。如果沒有設置,主機可能會耗盡內存 --cpus 限制容器可以使用多少可用的CPU資源 --cpuset-cpus 限制容器可以使用特定的CPU --cpu-shares 此值設置為大於或小於默認1024值,以增加或減少容器的權重, 並使其可以訪問主機CPU周期的更大或更小比例
例如,下面的命令輸出一個“Hello World”,之后容器自動終止。
[root@server ~]# docker run centos /bin/echo "Hello World" #這跟在本地直接運行/bin/echo "Hello World" 幾乎感覺不出任何差別 Hello World
啟動一個bash終端,允許用戶進行交互
[root@server ~]# docker run --name mydocker -t -i centos /bin/bash [root@8bad1a6db7b2 /]# pwd / [root@8bad1a6db7b2 /]# ls anaconda-post.log bin dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var --name: 給容器定義一個名稱 -t:讓Docker分配一個偽終端並綁定到容器的標准輸入上 -i:讓容器的標准輸入保持打開 /bin/bash:執行一個命令
當利用docker run 來創建容器時,Docker在后台運行的標准操作包括:
檢查本地是否存在指定的鏡像,不存在就從公有倉庫下載;
利用鏡像創建一個容器,並啟動該容器;
分配一個文件系統給容器,並在只讀的鏡像層外面掛載一層可讀寫層;
從宿主主機配置的網橋接口中橋接一個虛擬接口到容器中;
從網橋的地址池配置一個 IP 地址給容器;
執行用戶指定的應用程序;
執行完畢后容器被自動終止。
啟動已終止的容器 docker start
容器的核心為所執行的應用程序,所需要的資源都是應用程序運行所必需的。除此之外,並沒有其他的資源。可以在偽終端利用 ps 或 top 來查看進程信息
docker ps -a 可以查看所有容器的情況,docker ps 查看已啟動容器的情況
[root@server ~]# docker ps -a #查看所有的容器 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8bad1a6db7b2 centos "/bin/bash" 8 minutes ago Exited (0) About a minute ago mydocker 4d18a48ee315 centos "/bin/bash" 9 minutes ago Exited (0) 9 minutes ago amazing_herschel b3918347393a centos "/bin/echo 'Hello Wo…" 12 minutes ago Exited (0) 12 minutes ago competent_lovelace a661c9dd4470 centos "/bin/bash" 24 minutes ago Exited (0) 20 minutes ago angry_wu [root@server ~]# docker start 8bad1a6db7b2 #啟動一個終止的容器 8bad1a6db7b2 [root@server ~]# docker ps #查看已經啟動的容器 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8bad1a6db7b2 centos "/bin/bash" 8 minutes ago Up 4 seconds mydocker
守護進程運行(后台運行)
更多的時候,需要讓Docker容器在后台運行,而不是直接把執行命令的結果輸出在當前宿主機下。此時可以加 -d 參數來實現。
例如下面的命令會在后台運行容器:
[root@server ~]# docker run -d centos /bin/bash -c "while true; do echo hello world; sleep 1; done" 0ca1770a1fd0b21ae05f2f6bd9befbb9eef55576ab0a0b51fc6dc7e427128174 [root@server ~]# docker ps #查看正在運行的docker容器 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0ca1770a1fd0 centos "/bin/bash -c 'while…" 27 seconds ago Up 25 seconds ecstatic_wu 8bad1a6db7b2 centos "/bin/bash" 18 minutes ago Up 10 minutes mydocker [root@server ~]# docker logs 0ca1770a1fd0 #獲取容器輸出信息,通過docker logs命令 hello world hello world hello world
停止容器
可以使用 docker stop 來終止一個正在運行的容器。
此外,當Docker容器中指定的應用終結時,容器也會自動終結,例如啟動一個終端容器,用戶通過exit命令或者Ctrl+d 來退出終端時,所創建的容器立刻終止。
終止狀態的容器可以用 docker ps -a 命令看到,也可以通過 docker start 命令來重新啟動
[root@server ~]# docker ps -a #查看所有的容器 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0ca1770a1fd0 centos "/bin/bash -c 'while…" 8 minutes ago Up 7 minutes ecstatic_wu 8bad1a6db7b2 centos "/bin/bash" 26 minutes ago Up 17 minutes mydocker [root@server ~]# docker stop 8bad1a6db7b2 #停止容器 8bad1a6db7b2 [root@server ~]# docker stop 0ca1770a1fd0 #停止容器 0ca1770a1fd0 [root@server ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0ca1770a1fd0 centos "/bin/bash -c 'while…" 8 minutes ago Exited (137) 3 seconds ago ecstatic_wu 8bad1a6db7b2 centos "/bin/bash" 27 minutes ago Exited (137) 26 seconds ago mydocker
進入容器
在使用 -d 參數時,容器啟動后會進入后台,某些時候需要進入容器進行操作,有很多種房,包括 docker attach 命令 或者 nsenter 工具 或者 docker exec命令等。
attach 命令
docker attach 是Docker自帶的命令,示例:
[root@server ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8bad1a6db7b2 centos "/bin/bash" 32 minutes ago Exited (137) 5 minutes ago mydocker [root@server ~]# docker start mydocker #啟動已經停止的容器,start可以跟容器ID,也可以是名字 mydocker [root@server ~]# docker attach mydocker #通過docker attach進入容器 [root@8bad1a6db7b2 /]#
但是使用attach命令有時候並不方便,當多個窗口同時 attach 到同一個容器的時候,所有窗口都會同步顯示,當某個窗口因命令阻塞,其他窗口也無法執行操作了。且通過exit退出后容器就自動終止了。
nsenter 命令
nsenter 啟動一個新的shell進程(默認是/bin/bash),同時會把這個新進程切換到和目標(target)進程相同的命名空間,這樣就相當於進入了容器內部。nsenter 要正常工作需要root 權限。
[root@server ~]# yum install -y util-linux #centos自帶yum源有,直接安裝即可 [root@server ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8bad1a6db7b2 centos "/bin/bash" 43 minutes ago Exited (0) 3 minutes ago mydocker [root@server ~]# docker start mydocker #啟動已經關閉的容器 mydocker [root@server ~]# docker inspect -f "{{.State.Pid}}" 8bad1a6db7b2 #找到容器的第一個進程ID,說明:后面跟容器ID,容器名字都可以 21176 [root@server ~]# nsenter -t 21176 -m -u -i -n -p #通過這個PID連接到容器 [root@8bad1a6db7b2 /]# ls anaconda-post.log bin dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var [root@8bad1a6db7b2 /]# pwd / [root@8bad1a6db7b2 /]# exit logout [root@server ~]# docker ps #通過nsenter進入后再退出,我們可以看到容器還是處於后台運行中 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8bad1a6db7b2 centos "/bin/bash" About an hour ago Up 4 minutes mydocker
由於上面兩條命令都太長,不方便,所以我們編寫一個腳本進入,只需在腳本后面跟容器ID或者容器名字即可
[root@server ~]# cat in_docker.sh #!/bin/bash # Use nsenter to access docker docker_in() { NAME_ID=$1 PID=$(docker inspect -f "{{.State.Pid}}" $NAME_ID) nsenter -t $PID -m -u -i -n -p } docker_in $1 [root@server ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8bad1a6db7b2 centos "/bin/bash" About an hour ago Up 10 minutes mydocker [root@server ~]# ./in_docker.sh mydocker #執行腳本加上容器ID快速進入 [root@8bad1a6db7b2 /]#
exec 命令
exec 可以在容器內直接執行任意命令,此處我們也可以使用它進入到容器里面
[root@server ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8bad1a6db7b2 centos "/bin/bash" About an hour ago Up 13 minutes mydocker [root@server ~]# docker exec -it mydocker /bin/bash [root@8bad1a6db7b2 /]# exit exit [root@server ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8bad1a6db7b2 centos "/bin/bash" About an hour ago Up 14 minutes mydocker
導出和導入容器
某些時候,需要將容器從一個系統遷移到另外一個系統,此時可以使用Docker的導入和導出功能。這也是Docker 自身提供的一個重要特性
導出容器
如果要導出本地某個容器,可以使用 docker export 命令,導出容器是指導出一個已經創建的容器到一個文件,不管此時這個容器是否處於運行狀態。export后面跟需要導出的 容器ID 或者 容器名字 都可以
[root@server ~]# docker export mydocker > centos.tar #導出一個容器,也可以使用docker export -o centos.tar mydocker。 -o 指定導出的名字 [root@server ~]# ll centos.tar -rw-r--r-- 1 root root 209473024 1月 5 17:56 centos.tar
導入容器
導出的文件又可以使用 docker import 命令導入變成鏡像,例如
[root@server ~]# cat centos.tar | docker import - test/centos:7.3 sha256:a8375a86d721a718d70dc99a49005d70ce6a7b65423c1bbd1ce34b23ec787aa9 [root@server ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE test/centos 7.3 a8375a86d721 7 seconds ago 202MB
刪除容器
可以使用 docker rm 來刪除一個處於終止狀態的容器。例如
[root@server ~]# docker ps -a #查看所有容器當前狀態 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0ca1770a1fd0 centos "/bin/bash -c 'while…" About an hour ago Exited (137) About an hour ago ecstatic_wu a661c9dd4470 centos "/bin/bash" 2 hours ago Exited (0) 2 hours ago angry_wu [root@server ~]# docker rm a661c9dd4470 #刪除已經停止的容器 a661c9dd4470
如果要刪除一個運行中的容器,可以添加 -f 參數。 Docker會發送 STGKILL信號給容器,再進行刪除。
清理所有處於終止狀態的的容器(慎用)
[root@server ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0ca1770a1fd0 centos "/bin/bash -c 'while…" About an hour ago Exited (137) About an hour ago ecstatic_wu 4d18a48ee315 centos "/bin/bash" About an hour ago Exited (0) About an hour ago amazing_herschel b3918347393a centos "/bin/echo 'Hello Wo…" About an hour ago Exited (0) About an hour ago competent_lovelace [root@server ~]# docker rm $(docker ps -a -q) # 獲取全部容器的ID,進行刪除 0ca1770a1fd0 4d18a48ee315 b3918347393a [root@server ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@server ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Docker 數據管理
Docker 容器中管理數據主要有兩種方式:
- 數據卷(Data volumes)
- 數據卷容器(Data volumes containers)
數據卷
數據卷是一個可供一個或者多個容器使用的特殊目錄,它繞過UFS,可以提供很多有用的特性:
- 數據卷可以在容器之間共享和重用
- 對數據卷的修改會立馬生效
- 對數據卷的更新,不會影響鏡像
- 數據卷默認會一直存在,即時容器被刪除
管理卷 docker volume:
[root@server ~]# docker volume create myvolume #創建一個數據卷 myvolume [root@server ~]# docker volume inspect myvolume #查看數據卷的信息 [ { "CreatedAt": "2019-01-05T22:45:46+08:00", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/myvolume/_data", #可以看到數據卷創建在宿主機的/var/lib/docker/volume目錄下 "Name": "myvolume", "Options": {}, "Scope": "local" } ] [root@server ~]# docker volume ls #查看數據卷列表 DRIVER VOLUME NAME local myvolume
用卷創建一個容器:
[root@server ~]# docker run -d -it --name myCentos --mount src=myvolume,dst=/data centos #創建一個myCentos容器,並將myvolume數據卷掛載到myCentos容器的/data目錄 [root@server ~]# docker exec -it myCentos /bin/bash #進入容器 [root@8f3094a730af /]# ls /data #查看目錄為空 [root@8f3094a730af /]# ls /data #當在另外一個終端創建文件后再次進行查看有文件 test.txt [root@8f3094a730af /]# cat /data/test.txt #查看文件內容 hello world
[root@server ~]# cd /var/lib/docker/volumes/myvolume/_data #在另外一個終端進入到數據目錄里面 [root@server _data]# echo "hello world" >> test.txt #在數據目錄創建一個文件
src:數據卷名字
dst:需要掛載的目錄路徑
注意:如果沒有指定卷,則自動創建。
此時開啟另外一個終端再次創建一個容器,並且掛載同樣的數據卷,可以發現這種方式可以在容器之間共享和重用
[root@server ~]# docker run -d -it --name myCentos01 --mount src=myvolume,dst=/data centos #新開一個終端創建新的一個容器,掛載同樣的數據卷 [root@server ~]# docker exec -it myCentos01 /bin/bash [root@45c3ca27ddad /]# ls /data/ test.txt
上面創建容器並掛載數據卷,還可以使用下面這種方法 -v 數據卷名字:掛載路徑,Docker掛載數據卷默認權限是讀寫,也可以通過 :ro 指定為只讀。
[root@server ~]# docker run -d -it --name myCentos02 -v myvolume:/test:ro centos #創建一個myCentos02的容器,並將數據卷myvolume掛載到容器的/test目錄,並且為只讀模式 [root@server ~]# docker exec -it myCentos02 /bin/bash [root@784f03496b07 /]# ls /test test.txt
刪除數據卷
Docker 不會在容器被刪除后自動刪除數據卷。且如果要刪除數據卷,必須先將使用數據卷的容器停止,刪除后,才能刪除數據卷
[root@server ~]# docker rm myCentos myCentos01 myCentos02 #刪除容器 myCentos myCentos01 myCentos02 [root@server ~]# docker volume rm myvolume #刪除數據卷 myvolume
掛載一個主機目錄作為數據卷
使用 -v 參數也可以指定掛載一個本地主機的目錄到容器中
[root@server ~]# docker run -d -ti --name web -v /webapp:/opt/webapp centos #創建一個名字叫web的容器,並且將宿主機的/webapp目錄 掛載到容器的/opt/webapp目錄 [root@server ~]# ls /webapp/ #查看宿主機的目錄,如果沒有該目錄,會自動創建 [root@server ~]# echo "hello" >> /webapp/index.html #追加一個文件進去 [root@server ~]# docker exec -ti web /bin/bash #進入容器 [root@16c66fe42017 /]# cat /opt/webapp/index.html #查看容器/opt/webapp目錄下的數據 hello
掛載一個宿主機文件作為數據卷
-v 參數也可以從主機掛載單個文件到容器中
[root@server ~]# docker run --rm -it -v ~/.bash_history:/.bash_history centos /bin/bash #創建一個容器,並將宿主機的~./bash_history文件掛載到容器的/.bash_history文件
--rm:創建容器時如果帶上--rm表示容器終止時自動刪除
數據卷容器
如果有一些持續更新的數據需要在容器之間共享,最好創建數據卷容器。
數據卷容器其實就是一個正常的容器,專門用來提供數據卷供其它容器掛載的。
[root@server ~]# docker run -d -v /dbdata --name dbdata centos #創建一個數據卷容器 [root@server ~]# docker run -d -it --volumes-from dbdata --name db1 centos #創建一個db1容器, 使用 --volumes-from 來掛載 dbdata 容器中的數據卷 [root@server ~]# docker exec -it db1 /bin/bash #進入db1容器中 [root@1863842f0c16 /]# ls #查看已成功掛載dbdata數據卷 anaconda-post.log dbdata etc lib media opt root sbin sys usr bin dev home lib64 mnt proc run srv tmp var [root@1863842f0c16 /]# touch dbdata/file1 #在dbdata目錄中創建一個文件
[root@server ~]# docker run -d -it --volumes-from dbdata --name db2 centos #再創建一個db2容器,使用 --volumes-from 來掛載 dbdata 容器中的數據卷 [root@server ~]# docker exec -it db2 /bin/bash #進入db2容器中 [root@0fca0699a7c7 /]# ls #查看也成功掛載dbdata數據卷 anaconda-post.log dbdata etc lib media opt root sbin sys usr bin dev home lib64 mnt proc run srv tmp var [root@0fca0699a7c7 /]# ls dbdata/ #並且還查看到了db1容器創建的file1文件,說明容器之間的數據共享了 file1
從上面可以看出可以使用超過一個 --volumes-from 參數來指定從多個容器掛載不同的數據卷,也可以從其他已經掛載了數據卷的容器來級聯掛載數據卷,示例:
[root@server ~]# docker run -d -ti --name db3 --volumes-from db1 centos #創建一個db3容器,通過 --volumes-from 級聯掛載上面的db1容器 [root@server ~]# docker exec -it db3 /bin/bash #進入db3容器中 [root@1d2d8c30fccf /]# ls #查看也有dbdata目錄 anaconda-post.log dbdata etc lib media opt root sbin sys usr bin dev home lib64 mnt proc run srv tmp var [root@1d2d8c30fccf /]# ls dbdata/ #查看目錄,同樣有文件 file1
注意:使用 --volumes-from 參數所掛載數據卷的容器自己並需要保持在運行狀態。如果刪除了掛載的容器(包括dbdata、db1和db2),數據卷也不會被自動刪除。如果要刪除一個數據卷,必須在刪除最后一個還掛載着它的容器時使用 docker rm -v 命令來指定同時刪除關聯的容器。
Docker 網絡管理
Docker 允許通過外部訪問容器或容器互聯的方式來提供網絡服務。
外部訪問容器
容器中可以運行一些網絡應用,比如(nginx,apache,php等),要讓外部訪問這些應用可以通過 -P 或者 -p 參數來制定端口映射
使用 -P 參數時,Docker 會隨機映射一個 端口到內部容器開放的網絡端口。
[root@server ~]# docker run -d -P --name myNginx nginx:1.11 #創建一個容器,並通過-P隨機映射端口到容器的網絡端口 [root@server ~]# docker ps #查看容器信息,可以發現宿主機的32769端口映射到容器的80端口了,以及32768映射至443端口 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5ee2527dd496 nginx:1.11 "nginx -g 'daemon of…" 42 seconds ago Up 40 seconds 0.0.0.0:32769->80/tcp, 0.0.0.0:32768->443/tcp myNginx [root@server ~]# curl localhost:32769 #訪問宿主機的32769便能訪問到容器 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ...
同樣,可以通過 docker logs 命令查看應用的信息, -f 參數 動態查看
[root@server ~]# docker logs -f myNginx 172.17.0.1 - - [06/Jan/2019:02:25:17 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-" 172.17.0.1 - - [06/Jan/2019:02:38:04 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
-p (小寫的)則可以指定要映射的端口,並且,在一個指定端口上只可以綁定一個容器。格式有:
ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort
映射所有的接口地址
[root@server ~]# docker run -d -p 88:80 --name myNginx01 nginx:1.11 #使用hostPort:containerPort 格式宿主機的88端口映射到容器的80端口,默認會綁定宿主機所有接口上的所有地址 [root@server ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fab763a9ec68 nginx:1.11 "nginx -g 'daemon of…" 50 seconds ago Up 48 seconds 443/tcp, 0.0.0.0:88->80/tcp myNginx01
映射到指定地址的指定端口
[root@server ~]# docker run -d -p 127.0.0.1:89:80 --name myNginx02 nginx:1.11 #使用ip:hostPort:containerPort 格式指定映射使用一個特定地址,如localhost地址127.0.0.1 913f0cad940155978825b40f8e4c2bf23a4872bbd06e441ced4b8043b72c683e [root@server ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 913f0cad9401 nginx:1.11 "nginx -g 'daemon of…" 6 seconds ago Up 5 seconds 443/tcp, 127.0.0.1:89->80/tcp myNginx02
映射到指定地址的任意端口
[root@server ~]# docker run -d -p 127.0.0.1::80 --name myNginx03 nginx:1.11 #使用ip:containerPort 綁定localhost的任意端口到容器的80端口,宿主機會自動分配一個端口 [root@server ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 16b17ccf83cf nginx:1.11 "nginx -g 'daemon of…" 4 seconds ago Up 3 seconds 443/tcp, 127.0.0.1:32770->80/tcp myNginx03
還可以使用 udp 標記來指定 udp 端口
[root@server ~]# docker run -d -p 127.0.0.1:82:80/udp --name myNginx04 nginx:1.11 #將localhost的82端口映射到容器的80端口,並指定udp [root@server ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 79d14927ef84 nginx:1.11 "nginx -g 'daemon of…" 4 seconds ago Up 2 seconds 80/tcp, 443/tcp, 127.0.0.1:82->80/udp myNginx04
查看映射端口配置
使用 docker port 查看當前映射的端口配置,也可以查看到綁定的地址
[root@server ~]# docker port myNginx 443/tcp -> 0.0.0.0:32768 80/tcp -> 0.0.0.0:32769 [root@server ~]# docker port myNginx01 80/tcp -> 0.0.0.0:88
注意:
- 容器有自己內部網絡地址和ip地址(使用 docker inspect 可以獲取所有變量,Docker 還可以有一個可變的網絡配置)
- -p 標記可以多次使用來綁定多個端口
例如
[root@server ~]# docker run -d --name myNginx05 -p 8088:80 -p 8089:443 nginx:1.11 #將宿主機的8088和8089端口分別映射到容器的80/443端口 [root@server ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f0f18691e88e nginx:1.11 "nginx -g 'daemon of…" 4 seconds ago Up 3 seconds 0.0.0.0:8088->80/tcp, 0.0.0.0:8089->443/tcp myNginx05
容器互聯
容器的連接(linking)系統除了端口映射外,另一種是容器中應用交互的方式。該系統會在源和接收容器之間創建一個隧道,接受容器可以看到源容器指定的信息。
使用 --link 參數可以讓容器之間安全的進行交互
[root@server ~]# docker run -e MYSQL_ROOT_PASSWORD=123456 -d --name myDB mysql #先創建一個新的數據庫容器 [root@server ~]# docker run -d -P --name myWeb --link myDB:db nginx:1.11 #再創建一個web容器,並將它連接到 myDB 數據庫容器 [root@server ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 28bcc258fc47 nginx:1.11 "nginx -g 'daemon of…" 37 seconds ago Up 34 seconds 0.0.0.0:32771->80/tcp, 0.0.0.0:32770->443/tcp myWeb 49a6b11e2178 mysql "docker-entrypoint.s…" About a minute ago Up About a minute 3306/tcp, 33060/tcp myDB
此時,myDB 容器和 myWeb 容器建立互聯關系。
--link 參數的格式: --link name:alias
name:是要鏈接的容器的名稱,
alias:是這個鏈接的別名
Docker 在兩個互聯的容器之間創建了一個安全的隧道,而且不用映射它們的端口到宿主機上,在啟動myDB 容器時候沒有使用 -p 和 -P 參數,從而避免了暴露數據庫端口到外部網絡上。
Docker 通過2種方式為容器公開連接信息:
- 環境變量
- 更新 /etc/hosts 文件
使用 env 命令可以查看環境變量
[root@server ~]# docker run --rm --name myWeb1 --link myDB:DB nginx:1.11 env #創建一個web容器連接到上面的myDB,查看web容器的環境變量... DB_PORT=tcp://172.17.0.2:3306 DB_PORT_3306_TCP=tcp://172.17.0.2:3306 DB_PORT_3306_TCP_ADDR=172.17.0.2 DB_PORT_3306_TCP_PORT=3306 DB_PORT_3306_TCP_PROTO=tcp DB_PORT_33060_TCP=tcp://172.17.0.2:33060 DB_PORT_33060_TCP_ADDR=172.17.0.2 DB_PORT_33060_TCP_PORT=33060 DB_PORT_33060_TCP_PROTO=tcp DB_NAME=/myWeb1/DB DB_ENV_MYSQL_ROOT_PASSWORD=123456
其中DB_開頭的環境變量是供web容器連接 DB 容器使用的。可以看到連接容器的協議,端口,密碼等
除了環境變量,Docker 還添加host信息到父容器的 /etc/hosts 的文件:
[root@server ~]# docker run --rm -ti --name myWeb2 --link myDB:DB nginx:1.11 /bin/bash #創建一個web容器,同樣連接到myDB容器 root@9397b6ca77bd:/# cat /etc/hosts #查看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 49a6b11e2178 myDB 172.17.0.4 9397b6ca77bd root@9397b6ca77bd:/# ping myDB PING DB (172.17.0.2): 56 data bytes 64 bytes from 172.17.0.2: icmp_seq=0 ttl=64 time=0.142 ms
可以看到這里有2個hosts,第一個是 web 容器,web容器用id作為他的主機名,第二個是 DB 容器的 ip 和主機名。可以在web 容器中使用ping命令來測試跟 DB 容器的連通。
更多docker 高級網絡配置參考:https://www.cnblogs.com/yanjieli/articles/10229623.html
未完待續...