1、Docker 架構
http://blog.csdn.net/u012562943/article/category/6048991/1
Docker 使用客戶端-服務器 (C/S) 架構模式,使用遠程API來管理和創建Docker容器。
Docker 容器通過 Docker 鏡像來創建。
容器與鏡像的關系類似於面向對象編程中的對象與類。
Docker 面向對象
容器 對象
鏡像 類
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項目的目標是實現輕量級的操作系統虛擬化解決方案。Docker的基礎是linux容器(LXC)等技術。
2、Docker的概念,安裝及鏡像管理
2.1、docker的概念:
鏡像:是一個只讀的模板,類似於安裝系統用到的那個iso文件,我們通過鏡像來完成各種應用的部署。鏡像可以用來創建Docker容器
容器:鏡像類似於操作系統,而容器類似於虛擬機本身。它可以被啟動、開始、停止、刪除等操作,每個容器都是相互隔離的。可以把容器看做是一個簡易版的linux環境(包括root用戶權限、進程空間、用戶空間和網絡空間等)和運行在其中的應用程序。
倉庫:存放鏡像的一個場所,倉庫分為公開倉庫和私有倉庫。 最大的公開倉庫是Docker hub(hub.docker.com),國內公開倉庫(dockerpool.com)
2.2、docker安裝啟動:
yum install -y epel-release yum instal -y docker systemctl enable docker.service systemctl start docker
2.3、鏡像管理
2.3.1、獲取鏡像
語法:docker pull NAME[:TAG]
其中,NAME是鏡像倉庫的名稱(用來區分鏡像),TAG是鏡像的標簽(用來表示版本信息)
docker pull centos:從docker.com獲取centos鏡像
2.3.2、查看鏡像
語法:docker images [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/nginx latest b175e7467d66 2 days ago 109 MB
docker tag centos long:為centos鏡像設置標簽為long,再使用docker images查看會多出來一行,打了標簽的image id和centos的一樣 [root@localhost ~]# docker tag nginx nginx_1.12.2 [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/nginx latest b175e7467d66 2 days ago 109 MB nginx_1.12.2 latest b175e7467d66 2 days ago 109 MB docker inspect {IMAGE_ID | IMAGE_NAME}:獲取鏡像詳細信息 [root@localhost ~]# docker inspect nginx 返回的是一個JSON格式的消息,如果我們只要其中一項內容時,可以使用參數-f來指定,例如,獲取鏡像的Architecture [root@localhost ~]# docker inspect -f {{".Architecture"}} nginx amd64
2.3.3、搜索鏡像
docker search [image-name]:從docker倉庫搜索docker鏡像,后面是關鍵詞
[root@localhost ~]# docker search nginx
2.3.4、刪除鏡像
docker rmi centos:用來刪除指定鏡像, 其中后面的參數可以是tag,如果是tag時,實際上是刪除該tag,只要該鏡像還有其他tag,就不會刪除該鏡像。當后面的參數為鏡像ID時,則會徹底刪除整個鏡像,連通所有標簽一同刪除 [root@localhost ~]# docker rmi nginx_1111 Untagged: nginx_1111:latest Untagged: docker.io/nginx@sha256:37350fbb4afbb1c01b6e542fe1537dd701e4430983d6d9c673cbb5eccdbec357 docker rmi -f centos:強制刪除,一般不建議使用,會導致某些問題 [root@localhost ~]# docker rmi -f nginx_1111 Untagged: nginx_1111:latest
2.3.5、創建鏡像
創建鏡像的方法有以下3種方式:
(1)基於已有鏡像的容器創建
(2)基於本地模板導入
(3)基於Dockerfile創建
(1)基於已有鏡像的容器創建
命令格式:docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] 主要選項: -a:作者信息 -m:提交消息 -p:提交時暫停容器運行 運行docker run后,進入到該容器中,我們做一些變更,比如安裝一些東西,然后針對這個容器進行創建新的鏡像
[root@localhost ~]# docker ps -a //查看所有的容器 [root@localhost ~]# docker start 67d //啟動ID為67d的容器,ID可簡寫為前3位 [root@localhost ~]# docker exec -it 67d /bin/bash //進入67d容器 [root@67dde53e0651 /]# yum install -y net-tools wget [root@67dde53e0651 /]# exit [root@localhost ~]# docker commit -m "centos_with_nettools_wget" -a "long" 67d centos_with_net //創建新的鏡像 sha256:90f2a945a44d466c8a8d46dcdd4ab80f9f2aab79761482a1b5839d9ea2cf7904 tips:這個命令有點像svn的提交,-m 加一些改動信息,-a 指定作者相關信息 67d這一串為容器id,再后面為新鏡像的名字 [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos_with_net latest 90f2a945a44d 32 seconds ago 300.6MB docker.io/centos latest 328edcd84f1b 11 days ago 192.5MB long long 328edcd84f1b 11 days ago 192.5MB
(2)基於本地模板導入 模塊獲取,可以直接在網上下載一個模塊
[root@izwz920g719hydx1spem46z ~]# wget https://download.openvz.org/template/precreated/contrib/centos-7-x86_64-minimal-20170709.tar.xz http://openvz.org/Download/templates/precreated 可惜速度並不快,若我們下載了一個centos的模板 centos-7-x86_64-minimal-20170709.tar.xz那么導入該鏡像的命令為: cat centos-7-x86_64-minimal-20170709.tar.xz |docker import - centos-5-x86
2.3.6、存出和載入鏡像以及上傳鏡像
docker save -o ***.tar IMAGE:TAG docker load --input ***.tar 或 dokcer load < ***.tar docker push IMAGE_NAME 把現有鏡像,導出為一個文件,可以作為備份: docker save -o long.tar long:long 我們還可以用該文件恢復本地鏡像: docker load --input long.tar 或者 docker load < long.tar docker push image_name //可以把自己的鏡像傳到dockerhub官方網站上去,但前提是需要先注冊一個用戶,后續如果有需求再研究吧
3、操作Docker容器
3.1、創建容器
當使用docker run來創建並啟動容器時,Docker在后台運行的標准操作:
(1)檢查本地是否存在指定的鏡像centos,不存在就從公有倉庫下載
(2)利用鏡像創建並啟動一個容器
(3)分配一個文件系統,並在只讀的鏡像層外面掛載一層可讀寫層
(4)從宿主主機配置的橋接網絡接口中橋接一個虛擬接口到容器中去
(5)從地址池配置一個IP地址給容器
(6)執行用戶指定的應用程序
(7)執行完畢后,容器被終止
語法: 創建容器:docker create -it {image_name} docker create命令新建的容器處於停止狀態,可以使用docker start命令來啟動它。 啟動容器:docker start {container_id} 新建並啟動容器:docker run -t -i centos /bin/bash 用下載到的鏡像開啟容器,-i表示讓容器的標准輸入打開,-t表示分配一個偽終端,要把-i -t 放到鏡像名字前面 [root@localhost ~]# docker run -t -i nginx /bin/bash root@c1eff06c8501:/# 守護態運行容器:docker run -itd centos /bin/bash
3.2、終止容器
可以使用docker stop來終止一個運行中的容器,改命令的格式為docker stoop [container]
首先向容器發送SIGTERM信號,等待一段超時時間(默認為10s)后,再發送SIGKILL信號來終止容器docker kill
命令會直接發送SIGKILL信號來強行終止容器
[root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 402e1bd8ff16 centos "/bin/bash" 16 hours ago Up 16 hours mynginx [root@localhost ~]# docker stop mynginx mynginx
3.3、進入容器
進入容器有以下3種方法:
(1)attach命令
(2)exec命令(推薦方式)
(3)nsenter工具
(1)attach命令 [root@localhost ~]# docker attach mynginx [root@402e1bd8ff16 /]# 注意:使用attach命令有時候並不方便,當多個窗口同時使用attach命令鏈接到同一個容器的時候,所有窗口都會同步顯示。當某個窗口因命令阻塞時,其他窗口也無法進行操作。
(2)exec命令(推薦方式) [root@localhost ~]# docker exec -it mynginx /bin/bash [root@402e1bd8ff16 /]#
(3)nsenter工具 [root@localhost ~]# yum install -y util-linux #安裝nsenter工具 為了使nsenter鏈接到容器,還需要找到容器進程的PID,可以通過以下命令獲取 PID=$(docker inspect --format "{{.State.Pid}}" <container>) 通過這個pid就可以連接到這個容器 nsenter -t $PID -u -i -n -p 一般情況下,將這個工具寫成一個腳本更方便: [root@localhost ~]# cat ns.sh #!/bin/bash PID=`docker inspect --format "{{.State.Pid}}" $1` nsenter -t $PID -u -i -n -p [root@localhost ~]# ./ns.sh mynginx [root@402e1bd8ff16 ~]#
3.4、刪除容器
可以使用docker rm 命令來刪除處於終止或退出狀態的容器,命令格式為docker rm <container>
默認情況下,docker rm 只能刪除處於終止或退出狀態的容器,並不能刪除還處於運行狀態的容器。如果需要直接刪除一個運行中的容器,可以添加-f參數。Docker會先發送SIGKILL信號給容器,終止其中的應用,之后強行刪除。
選項:-f:
強行終止並刪除在運行的一個容器-l:
刪除容器的鏈接,但保留容器-v:
刪除容器掛載的數據卷
[root@localhost ~]# docker rm nginx2 nginx2
3.5、導入和導出容器
導出容器是指導出一個已經創建的容器到一個文件,不管此時這個容器是否處於運行狀態,可以使用docker export命令 格式為:docker export CONTAINER_ID docker export container_id > file.tar // 導出容器,可以遷移到其他機器上,需要導入 舉例: [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c40ae00fd190 centos_1 "bash" 14 hours ago Up 14 hours 0.0.0.0:82->80/tcp mad_yonath 84acb55af1f9 nginx "bash" 14 hours ago Up 14 hours 0.0.0.0:81->80/tcp prickly_montalcini [root@localhost ~]# docker export 84acb55af1f9 > file.tar 導出的文件file.tar又可以使用docker import 命令導入,成為鏡像 格式:cat ***.tar |docker import - IMAGENAME:TAG [root@localhost ~]# cat /tmp/mynginx.tar |docker import - test/nginx:v1 sha256:f133989eba3b11f0b81e6976421f9510a94d8692cceb7505c4d98029870cd110 [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE test/nginx v1 f133989eba3b 3 seconds ago 199 MB
3.6、docker的基礎命令
[root@localhost ~]# docker -h Flag shorthand -h has been deprecated, please use --help Usage: docker COMMAND A self-sufficient runtime for containers Options: --config string Location of client config files (default "/root/.docker") #客戶端配置文件的位置 -D, --debug Enable debug mode #啟用Debug調試模式 --help Print usage #查看幫助信息 -H, --host list Daemon socket(s) to connect to (default []) #守護進程的套接字(Socket)連接 -l, --log-level string Set the logging level ("debug", "info", "warn", "error", "fatal") (default "info") #設置日志級別 -v, --version Print version information and quit #打印版本信息並退出 Commands: attach Attach to a running container #進入一個正在運行的容器 build Build an image from a Dockerfile #通過Dockerfile創建鏡像 commit Create a new image from a container's changes #提交當前容器為一個新的鏡像 cp Copy files/folders between a container and the local filesystem #從容器中拷貝指定文件或者目錄到宿主機中 create Create a new container #創建一個新的容器 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歸檔文件 history Show the history of an image #展示一個鏡像形成歷史 images List images #列出系統當前鏡像 import Import the contents from a tarball to create a filesystem image #導入一個鏡像 info Display system-wide information #顯示系統信息 inspect Return low-level information on Docker objects #查看容器詳細信息 kill Kill one or more running containers #kill指定docker容器 load Load an image from a tar archive or STDIN #從一個tar包中加載一個鏡像(對應save) login 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 one or more containers #暫停容器 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 one or more containers #重啟運行的容器 rm Remove one or more containers #移除一個或者多個容器 rmi Remove one or more images #移除一個或者多個鏡像 run Run a command in a new container #創建一個新的容器並運行一個命令 save Save one or more images to a tar archive (streamed to STDOUT by default) 保存一個鏡像為一個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 one or more running containers #停止容器 tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE #給源中鏡像打標簽 top Display the running processes of a container #查看容器中運行的進程信息 unpause Unpause all processes within one or more containers #取消暫停容器 update Update configuration of one or more containers #更新一個或多個容器的配置信息 version Show the Docker version information #查看容器版本號 wait Block until one or more containers stop, then print their exit codes #截取容器停止時的退出狀態值 Run 'docker COMMAND --help' for more information on a command. #運行docker命令在幫助可以獲取更多信息
4、訪問Docker倉庫
4.1、解析Docker 倉庫
倉庫(Repository)是集中存放鏡像的地方。
一個容易混淆的的概念是注冊服務器(Registry
)。實際上注冊服務器是存放倉庫的具體服務器,每個服務器上都有很多個倉庫,而每個倉庫下面都有多個鏡像。從這方面來說,倉庫可以認為是一個具體的項目或目錄。例如對於倉庫地址dl.dockerpool.com/centos
來說,dl.dockerpool.com
是注冊服務器地址,centos
是倉庫名。
倉庫又分為公有倉庫(public)和私有倉庫(private)
4.2、創建和使用私有倉庫
使用registry鏡像來創建私有倉庫:
docker pull registry
//以registry鏡像啟動容器,-p會把容器的端口映射到宿主機上,:左邊為宿主機監聽端口,:右邊為容器監聽端口[root@localhost ~]# docker run -d -p 5000:5000 registry #這里將自動下載registry鏡像並啟動容器,創建本地私有倉庫。 Unable to find image 'registry:latest' locally Trying to pull repository docker.io/library/registry ... latest: Pulling from docker.io/library/registry 49388a8c9c86: Pull complete e4d43608dd22: Pull complete 3a41740f900c: Pull complete e16ef4b76684: Pull complete 65f212f7c778: Pull complete Digest: sha256:d837de65fd9bdb81d74055f1dc9cc9154ad5d8d5328f42f57f273000c402c76d c9bba59aa7ce072b888ca8214a76211bf03cf9d3bcb55d2183183b876683f33f [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c9bba59aa7ce registry "/entrypoint.sh /etc/" About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp sick_wozniak默認的情況下,會將倉庫創建在容器的
/tmp/registry
目錄下,可以通過-v參數來將鏡像文件存放在本地的指定路徑上。[root@localhost ~]# mkdir -p /opt/data/registry [root@localhost ~]# docker run -d -p 5000:5000 -v /opt/data/registry:/tmp/registry registry [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE test/nginx 1.10.1 def358072817 3 hours ago 106.7 MB [root@localhost ~]# docker tag test/nginx:1.10.1 192.168.0.134:5000/test2 //標記一下tag,必須帶有私有倉庫的ip:port [root@localhost ~]# docker push 192.168.0.134:5000/test2 Get https://192.168.0.165:5000/v2/: http: server gave HTTP response to HTTPS client tips:由於客戶端采用https,docker registry未采用https服務所致。<br/>處理方法:更改配置文件:/etc/docker/daemon.json [root@localhost ~]# vim /etc/docker/daemon.json {"insecure-registries":["192.168.0.134:5000"]} 修改完配置文件需要進行重啟docker [root@localhost ~]# systemctl restart docker docker重啟后,原先運行的容器會停止掉,需要重新開啟容器 [root@localhost ~]# docker run -d -p 5000:5000 -v /opt/data/registry:/tmp/registry registry [root@localhost ~]# docker push 192.168.0.134:5000/test2 The push refers to a repository [192.168.0.134:5000/test2] c4c704007df5: Pushed latest: digest: sha256:2fa255d11989458a1f9d3173e36a911c5f40c0ba1d74b16608a27ba52fa9237a size: 528 [root@localhost ~]# curl http://192.168.0.134:5000/v2/_catalog {"repositories":["test2"]} 在第二台機器(192.168.0.136)上進行驗證私有倉庫是否可用 [root@backup ~]# yum install -y docker [root@backup ~]# systemctl start docker [root@backup ~]# curl http://192.168.0.134:5000/v2/_catalog {"repositories":["test2"]} [root@backup ~]# docker pull 192.168.0.134:5000/test2 Using default tag: latest Trying to pull repository 192.168.0.134:5000/test2 ... Get https://192.168.0.165:5000/v1/_ping: http: server gave HTTP response to HTTPS client 出現在docker私有倉庫一樣的錯誤,於是同樣修改配置文件 [root@backup ~]# vim /etc/docker/daemon.json {"insecure-registries":["192.168.0.134:5000"]} [root@backup ~]# systemctl restart docker [root@backup ~]# docker pull 192.168.0.134:5000/test2 Using default tag: latest Trying to pull repository 192.168.0.134:5000/test2 ... latest: Pulling from 192.168.0.134:5000/test2 9ff86f02c57e: Pull complete Digest: sha256:2fa255d11989458a1f9d3173e36a911c5f40c0ba1d74b16608a27ba52fa9237a [root@backup ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE 192.168.0.165:5000/test2 latest def358072817 Less than a second ago 106.7 MB 小結: 倉庫概念的引入,為Docker鏡像文件的分發和管理提供了便捷的途徑,在企業生產環境中,則往往需要使用私有倉庫來維護內部鏡像。5、Docker數據管理
用戶在使用Docker的過程中,往往需要能查看容器內應用產生的數據,或者需要把容器內的數據進行備份,甚至多個容器之間進行數據共享,這必然涉及到容器的數據管理操作。
容器中管理數據主要有兩種方式:
(1)數據卷(Data Volumes
)
(2)數據卷容器(Data Volumes Dontainers
)5.1、數據卷
數據卷可以是一個可供容器使用的特殊目錄。
a.
數據卷可以在容器中共享和重用b.
對數據卷修改會立馬生效c.
對數據卷更新,不會影響鏡像d.
卷會一直存在,直到沒有容器使用
數據卷的使用,類似於Linux下對目錄或文件進行mount操作
在容器內創建一個數據卷
在使用docker run
命令的時候,使用-v
標記可以在容器內創建一個數據卷,多次使用-v
標記,可以創建多個數據卷。使用-v標記也可以指定本地的已有的目錄到容器中作為數據卷。也就是映射宿主機目錄到容器中去。這個功能在測試的時候十分方便,比如用戶可以放置一些程序或數據到本地目錄,然后再容器中運行和使用。另外,本地目錄的路徑必須是絕對路徑,如果目錄不存在,Docker會自行創建。
Docker掛載數據卷的默認權限是rw
,用戶也可以通過指定權限,ro
指定可讀:docker run -itd -P --name web2 -v /data:/data:ro centos_nginx:1.10 bash
同時,也可以掛載本地主機的一個文件作為數據卷docker run -it --rm -P --name web2 -v ~/.bash_history:/.bash_history centos_nginx:1.10 bash
5.2、掛載本地的目錄到容器里
(1)查看本地鏡像 [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos_nginx 1.10 3cdab9e3fdbb 19 hours ago 361.6 MB centos_nginx latest 3cdab9e3fdbb 19 hours ago 361.6 MB (2)創建容器,並將本地/data目錄映射到容器中 [root@localhost ~]# docker run -itd -P --name web2 -v /data:/data centos_nginx:1.10 bash 52babe20009cb2366ebe0a9e3633140bcaa2d92e2057c56e47b8377960f43d62 //-v 用來指定掛載目錄,:前面的/data/為宿主機本地目錄,:后面的/data/為容器里的目錄,會在容器中自動創建 [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 52babe20009c centos_nginx:1.10 "bash" 3 seconds ago Up 3 seconds 0.0.0.0:32771->80/tcp web2 (3)在數據卷目錄中創建目錄123 [root@localhost ~]# docker exec -it 52babe20009c bash [root@52babe20009c /]# mkdir /data/123 [root@52babe20009c /]# ll /data/ total 24 drwxr-xr-x 2 root root 4096 Nov 12 07:06 123 drwxr-xr-x 5 1003 1003 4096 Sep 30 03:17 logs drwxr-xr-x 8 1003 1003 4096 Oct 19 04:16 mysql drwxr-xr-x 3 1003 1003 4096 Sep 30 03:18 nginx drwxr-xr-x 2 1003 1003 4096 Oct 1 13:01 oldboy drwxr-xr-x 2 1003 1003 4096 Sep 30 03:17 web (4)宿主機查看目錄變化 [root@localhost ~]# ll /data/ total 24 drwxr-xr-x 2 root root 4096 Nov 12 02:06 123 drwxr-xr-x 5 mysql mysql 4096 Sep 29 23:17 logs drwxr-xr-x 8 mysql mysql 4096 Oct 19 00:16 mysql drwxr-xr-x 3 mysql mysql 4096 Sep 29 23:18 nginx drwxr-xr-x 2 mysql mysql 4096 Oct 1 09:01 oldboy drwxr-xr-x 2 mysql mysql 4096 Sep 29 23:17 web5.3、數據卷容器
如果用戶需要在容器之間共享一些持續更新的數據,最簡單的方式是試用數據卷容器。數據卷容器其實就是一個普通的容器,專門用它來提供數據卷供其他容器掛載使用。
(1)首先創建一個數據卷容器
dbdata
,並在其中創建一個數據卷掛載到/dbdata
[root@localhost ~]# docker run -it -v /dbdata --name dbdata centos
tips:這里的/dbdata是容器里的/dbdata目錄,並非宿主機本地的目錄(2)查看
/dbdata
目錄,並創建文件[root@8ee4460dccae /]# ls anaconda-post.log bin dbdata dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var [root@8ee4460dccae /]# touch /dbdata/long.txt [root@8ee4460dccae /]# ll /dbdata/ total 0 -rw-r--r-- 1 root root 0 Nov 12 07:12 long.txt [root@8ee4460dccae /]# exit(3)通過
--volumes-from
來掛載dbdata
容器中的數據卷,例如創建一個db1
容器,並從dbdata
容器掛載數據卷[root@localhost ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8ee4460dccae centos "/bin/bash" 2 minutes ago Exited (0) About a minute ago dbdata [root@localhost ~]# docker run -it --volumes-from dbdata --name db1 centos bash(4)查看db1容器是否存在
/dbdata
目錄,並在該目錄下創建long2.txt
文件[root@ee0f12d8023b /]# ll /dbdata/ total 0 -rw-r--r-- 1 root root 0 Nov 12 07:12 long.txt [root@ee0f12d8023b /]# touch /dbdata/long2.txt [root@ee0f12d8023b /]# exit(5)進入
dbdata
容器查看是否有long2.txt
[root@localhost ~]# docker exec -it 8ee4460dccae bash [root@8ee4460dccae /]# ll /dbdata/ total 0 -rw-r--r-- 1 root root 0 Nov 12 07:12 long.txt -rw-r--r-- 1 root root 0 Nov 12 07:15 long2.txt(6)多次使用
--volumes-from
參數來從多個容器掛載多個數據卷[root@localhost ~]# docker run -itd --name db5 --volumes-from db1 --volumes-from db4 centos bash 9513d4c30a85601b8d0939e4b58e24697df6417fb0b82a5eb5dfc42ed729cc7b [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9513d4c30a85 centos "bash" 5 seconds ago Up 3 seconds db5 72ae1898a04d centos "bash" 56 seconds ago Up 55 seconds db4 ee0f12d8023b centos "/bin/bash" 51 minutes ago Up 50 minutes db1 [root@localhost ~]# docker exec -it db5 bash [root@9513d4c30a85 /]# ls anaconda-post.log bin dbdata dbdata4 dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var(7)還可以從其他已經掛載了容器卷的容器來掛載容器卷:
[root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ee0f12d8023b centos "/bin/bash" 47 minutes ago Up 46 minutes db1 8ee4460dccae centos "/bin/bash" 49 minutes ago Up 45 minutes dbdata [root@localhost ~]# docker run -it --name db2 --volumes-from db1 centos bash [root@701a34da1cde /]# ll /dbdata/ total 0 -rw-r--r-- 1 root root 0 Nov 12 07:12 long.txt -rw-r--r-- 1 root root 0 Nov 12 07:15 long2.txt
tips:使用--volumes-from參數所掛載數據卷的容器自身並不需要保持在運行狀態,如果刪除了掛載的容器(包括dbdata,db1,db2),數據卷並不會被自動刪除,
如果要刪除一個數據卷,必須在刪除最后一個還掛載着它的容器時顯示使用docker rm -v 命令來指定刪除關聯的容器(1)停止
db4
容器並刪除[root@localhost ~]# docker stop db4 db4 [root@localhost ~]# docker rm db4 db4(2)進入
db5
容器查看數據卷dbdata4
是否存在[root@localhost ~]# docker exec -it db5 bash [root@9513d4c30a85 /]# ls anaconda-post.log bin dbdata dbdata4 dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var5.4、利用數據卷容器遷移數據
可以利用數據卷容器對其中的數據卷進行備份,恢復,以實現數據的遷移。 (1)備份 [root@localhost ~]# docker run --volumes-from dbdata -v /backup:/backup --name work centos tar cvf /backup/backup.tar /dbdata tar: Removing leading `/' from member names /dbdata/ /dbdata/long.txt /dbdata/long2.txt [root@localhost ~]# ll /backup/ -rw-r--r-- 1 root root 10240 Nov 12 03:30 backup.tar 說明:首先利用centos鏡像創建了一個容器work,使用--volumes-from dbdata參數來讓容器掛載dbdata容器的數據卷(即dbdata數據卷);
-v /backup:/backup參數來將本地的備份目錄(/backup)掛載到work容器的/backup目錄。work容器啟動后,使用了tar cvf /backup/backup.tar /dbdata命令來將/dbdata下的內容備份為容器內的/backup/backup.tar,
即宿主機/backup目錄下的/backup/backup.tar (2)恢復 [root@localhost ~]# docker run -itd -v /dbdata --name db6 centos bash bb0357aba6fcee546eda5903f40cf61b3fd46a4ad9e0962e55550caaea10e06c [root@localhost ~]# docker run --volumes-from db6 -v /backup:/backup --name db7 centos tar xvf /backup/backup.tar dbdata/ dbdata/long.txt dbdata/long2.txt [root@localhost ~]# docker exec -it db6 bash [root@bb0357aba6fc /]# ll /dbdata/ total 0 -rw-r--r-- 1 root root 0 Nov 12 07:12 long.txt -rw-r--r-- 1 root root 0 Nov 12 07:15 long2.txt
說明:首先利用centos鏡像新建一個db6的容器,然后通過--volumes-from參數掛載db6容器的數據卷(/dbdata)新建容器,
並將本地的/backup目錄映射到db7容器中。而后對/backup/backup.tar進行解壓到/dbdata目錄下,從而實現db6恢復/dbdata數據 小結: 在生產環境中,在使用數據卷或者數據卷容器之外,定期將宿主機的本地數據進行備份,或者使用支持容錯的存儲系統,包括RAID或分布式文件系統。6、端口映射和容器互聯
6.1、端口映射,實現外部訪問
在啟動容器的時候,如果不指定對應的參數,在容器外部是無法通過網絡進行訪問容器內的應用和服務的。當容器中運行一些網絡應用,要讓外部訪問這些應用,可以通過
-P
或-p
參數來指定端口映射。當使用-P標記時,Docker會隨機映射一個49000~49900
的端口至容器內部開放的網絡端口。
端口映射的方式:(1)映射所有接口地址 使用hostPort:containerPort格式,將本地的5000端口映射到容器的5000端口,可以執行以下命令: docker run -d -p 5000:5000 centos_nginx bash 此時默認會綁定本地所有接口上的所有地址。多次使用-p標記可以綁定多個端口。例如: docker run -d -p 5000:5000 -p 8082:80 centos_nginx bash (2)映射到指定地址的指定端口 可以使用ip:hostPort:containerPort格式指定映射一個特定的地址,例如localhost的地址127.0.0.1 docker run -d -p 127.0.0.1:5000:5000 centos_nginx bash (3)映射到指定地址的任意端口 使用ip::containerPort綁定localhost的任意端口到容器的5000端口,本地主機會任意分配一個端口 docker run -d -p 127.0.1.1::5000 centos_nginx bash (4)查看端口映射情況 docker port container_name/container_id演示:
(1)以centos_nginx鏡像啟動一個容器(web_nginx),並將宿主機8081端口進行映射 [root@localhost ~]# docker run -itd --name web_nginx -p 8081:80 centos_nginx bash c558c2a986929f280e7b1db2c46c5951fa95670dfa54de1df83f8b0335241c3c [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c558c2a98692 centos_nginx "bash" 6 seconds ago Up 4 seconds 0.0.0.0:8081->80/tcp web_nginx
(2)進入容器,啟動nginx,發現Operation not permitted報錯 [root@localhost ~]# docker exec -it web_nginx bash [root@c558c2a98692 /]# ps -ef |grep nginx root 26 13 0 05:59 ? 00:00:00 grep --color=auto nginx [root@c558c2a98692 /]# systemctl start nginx Failed to get D-Bus connection: Operation not permitted 解決: •新建的容器,啟動nginx或者httpd服務的時候會報錯 •Failed to get D-Bus connection: Operation not permitted • 這是因為dbus-daemon沒有啟動,解決該問題可以這樣做 • 啟動容器時,要加上--privileged -e "container=docker",並且最后面的命令改為/usr/sbin/init docker run -itd --privileged -e "container=docker" centos_with_nginx /usr/sbin/init 但是如果直接使用nginx命令直接啟動,nginx也是可以的。 (3)刪除容器,使用參數--privileged -e "container=docker",bash改為/usr/sbin/init重新啟動一個容器,並查看端口映射 [root@localhost ~]# docker rm -f web_nginx web_nginx [root@localhost ~]# docker run -itd --privileged -e "container=docker" --name web_nginx -p 8081:80 centos_nginx /usr/sbin/init c57f0ef025b8b61ced5b39d6cf088f6258b536eecbe05868cb8adadf3610db44 [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c57f0ef025b8 centos_nginx "/usr/sbin/init" 7 seconds ago Up 6 seconds 0.0.0.0:8081->80/tcp web_nginx
(4)啟動nginx,並寫入網頁內容,查看是否實現端口映射 [root@localhost ~]# docker exec -it web_nginx bash [root@c57f0ef025b8 /]# ps -ef |grep nginx root 75 63 0 06:03 ? 00:00:00 grep --color=auto nginx [root@c57f0ef025b8 /]# systemctl start nginx [root@c57f0ef025b8 /]# ps -ef |grep nginx root 82 1 0 06:03 ? 00:00:00 nginx: master process /usr/sbin/nginx nginx 83 82 0 06:03 ? 00:00:00 nginx: worker process root 85 63 0 06:03 ? 00:00:00 grep --color=auto nginx [root@c57f0ef025b8 /]# cp /usr/share/nginx/html/index.html{,.bak} [root@c57f0ef025b8 /]# echo "<h1> www.deng.com </h1>" > /usr/share/nginx/html/index.html
7、使用Dokcerfile創建鏡像
7.1、Dockerfile基本結構
Dockerfile
是為了快速構建鏡像Dockerfile
由一行行命令語句組成,並且支持以#開頭的注釋行。
一般而言,Dockerfile
分為4個部分:基礎鏡像信息<br/>維護者信息<br/>鏡像操作指令<br/>容器啟動時執行指令
示例:
#This dockerfile uses the centos image #VERSION 1 #Author:docker_user #Command format:Instruction [arguments / command] .. #第一行必須制定基於的基礎鏡像 FROM centos #維護者信息 MAINTAINER docker_user docker_user@email.com #鏡像的操作指令 RUN echo "hello world" RUN yum update && yum install -y net-tools RUN yum install -y nginx #容器啟動時執行指令 CMD /usr/sbin/nginx
其中,一開始必須指明所基於的鏡像名稱,接下來一般會說明維護者信息。
后面則是鏡像操作指令,例如RUN
指令,RUN
指令將對鏡像執行跟隨的命令。每運行一條RUN
指令,鏡像添加新的一層,並提交。最后是CMD
指令,來指定運行容器時操作的命令。
7.2、Dockerfile指令
指令的一般格式為INSTRUCTION arguments
(1)FROM 指定所創建鏡像的基礎鏡像,如果本地不存在,則默認會去Docker Hub下載指定鏡像。 格式:FROM <image>或 FROM <image>:<tag> 任何Dockerfile中的第一條指令必須為FROM指令。並且在同一個Dockerfile中創建多個鏡像時,可以使用多個FROM指令(每個鏡像一次) (2)MAINTAINER 格式:MAINTAINER <name>,指定維護者信息 該信息會寫入生成鏡像的Author屬性域中 (3)RUN 運行指定命令。 格式:RUN <command>或RUN ["executable","param1","param2"]。注意,后一個指令會被解析為Json數組,因此必須用雙引號。 前者默認將在shell終端運行命令,即/bin/sh -c;后者則使用exec執行,不會啟動shell環境。 比如:RUN yum install httpd RUN ["/bin/bash","-c","echo hello"] 每條RUN指令將在當前鏡像基礎上執行指定命令,並提交為新鏡像。當命令過長時,可以使用\來換行。 (4)CMD CMD指令用來指定啟動容器時默認執行的命令。 支持3種格式: •CMD ["executable", "param1", "param2"]<br/>•CMD command param1 param2<br/>•CMD ["param1", "param2"] RUN和CMD看起來很像,但是CMD用來指定容器啟動時用到的命令,只能有一條。如果指定了多條命令,只有最后一條會被執行。如果用戶啟動容器時,指定了運行命令,則會覆蓋掉CMD指定的命令。 比如:CMD ["/bin/bash", "/usr/local/nginx/sbin/nginx", "-c", "/usr/local/nginx/conf/nginx.conf"] (5)EXPOSE 聲明鏡像內服務所監聽的端口 格式:EXPOSE <port> [<port>...] 比如:EXPOSE 22 80 443 告訴Docker服務端容器暴露的端口號,供互聯系統使用。在啟動容器時需要通過-P,Docker主機會自動分配一個端口轉發到指定端口;使用-p,則可以具體指定哪個本地端口映射過來。 (6)ENV 格式:ENV <key> <value>或ENV <key>=<value>,指定一個環境變量,會被后續RUN指令使用,在鏡像啟動的容器中也會存在。 比如:ENV PATH /usr/local/mysql/bin:$PATH (7)ADD 格式:ADD <src> <dest> 將本地的一個文件或目錄拷貝到容器的某個目錄里。其中<src>為Dockerfile所在目錄的相對路徑,它也可以是一個URL;如果為tar文件,會自動解壓到<dest>路徑下。<dest>可以是鏡像內的絕對路徑,或者相對於工作目錄(WORKDIR)的相對路徑。 • ADD <conf/vhosts> </usr/local/nginx/conf> (8)COPY 格式:COPY <src> <dest> 復制本地主機的<src>(為Dockerfile所在目錄的相對路徑,文件或目錄)為容器中的<dest>。目錄路徑不存在時,會自動創建。當使用本地目錄為源目錄時,推薦使用COPY。 (9)ENTRYPOINT 指定鏡像的默認入口命令,該入口命令在啟動容器時作為根命令執行,所有傳入值作為該命令的參數 兩種格式: ENTRYPOINT ["executable", "param1", "param2"] (exec調用執行)<br/>ENTRYPOINT command param1 param2 (shell中執行) 此時,CMD指令指定值將作為根命令的參數 配置容器啟動后執行的命令,並且不可被docker run 提供的參數覆蓋,每個Dockerfile中只能有一個ENTRYPOINT,當指定多個ENTRYPOINT時,只有最后一個生效。 在運行時,可以被--entrypoint參數覆蓋掉,如docker run --entrypoint •我們在Dockerfile中指定如下CMD: • CMD ["/bin/echo", "test"] • 啟動容器的命令是 docker run aming這樣會輸出test • 假如啟動容器的命令是 docker run -it aming /bin/bash 什么都不會輸出 • ENTRYPOINT不會被覆蓋,而且會比CMD或者docker run指定的命令要靠前執行 • ENTRYPOINT ["echo", "test"] • docker run -it aming 123 • 則會輸出 test 123,這相當於要執行命令 echo test 123 (10)VOLUME 創建一個數據卷掛載點 格式:VOLUME ["/data"] 創建一個可以從本地主機或其他容器掛載的掛載點,一般用於存放數據庫和需要保持的數據等。 (11)USER 格式:USER daemon 指定運行容器時的用戶名或UID,后續的RUN也會指定用戶。 當服務不需要管理員權限時,可以通過該指令指定運行的用戶。並且可以在之前創建所需要的用戶。例如: RUN groupadd -r postgres && useradd -r -g postgres postgres。要臨時獲取管理員權限可以使用gosu,而不推薦sudo (12)WORKDIR 格式:WORKDIR /path/to/workdir 為后續的RUN,CMD,ENTRYPOINT指令配置工作目錄。可以使用多個WORKDIR指令,后續命令如果參數是相對路徑,則會基於之前命令指定的路徑。例如: WORKDIR /a<br/>WORKDIR b<br/>WORKDIR c<br/>RUN pwd 則最終路徑為:/a/b/c (13)ARG 指定一些鏡像內使用的參數(例如版本號信息等),這些參數在執行docker build命令時,才以--build-arg<varname>=<value>格式傳入 格式:ARG<name>[=<default value>] 則可以用docker build --build-arg<name>=<value>.來指定參數值 (14)ONBUILD 配置當所創建的鏡像作為其他鏡像的基礎鏡像時,所執行的創建操作指令。 格式:ONBUILD [INSTRUCTION] 例如,Dockerfile使用如下的內容創建了鏡像image-A: [...]<br/>ONBUILD ADD . /app/src<br/>ONBUILD RUN /usr/local/bin/python-build --dir /app/src<br/>[...] 如果基於image-A創建新的鏡像時,新的Dockerfile中使用FROM image-A指定基礎鏡像,會自動執行ONBUILD指令的內容 (15)STOPSIGNAL 指定所創建鏡像啟動的容器接收退出的信號值。例如: STOPSIGNAL signal (16)HEALTHCHECK 配置所啟動容器如何進行健康檢查(如何判斷健康與否),自docker 1.12開始支持 格式有兩種: HEALTHCHECK [OPTIONS] CMD command:根據所執行命令返回值是否為0來判斷; HEALTHCHECK NONE:禁止基礎鏡像中的健康檢查。 OPTION支持: ①--interval=DURATION(默認為:30s):過多久檢查一次; ②--timeout=DURATION(默認為:30s):每次檢查等待結果的超時; ③--retries=N(默認為:3):如果失敗了,重試幾次才最終確定失敗。 (17)SHELL 指定其他命令使用shell時的默認shell類型 SHELL ["executable","parameters"] 默認值為["/bin/sh","-c"]
7.3、創建鏡像
編寫完Dockerfile之后,可以通過docker build命令來創建鏡像。 格式:docker build [選項] 內容路徑 該命令將讀取指定路徑下(包括子目錄)的Dockerfile,並將該路徑下的所有內容發送給Docker服務端,有服務端來創建鏡像。因此除非生成鏡像需要,否則一般建議放置Dockerfile的目錄為空目錄,可以使用-f選項來指定其路徑。
①如果使用非內容路徑下的Dockerfile,可以通過-f選項來指定其路徑 ②要指定生成鏡像的標簽信息,可以使用-t選項 例如:指定的Dockerfile所在路徑為/tmp/docker_builder/,並且希望生成的鏡像標簽為build_repo/frist_image,可以使用: docker build -t build_repo/first_image /tmp/docker_builder/
7.4、Dockerfile創建鏡像示例(nginx)
(1)編輯Dockerfile文件
[root@localhost ~]# vim Dockerfile FROM centos MAINTAINER long 442305405@qq.com RUN yum install -y pcre-devel wget net-tools gcc zlib zlib-devel make openssl-devel ADD http://nginx.org/download/nginx-1.12.2.tar.gz . RUN tar zxvf nginx-1.12.2.tar.gz RUN mkdir -p /usr/local/nginx RUN cd nginx-1.12.2 && ./configure --prefix=/usr/local/nginx && make && make install RUN rm -fv /usr/local/nginx/conf/nginx.conf ADD http://www.apelearn.com/study_v2/.nginx_conf /usr/local/nginx/conf/nginx.conf ADD index.html /usr/local/nginx/html/index.html RUN echo "daemon off;" >> /usr/local/nginx/conf/nginx.conf EXPOSE 80 ENTRYPOINT /usr/local/nginx/sbin/nginx
(2)創建鏡像
[root@localhost ~]# docker build -t centos_nginx:1.12.2 . Sending build context to Docker daemon 212.7 MB Step 1 : FROM centos ---> d123f4e55e12 Step 2 : MAINTAINER long 442305405@qq.com ---> Using cache ---> 42a2766d5cce Step 3 : RUN yum install -y pcre-devel wget net-tools gcc zlib zlib-devel make openssl-devel ---> Running in ebd2bc43b045 Loaded plugins: fastestmirror, ovl ...... Step 8 : RUN rm -fv /usr/local/nginx/conf/nginx.conf ---> Running in eb41c1c7b39d removed '/usr/local/nginx/conf/nginx.conf' ---> d6b0d765ca2e Removing intermediate container eb41c1c7b39d Step 9 : ADD http://www.apelearn.com/study_v2/.nginx_conf /usr/local/nginx/conf/nginx.conf Downloading [==================================================>] 1.678 kB/1.678 kB ---> efffda0c218d Removing intermediate container af06898e74f4 Step 10 : EXPOSE 80 ---> Running in fb3905caf714 ---> 6efacb9d8a12 Removing intermediate container fb3905caf714 Step 11 : ENTRYPOINT /usr/local/nginx/sbin/nginx && tail -f /etc/passwd ---> Running in 61b617e30d2b ---> 02447e813325 Removing intermediate container 61b617e30d2b Successfully built 02447e813325
(3)查看創建的鏡像,並通過創建的鏡像創建容器
[root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos_nginx 1.12.2 02447e813325 About a minute ago 350 MB [root@localhost ~]# docker run -itd centos_nginx:1.12.2 bash 10fa28dc417e0023004f857f72537e232a63b2977fda3228a77688d33b0d7803 [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 10fa28dc417e centos_nginx:1.12.2 "/bin/sh -c '/usr/loc" 3 seconds ago Up 3 seconds 80/tcp gigantic_agnesi
(4)進入容器查看nginx運行狀況
[root@localhost ~]# docker exec -it gigantic_agnesi bash [root@10fa28dc417e /]# ps -ef |grep nginx root 1 0 0 06:37 ? 00:00:00 /bin/sh -c /usr/local/nginx/sbin/nginx root 6 1 0 06:37 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx nobody 7 6 0 06:37 ? 00:00:00 nginx: worker process nobody 8 6 0 06:37 ? 00:00:00 nginx: worker process root 24 10 0 06:38 ? 00:00:00 grep --color=auto nginx
7.5.遇到的問題
由於之前使用過pipework進行配置橋接網絡,需要更改網絡,並開啟IPv4轉發 [root@localhost ~]# docker run -itd --name test centos_nginx bash WARNING IPv4 forwarding is disabled. Networking will not work a93d14f536d31b3edfd847f12c8e1115bb75bc2b202fb44f761c2e14c2018a6b 解決: # vi /etc/sysctl.conf 或者 # vi /usr/lib/sysctl.d/00-system.conf 添加如下代碼: net.ipv4.ip_forward=1 重啟network服務 # systemctl restart network 查看是否修改成功 # sysctl net.ipv4.ip_forward