Docker 學習筆記【4】 高級網絡配置實操,實戰案例實驗
===========================================================================
Docker 學習筆記【2】 Docker 倉庫實操,創建私有倉庫,實操數據卷、數據卷容器,記錄開始
===========================================================================
被格式化的腳本內容:
#開頭代表宿主機的root用戶執行的命令
]$開頭的代表宿主機的普通用戶執行的命令
[root@ec600b17b4ad /]# 類似開頭的,實在docker啓動的實例中執行的命令
--1-- 倉庫
1、公有倉庫:
1.基本操作:
1>搜索、下載image:
# docker search tomcat NAME DESCRIPTION STARS OFFICIAL AUTOMATED tomcat Apache Tomcat is an open source implementa... 1017 [OK] dordoka/tomcat Ubuntu 14.04, Oracle JDK 8 and Tomcat 8 ba... 27 [OK] consol/tomcat-8.0 Tomcat 8.0.15, 8080, "admin/admin" 15 [OK] davidcaste/alpine-tomcat Apache Tomcat 7/8 using Oracle Java 7/8 wi... 10 [OK] cloudesire/tomcat Tomcat server, 6/7/8 10 [OK] andreptb/tomcat Debian Jessie based image with Apache Tomc... 6 [OK] openweb/oracle-tomcat A fork off of Official tomcat image with O... 4 [OK] kieker/tomcat 2 [OK] fbrx/tomcat Minimal Tomcat image based on Alpine Linux 2 [OK] camptocamp/tomcat-logback Docker image for tomcat with logback integ... 1 [OK] abzcoding/tomcat-redis a tomcat container with redis as session m... 1 [OK] bitnami/tomcat Bitnami Tomcat Docker Image 1 [OK] picoded/tomcat tomcat 8 with java 8, and MANAGER_USER / M... 1 [OK] rennergabor/virgo-tomcat-server Docker image for Eclipse Virgo Tomcat Server 0 [OK] ping2ravi/tomcat Tomcat Versions 7 and 8 0 [OK] cheewai/tomcat Tomcat and Oracle JRE in docker 0 [OK] inspectit/tomcat Tomcat with inspectIT 0 [OK] stakater/tomcat Tomcat based on Ubuntu 14.04 and Oracle Java 0 [OK] charlycoste/tomcat Debian based Tomcat (don't use it, this is... 0 [OK] davidcaste/debian-tomcat Yet another Debian Docker image for Tomcat... 0 [OK] elcom/tomcat Tomcat with Java 0 [OK] blueur/tomcat Tomcat with the possibility to set the use... 0 [OK] khipu/tomcat ansible based tomcat 8 0 [OK] oriaks/tomcat Tomcat 0 [OK] phpmentors/tomcat-app Tomcat application image using Maven 0 [OK] docker pull ${REPOSITORY}:${TAG}---------[不演示,第一節的實操在筆記【2】中有]
2.自動創建:
作爲後續擴展學習部分,暫不演示,以實用功能爲主
2、私有倉庫:
1.使用registry的鏡像創建私有倉庫容器:
1>將registry鏡像下載到本地:
# docker pull registry latest: Pulling from registry 4b59778f82f9: Pull complete d55b2c222c83: Pull complete c664f834680b: Pull complete b772c022cbbe: Pull complete feb1c3b189e9: Pull complete 601bdc23d897: Pull complete be7eadf718aa: Pull complete 9bac026e7e41: Pull complete 5c929a8b587a: Pull complete Digest: sha256:0658d259f220a395b17f994a433cca057ff3828c839c303506db2993189bb2df Status: Downloaded newer image for registry:latest
2>使用pull的官方registry啓動一個倉庫docker容器實例
方法1含義:將本地5000端口連接到容器實例的5000端口,實用官方registry鏡像啓動實例
# docker run -d -p 5000:5000 registry 4ea87a9497d26b3fac32748d72b0fc7ab1ca1c2cbde7075da530c16fe8a088f6
注:筆記中有s3相關的筆記,但是由於亞馬遜中國區註冊需要營業執照,國際區速度慢而且收費,所以就不演示,有機會演示的話,新起一個筆記連接於此:鏈接
方法2含義:將本地5000端口連接到容器實例的5000端口,實用官方registry鏡像啓動實例,並將本地目錄/home/admin/registry掛載爲該容器實例的數據卷,目錄爲容器中的/registry,權限讀寫
【推薦,因此,所有基於使用registry的鏡像創建私有倉庫容器的操作,都基於這個方式啓動的,這樣可以將鏡像存在宿主機的/home/admin/registry目錄下!】
# docker run -d -p 5000:5000 -v /home/admin/registry:/var/lib/registry registry 879e4d9ab3575846ca41251d95f6486449f4ba4461c7ec8f6068413f522d94a6
3>驗證:
# docker tag my_centos:6.8 127.0.0.1:5000/lich_centos:6.8 # docker push 127.0.0.1:5000/lich_centos:6.8 The push refers to a repository [127.0.0.1:5000/lich_centos] (len: 1) 35b7ec25ed6f: Buffering to Disk 35b7ec25ed6f: Image already exists Digest: sha256:2abc4b59ac7f668e699148994826d48149b12db4e69c2ec0a5abecdeafaf291c # curl 127.0.0.1:5000/v2/_catalog {"repositories":["lich_centos"]}
【注意,docker通過repository來斷定1:鏡像屬於哪個註冊服務器;2:鏡像屬於註冊服務器的哪個倉庫,通過tag來標記具體鏡像】
【所以,push之前需要將image重新tag,然後再執行push操作】
【附:v2私服的http api】http://blog.csdn.net/ztsinghua/article/details/51496658
------------重要標記--------------
1、v1版本的registry和v2版本的registry,驗證方式不同:
v1:瀏覽器訪問方式爲:我的ip:5000/v1/search
v1可以通過get方式搜索關鍵字:curl -X GET 我的ip:5000/v1/search?q=關鍵字
latest版本爲v2瀏覽器訪問方式爲:我的ip:5000/v2/_catalog
2、容器內部,存儲鏡像的位置不同:
v1:/tmp/registry
v2:/var/lib/registry
3、實現語言:
v1:python
v2:go[與docker相同]
4、以我上傳的127.0.0.1:5000/lich_centos:6.8爲例[v2],由於將本地的/home/admin/registry目錄掛在到了他的鏡像存儲目錄,所以鏡像被存儲到了本地的/home/admin/registry目錄。結構如下:
]$ pwd /home/admin/registry ]$ ll total 4 drwxr-xr-x 3 root root 4096 Nov 11 10:46 docker cd docker/registry/v2/ ]$ ll total 8 drwxr-xr-x 3 root root 4096 Nov 11 10:46 blobs drwxr-xr-x 3 root root 4096 Nov 11 10:46 repositories ]$ pwd /home/admin/registry/docker/registry/v2 ]$ du -sh * 118M blobs 80K repositories
到上述步驟可以看出,鏡像數據是存在blobs中的
$ cd repositories/ ]$ ll total 4 drwxr-xr-x 5 root root 4096 Nov 11 10:46 lich_centos ]$ pwd /home/admin/registry/docker/registry/v2/repositories ]$ ll total 4 drwxr-xr-x 5 root root 4096 Nov 11 10:46 lich_centos
以上步驟看出repositories是存儲倉庫文件的信息
]$ pwd /home/admin/registry/docker/registry/v2/repositories/lich_centos/_manifests/tags ]$ ll total 4 drwxr-xr-x 4 root root 4096 Nov 11 10:46 6.8 ]$ pwd /home/admin/registry/docker/registry/v2/repositories/lich_centos/_manifests/tags/6.8 ]$ cd current/ ]$ ll total 4 -rw-r--r-- 1 root root 71 Nov 11 10:46 link ]$ cat link sha256:2abc4b59ac7f668e699148994826d48149b12db4e69c2ec0a5abecdeafaf291c $ pwd /home/admin/registry/docker/registry/v2/repositories/lich_centos/_manifests/tags/6.8/index/sha256/2abc4b59ac7f668e699148994826d48149b12db4e69c2ec0a5abecdeafaf291c ]$ ll total 4 -rw-r--r-- 1 root root 71 Nov 11 10:46 link ]$ cat link sha256:2abc4b59ac7f668e699148994826d48149b12db4e69c2ec0a5abecdeafaf291c
以上可以看出_manifests中存着tag,以及相關的sha256密文信息,索引,以及當前的版本信息等
]$ pwd /home/admin/registry/docker/registry/v2/blobs/sha256 ]$ du -sh * 12K 2a 118M 57 ]$ pwd /home/admin/registry/docker/registry/v2/blobs/sha256/2a/2abc4b59ac7f668e699148994826d48149b12db4e69c2ec0a5abecdeafaf291c ]$ ll total 4 -rw-r--r-- 1 root root 2685 Nov 11 10:46 data ]$ du -sh *
4.0K data
]$ pwd /home/admin/registry/docker/registry/v2/blobs/sha256/57/57f54b88f59ddb62a1630ffb17ab61894db1d6393b0961a14c1334aad1403b27 ]$ ll total 120504 -rw-r--r-- 1 root root 123395470 Nov 11 10:46 data ]$ du -sh * 118M data
以上步驟可以看出,鏡像文件加密成名爲data的文件存放在一串密文文件夾中,這與鏡像的唯一id相關。
5、私服上的image刪除,參考http api,後續專欄寫私服中的鏡像管理:
【附:v2私服的http api】http://blog.csdn.net/ztsinghua/article/details/51496658
2.docker-registry安裝私服[使用gunicorn]:
1>下載源碼:
# git clone https://github.com/docker/docker-registry.git Initialized empty Git repository in /root/tmp/docker-registry/.git/ remote: Counting objects: 7007, done. remote: Total 7007 (delta 0), reused 0 (delta 0), pack-reused 7007 Receiving objects: 100% (7007/7007), 1.69 MiB | 273 KiB/s, done. Resolving deltas: 100% (4101/4101), done.
2>安裝:
#cd docker-registry/ #yum install -y python-devel libevent-devel python-pip gcc xz-devel #python setup.py install
從日誌中看,會自動檢查依賴包,如果依賴包不存在會自動從默認pypi.python.org下載並安裝,根據報錯安裝缺少的包,不贅述
基本找到如:Searching for docker-registry-core>=2,<3的信息執行:pip install "docker-registry-core>=2,<3" 處理即可
3>啓動:
命令:
docker-registry
默認佔用宿主機5000端口
我機器上安裝的默認路徑是:
/usr/lib/python2.6/site-packages/docker_registry-1.0.0_dev-py2.6.egg
其中配置文件在:
/usr/lib/python2.6/site-packages/docker_registry-1.0.0_dev-py2.6.egg/config
可通過:
export DOCKER_REGISTRY_CONFIG=/opt/docker-registy/conf/config.yml
環境變量重新制定文件路徑
【博客鏈接,docker-registry配置】http://aresy.blog.51cto.com/5100031/1553624/
需要配置配置文件:
# cd /usr/lib/python2.6/site-packages/docker_registry-1.0.0_dev-py2.6.egg/config # cp config_sample.yml config.yml
編輯配置文件,dev:的內容修改爲:
dev: &dev <<: *common loglevel: _env:LOGLEVEL:debug debug: _env:DEBUG:true storage: file storage_path: /root/docker search_backend: _env:SEARCH_BACKEND:sqlalchemy
docker-registry使用
# docker-registry -h usage: docker-registry [-h] run the docker-registry with gunicorn, honoring the following environment variables: REGISTRY_HOST: TCP host or ip to bind to; default is 0.0.0.0 REGISTRY_PORT: TCP port to bind to; default is 5000 GUNICORN_WORKERS: number of worker processes gunicorn should start GUNICORN_GRACEFUL_TIMEOUT: timeout in seconds for graceful worker restart GUNICORN_SILENT_TIMEOUT: timeout in seconds for restarting silent workers GUNICORN_USER: unix user to downgrade priviledges to GUNICORN_GROUP: unix group to downgrade priviledges to GUNICORN_ACCESS_LOG_FILE: File to log access to GUNICORN_ERROR_LOG_FILE: File to log errors to GUNICORN_OPTS: extra options to pass to gunicorn
可見,docker-registry啓動的時候是從環境變量中讀取這些量,爲此,我們在~/.bashrc中添加如下內容:
export REGISTRY_HOST=0.0.0.0 export REGISTRY_PORT=9000 export GUNICORN_WORKERS=10 export GUNICORN_GRACEFUL_TIMEOUT=10 export GUNICORN_SILENT_TIMEOUT=10 export GUNICORN_USER=root export GUNICORN_GROUP=root export GUNICORN_ACCESS_LOG_FILE=/root/registry_logs/access.log export GUNICORN_ERROR_LOG_FILE=/root/registry_logs/error.log
啓動docker-registry【由於dev:跟了&dev 進入守護模式運行】:
docker-registry
啓動後可能會有警告信息,不影響使用,只是沒有開啓redis的cache而已:
11/Nov/2016:14:25:13 +0000 WARNING: Cache storage disabled! 11/Nov/2016:14:25:13 +0000 WARNING: LRU cache disabled! 11/Nov/2016:14:25:13 +0000 DEBUG: Will return docker-registry.drivers.file.Storage
4>驗證:
重新tag一個鏡像:
# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE python latest cbf35a92f6c2 22 hours ago 682.4 MB 127.0.0.1:5000/lich_centos 6.8 35b7ec25ed6f 25 hours ago 343.8 MB registry latest 5c929a8b587a 3 weeks ago 33.27 MB ubuntu 12.04 cfc2576a1531 6 weeks ago 103.6 MB centos 6.8 80e46367f846 10 weeks ago 194.5 MB consol/tomcat-8.0 latest 1a333e5a77be 17 months ago 600.7 MB # docker tag 35b7ec25ed6f 127.0.0.1:9000/lich9_centos # docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE python latest cbf35a92f6c2 22 hours ago 682.4 MB 127.0.0.1:9000/lich9_centos latest 35b7ec25ed6f 25 hours ago 343.8 MB 127.0.0.1:5000/lich_centos 6.8 35b7ec25ed6f 25 hours ago 343.8 MB registry latest 5c929a8b587a 3 weeks ago 33.27 MB ubuntu 12.04 cfc2576a1531 6 weeks ago 103.6 MB centos 6.8 80e46367f846 10 weeks ago 194.5 MB consol/tomcat-8.0 latest 1a333e5a77be 17 months ago 600.7 MB
push鏡像,日誌中可以看出,這個版本安裝的是v1版本的註冊私有服務器
# docker push 127.0.0.1:9000/lich9_centos The push refers to a repository [127.0.0.1:9000/lich9_centos] (len: 1) Sending image list Pushing repository 127.0.0.1:9000/lich9_centos (1 tags) 35b7ec25ed6f: Image successfully pushed Pushing tag for rev [35b7ec25ed6f] on {http://127.0.0.1:9000/v1/repositories/lich9_centos/tags/latest} 此時docker-registry的日誌會刷新: 11/Nov/2016:14:27:45 +0000 DEBUG: args = {'namespace': 'library', 'repository': 'lich9_centos'} 11/Nov/2016:14:27:45 +0000 DEBUG: args = {'image_id': u'35b7ec25ed6f9657ff7581a8c7643c2ce48d1b892eac6116b783b43fc8fd9bfc'} 11/Nov/2016:14:27:45 +0000 DEBUG: api_error: Image not found 11/Nov/2016:14:27:45 +0000 DEBUG: args = {'image_id': u'35b7ec25ed6f9657ff7581a8c7643c2ce48d1b892eac6116b783b43fc8fd9bfc'} 11/Nov/2016:14:27:48 +0000 DEBUG: args = {'image_id': u'35b7ec25ed6f9657ff7581a8c7643c2ce48d1b892eac6116b783b43fc8fd9bfc'} 11/Nov/2016:14:28:48 +0000 DEBUG: args = {'image_id': u'35b7ec25ed6f9657ff7581a8c7643c2ce48d1b892eac6116b783b43fc8fd9bfc'} 11/Nov/2016:14:28:48 +0000 DEBUG: args = {'tag': u'latest', 'namespace': 'library', 'repository': 'lich9_centos'} 11/Nov/2016:14:28:48 +0000 DEBUG: [put_tag] namespace=library; repository=lich9_centos; tag=latest 11/Nov/2016:14:28:48 +0000 DEBUG: args = {'images': True, 'namespace': 'library', 'repository': 'lich9_centos'} 11/Nov/2016:14:30:57 +0000 DEBUG: args = {'namespace': 'library', 'repository': 'lich9_centos'} 11/Nov/2016:14:30:57 +0000 DEBUG: args = {'namespace': u'library', 'repository': 'lich9_centos'} 11/Nov/2016:14:30:57 +0000 DEBUG: [get_tags] namespace=library; repository=lich9_centos 11/Nov/2016:14:30:57 +0000 DEBUG: args = {'image_id': u'35b7ec25ed6f9657ff7581a8c7643c2ce48d1b892eac6116b783b43fc8fd9bfc'} 11/Nov/2016:14:31:27 +0000 DEBUG: args = {'namespace': 'library', 'repository': 'lich9_centos'} 11/Nov/2016:14:31:27 +0000 DEBUG: args = {'namespace': u'library', 'repository': 'lich9_centos'} 11/Nov/2016:14:31:27 +0000 DEBUG: [get_tags] namespace=library; repository=lich9_centos 11/Nov/2016:14:31:27 +0000 DEBUG: args = {'image_id': u'35b7ec25ed6f9657ff7581a8c7643c2ce48d1b892eac6116b783b43fc8fd9bfc'} 11/Nov/2016:14:31:27 +0000 DEBUG: args = {'image_id': u'35b7ec25ed6f9657ff7581a8c7643c2ce48d1b892eac6116b783b43fc8fd9bfc'} 11/Nov/2016:14:31:27 +0000 DEBUG: args = {'image_id': u'35b7ec25ed6f9657ff7581a8c7643c2ce48d1b892eac6116b783b43fc8fd9bfc'} 配置文件將存儲路徑指向:/root/docker此時該文件夾下已經有了數據: tree /root/docker/ docker/ ├── images │ └── 35b7ec25ed6f9657ff7581a8c7643c2ce48d1b892eac6116b783b43fc8fd9bfc │ ├── ancestry │ ├── _checksum │ ├── json │ └── layer └── repositories └── library └── lich9_centos ├── _index_images ├── json ├── tag_latest └── taglatest_json 5 directories, 8 files
調用http、api驗證
# curl -X GET http://127.0.0.1:9000/v1/search {"num_results": 1, "query": "", "results": [{"description": null, "name": "library/lich9_centos"}]}
使用docker命令:
# docker search 127.0.0.1:9000/centos NAME DESCRIPTION STARS OFFICIAL AUTOMATED library/lich9_centos 0
5>將本地所有鏡像push到私服:
shell腳本,後面參數需要跟上本地的id【一個或多個】如:
# ./push_images.sh python registry centos:6.8 The registry server is 127.0.0.1:9000 Uploading python... The push refers to a repository [127.0.0.1:9000/python] (len: 1) Sending image list Pushing repository 127.0.0.1:9000/python (1 tags) 385b367e1f47: Image successfully pushed 3307aeade16b: Image successfully pushed c799e95a8f7b: Image successfully pushed 4fda0db3e365: Image successfully pushed 1d79f596a4bc: Image successfully pushed b0efeca46bd3: Image successfully pushed fcce871796c9: Image successfully pushed 3b498d682dde: Image successfully pushed 17ee65a53e86: Image successfully pushed ce03e868fe5e: Image successfully pushed ea02150f8827: Image successfully pushed 4bf63b636773: Image successfully pushed baf78a44efdd: Image successfully pushed cbf35a92f6c2: Image successfully pushed Pushing tag for rev [cbf35a92f6c2] on {http://127.0.0.1:9000/v1/repositories/python/tags/latest} Untagged: 127.0.0.1:9000/python:latest Done Uploading registry... The push refers to a repository [127.0.0.1:9000/registry] (len: 1) Sending image list Pushing repository 127.0.0.1:9000/registry (1 tags) 4b59778f82f9: Image successfully pushed d55b2c222c83: Image successfully pushed c664f834680b: Image successfully pushed b772c022cbbe: Image successfully pushed feb1c3b189e9: Image successfully pushed 601bdc23d897: Image successfully pushed be7eadf718aa: Image successfully pushed 9bac026e7e41: Image successfully pushed 5c929a8b587a: Image successfully pushed Pushing tag for rev [5c929a8b587a] on {http://127.0.0.1:9000/v1/repositories/registry/tags/latest} Untagged: 127.0.0.1:9000/registry:latest Done 。 。 。 :
腳本內容:
#!/bin/sh # This script will upload the given local images to a registry server ($registry is the default value). # See: https://github.com/yeasy/docker_practice/blob/master/_local/push_images.sh # Usage: push_images image1 [image2...] # Author: yeasy@github # Create: 2014-09-23 #The registry server address where you want push the images into registry=127.0.0.1:9000 ### DO NOT MODIFY THE FOLLOWING PART, UNLESS YOU KNOW WHAT IT MEANS ### echo_r () { [ $# -ne 1 ] && return 0 echo -e "\033[31m$1\033[0m" } echo_g () { [ $# -ne 1 ] && return 0 echo -e "\033[32m$1\033[0m" } echo_y () { [ $# -ne 1 ] && return 0 echo -e "\033[33m$1\033[0m" } echo_b () { [ $# -ne 1 ] && return 0 echo -e "\033[34m$1\033[0m" } usage() { sudo docker images echo "Usage: $0 registry1:tag1 [registry2:tag2...]" } [ $# -lt 1 ] && usage && exit echo_b "The registry server is $registry" for image in "$@" do echo_b "Uploading $image..." sudo docker tag $image $registry/$image sudo docker push $registry/$image sudo docker rmi $registry/$image echo_g "Done" done
--2-- 數據卷和數據卷容器
docker的配置文件在:
# pwd /etc/sysconfig # ll docker* -rw-r--r-- 1 root root 531 Nov 11 15:27 docker -rw-r--r-- 1 root root 0 Aug 15 2015 docker-network -rw-r--r-- 1 root root 597 Aug 15 2015 docker-storage
1、數據卷:
筆記2中的描述有問題:
創建一個web服務器,並創建一個數據卷/webapp,從宿主機端口中任意打開一個端口映射到容器的5000端口
# docker run -d -P --name web -v /webapp training/webapp python app.py 4de65ac6fb26790c17daef58a3457f0057f6cf2be14a57afbcda993a769f9903 # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4de65ac6fb26 training/webapp "python app.py" 29 seconds ago Up 27 seconds 0.0.0.0:32768->5000/tcp web
此時訪問我的ip:32768 會得到hello world!
確認鏡像可用,將實例殺掉:
# docker stop 4de65ac6fb26 # docker rm 4de65ac6fb26
實用角度出發,實用tomcat鏡像進行測試:
現已知:consol/tomcat-8.0鏡像中,頁面存放的位置在:/opt/apache-tomcat-8.0.23/webapps,我們將宿主機的一個文件夾:/root/webapp_local掛載到容器的/opt/apache-tomcat-8.0. 23/webapps/what數據卷下:
在目錄/root/webapp_local下我創建了一個html裏面寫上了:sakdfaksdfhasdfh
]# docker run -d -P --name web -v /root/webapp_local:/opt/apache-tomcat-8.0.23/webapps/what consol/tomcat-8.0 75039e93610d66fd0d53b90342a26e506c48896046c1896aec6f413ece6475e6 # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 75039e93610d consol/tomcat-8.0 "/bin/sh -c /opt/tom 5 seconds ago Up 2 seconds 0.0.0.0:32773->8080/tcp, 0.0.0.0:32772->8778/tcp web
只讀權限的掛載就不演示了,就是docker內部對掛載的目錄沒有寫權限,跟掛在了一個光盤一樣。掛載單個文件由於inode問題,也不進行實驗了,基本不會用到的。
此時訪問: http://我的ip:32773 得到apache歡迎頁 http://我的ip:32773/what/what.html 得到我寫的字符串:sakdfaksdfhasdfh 修改what.html爲:123234523453 http://我的ip:32773/what/what.html 得到:123234523453
2、數據卷容器
創建數據卷容器:
#docker run -d -v /dbdata_volume --name dbdata training/postgres
創建其他容器時,使用數據卷容器中的數據卷:
#docker run -d --volumes-from dbdata --name db1 training/postgres #docker run -d --volumes-from dbdata --name db2 training/postgres
此時 db1、db2的/dbdata_volume都掛在的dbdata這個數據卷容器的/data目錄,雙數據庫讀取同一個數據文件
此時db1、db2都存在數據卷,這兩個容器也是數據卷容器了,因此可以被使用【其實掛載的還是dbdata容器中的/dbdata_volume數據卷】:
#docker run -d --name db3 --volumes-from db1 training/postgres
容器被docker rm的時候,不會刪除數據卷,如果要刪除對應的數據卷,則需要在刪除最後一個引用了數據卷容器的時候使用 -v參數
# docker rm -f -v db3
3、通過數據卷容器進行備份、恢復、遷移數據卷【原理釋義,暫時不會用到,因此做理解記錄,詳情不再記錄】
docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
此時卷被被備份在本地的當前目錄,名爲backup.tar
docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
此時創建了一個dbdata2的數據卷容器
docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar
此時創建了另一個容器,並將dbdata2中的數據卷/dbdata掛到了自己的目錄中,並且又掛載了一個本地的數據卷:$(pwd):/backup,又將其中的backup.tar解壓出來,其中只有一個/dbdata目錄和其中的數據,因此,數據卷容器得以複製到dbdata2數據卷容器的/dbdata數據卷中。
--3-- Docker中的網絡:
1、前面在做web測試數據卷的時候已經用到了,不再贅述記錄,做簡單理解性筆記:
-p小寫指定端口
-P大寫隨機端口,host爲0.0.0.0
docker容器啓動的時候也會創建一套網絡服務,內部ip和端口想虛擬機一樣在宿主機上,但是如果不做綁定,將會導致外面無法訪問到docker裏面的服務
指定端口綁定容器的方式有三種:
【ip:hostPort:containerPort 】指定一個監聽ip、端口綁定到docker容器的指定端口:
docker run -d -p 127.0.0.1:9988:8080 --name web -v /root/webapp_local:/opt/apache-tomcat-8.0.23/webapps/what consol/tomcat-8.0
【ip::containerPort 】指定一個監聽ip、隨機端口綁定到docker容器的指定端口:
docker run -d -p 127.0.0.1::8080 --name web -v /root/webapp_local:/opt/apache-tomcat-8.0.23/webapps/what consol/tomcat-8.0
【hostPort:containerPort 】指定一個端口,監聽所有ip、端口綁定到docker容器的指定端口:
docker run -d -p 9988:8080 --name web -v /root/webapp_local:/opt/apache-tomcat-8.0.23/webapps/what consol/tomcat-8.0
--4-- 容器互聯:
1、容器之間的安全交互:
創建一個容器:
# docker run -d --name db training/postgres 81ffbb409bf61b67b95426eb51a52ec9e55c4b10e4233d8fe1eefaf0abd038cd
這是一個postgres的容器
創建一個centos容器,centos:使其跟db互聯,互聯的別名叫做db_alias
# docker run -ti --name centos --link db:db_alias centos:6.8 2a85ef59d70b9edf04275eee42a897c95efbb9cc50628a4215f647f03d49ea98 [root@54ab58dec35c /]# cat /etc/hosts 172.17.0.26 54ab58dec35c 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.22 db_alias 98a476f6c636 db
由上面可以看出,其實就是在容器內部通過docker網橋,打通了兩個ip,並且將容器名、容器id、link別名都在hosts中做了解析
2、Docker通過兩種方式公開連接信息:
1.環境變量:
# docker run -ti --name centos --link db:db_alias centos:6.8 env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=0c889e04a32f TERM=xterm DB_ALIAS_PORT=tcp://172.17.0.27:5432 DB_ALIAS_PORT_5432_TCP=tcp://172.17.0.27:5432 DB_ALIAS_PORT_5432_TCP_ADDR=172.17.0.27 DB_ALIAS_PORT_5432_TCP_PORT=5432 DB_ALIAS_PORT_5432_TCP_PROTO=tcp DB_ALIAS_NAME=/centos/db_alias DB_ALIAS_ENV_PG_VERSION=9.3 HOME=/root
2.hosts解析:
# docker run -ti --name centos --link db:db_alias centos:6.8 [root@a62d53a46fd9 /]# cat /etc/hosts 172.17.0.30 a62d53a46fd9 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.27 db_alias 25de25a6cd0f db
可以連接多個子容器到父容器 不多做解釋了,因爲跟網絡一樣,網絡互通只要ip池有地址,就不限制
===========================================================================
Docker 學習筆記【2】 Docker 倉庫實操,創建私有倉庫,實操數據卷、數據卷容器,記錄結束
===========================================================================
===========================================================================
高級網絡配置
===========================================================================
--1-- 基本概念
1、基本概念
1.Docker啓動時,會自動在宿主機上創建一個docker0命名的虛擬網橋,實際上是linux的一個bridge,可以理解爲一個軟件交換機,它會在掛載到他的網口之間進行轉發。
2.Docker隨機分配一個本地未佔用的私有網段【RFC1918中定義】,中的一個地址給docker0接口,比如典型默認值:172.17.42.1,掩碼爲:255.255.0.0,啓動容器時。會自動在網口上分配一個網段172.17.0.0/16地址
3.RFC1918定義的三類私網地址:
A類:10.0.0.0/8即10.0.0.0~10.255.255.255
B類:172.16.0.0/12即172.16.0.0~172.31.255.255
C類:192.168.0.0/16即192.168.0.0~192.168.255.255
2、基本原理
1.當創建一個Docker容器的時候,同事創建了一對veth pair接口,即當數據包發送到一個接口時,另一個接口也收到相同的數據包。這對接口一端在容器內,即eth0【容器內的eth0】:另一端在宿主機上被掛在到docker0這個虛擬網橋上,名稱以veth開頭,後面跟上一串字符串:vethAQI2QT。通過這種方式,宿主機可以跟容器通信,容器之間也可以互相通信,Docker就創建了在宿主機和容器之間的一個虛擬共享網絡。
--2-- 網絡配置
1、基本操作
1.Docker相關網絡配置命令:注:【其中部分命令不能立即生效,必須在重啓docker服務後生效】
-b BRIDGE or --bridge=BRIDGE --指定容器掛載的網橋 --bip=CIDR --定製 docker0 的掩碼 -H SOCKET... or --host=SOCKET... --Docker 服務端接收命令的通道 --icc=true|false --是否支持容器之間進行通信 --ip-forward=true|false --請看:容器之間的通信 --iptables=true|false --禁止 Docker 添加 iptables 規則 --mtu=BYTES --容器網絡中的 MTU【windows默認1400 linux默認是1380,如果windows撥上***不好用,可能需要設置這個值】
2.下面2個命令選項既可以在啓動服務時指定,也可以 Docker 容器啓動(docker run)時候指定。在 Docker 服務啓動的時候指定則會成爲默認值,後面執行 docker run 時可以覆蓋設置的默認值。
--dns=IP_ADDRESS... --使用指定的DNS服務器 --dns-search=DOMAIN... --指定DNS搜索域
3.最後這些選項只有在 docker run 執行時使用,因爲它是針對容器的特性內容。
-h HOSTNAME or --hostname=HOSTNAME --配置容器主機名 --link=CONTAINER_NAME:ALIAS --添加到另一個容器的連接 --net=bridge|none|container:NAME_or_ID|host --配置容器的橋接模式 -p SPEC or --publish=SPEC --映射容器端口到宿主主機 -P or --publish-all=true|false --映射容器所有端口到宿主主機
4.配置DNS
Docker 沒有爲每個容器專門定製鏡像,容器利用虛擬文件來掛載到來容器的 3 個相關配置文件,實現自定義容器的主機名和dns配置。
在容器中使用 mount 命令可以看到掛載信息:
$ mount ... /dev/disk/by-uuid/1fec...ebdf on /etc/hostname type ext4 ... /dev/disk/by-uuid/1fec...ebdf on /etc/hosts type ext4 ... tmpfs on /etc/resolv.conf type tmpfs ... ...
這種機制可以讓宿主主機 DNS 信息發生更新後,所有 Docker 容器的 dns 配置通過 /etc/resolv.conf 文件立刻得到更新。
如果用戶想要手動指定容器的配置,可以利用下面的選項。
-h HOSTNAME or --hostname=HOSTNAME :
設定容器的主機名,它會被寫到容器內的 /etc/hostname 和 /etc/hosts。但它在容器外部看不到,既不會在 docker ps 中顯示,也不會在其他的容器的 /etc/hosts 看到。
--link=CONTAINER_NAME:ALIAS :
選項會在創建容器的時候,添加一個其他容器的主機名到 /etc/hosts 文件中,讓新容器的進程可以使用主機名 ALIAS 就可以連接它。【上一節容器的連接的時候,使用過,hosts中添加了解析】
--dns=IP_ADDRESS :
添加 DNS 服務器到容器的 /etc/resolv.conf 中,讓容器用這個服務器來解析所有不在 /etc/hosts 中的主機名。
--dns-search=DOMAIN :
設定容器的搜索域,當設定搜索域爲 .example.com 時,在搜索一個名爲 host 的主機時,DNS 不僅搜索host,還會搜索 host.example.com。
注意:如果沒有上述最後 2 個選項,Docker 會默認用主機上的 /etc/resolv.conf 來配置容器。
5.容器訪問控制:
主要通過宿主機的iptables進行訪問權限控制。
6.容器訪問外部網絡:
容器要想訪問外部網絡,需要本地系統的轉發支持。在Linux 系統中,檢查轉發是否打開。
$sysctl net.ipv4.ip_forward net.ipv4.ip_forward = 1
如果爲 0,說明沒有開啓轉發,則需要手動打開。
$sysctl -w net.ipv4.ip_forward=1
如果在啓動 Docker 服務的時候設定 --ip-forward=true, Docker 就會自動設定系統的 ip_forward 參數爲 1。
7.容器之間訪問:
容器之間相互訪問,需要兩方面的支持。
1>容器的網絡拓撲是否已經互聯。默認情況下,所有容器都會被連接到 docker0 網橋上。
2>本地系統的防火牆軟件 -- iptables 是否允許通過。
8.訪問所有端口:
當啓動 Docker 服務時候,默認會添加一條轉發策略到 iptables 的 FORWARD 鏈上。策略爲通過(ACCEPT)還是禁止(DROP)取決於配置--icc=true(缺省值)還是 --icc=false。當然,如果手動指定 --iptables=false 則不會添加 iptables 規則。
可見,默認情況下,不同容器之間是允許網絡互通的。如果爲了安全考慮,可以在 /etc/default/docker 文件中配置 DOCKER_OPTS=--icc=false 來禁止它。
【此處可見docker的默認配置文件是:/etc/default/docker】
9.訪問指定端口:
在通過 -icc=false 關閉網絡訪問後,還可以通過 --link=CONTAINER_NAME:ALIAS 選項來訪問容器的開放端口。
例如,在啓動 Docker 服務時,可以同時使用 icc=false --iptables=true 參數來關閉允許相互的網絡訪問,並讓 Docker 可以修改系統中的 iptables 規則。
此時,系統中的 iptables 規則可能是類似
$ sudo iptables -nL ... Chain FORWARD (policy ACCEPT) target prot opt source destination DROP all -- 0.0.0.0/0 0.0.0.0/0 ...
之後,啓動容器(docker run)時使用 --link=CONTAINER_NAME:ALIAS 選項。Docker 會在 iptable 中爲 兩個容器分別添加一條 ACCEPT 規則,允許相互訪問開放的端口(取決於 Dockerfile 中的 EXPOSE 行)。
當添加了 --link=CONTAINER_NAME:ALIAS 選項後,添加了 iptables 規則。
$ sudo iptables -nL ... Chain FORWARD (policy ACCEPT) target prot opt source destination ACCEPT tcp -- 172.17.0.2 172.17.0.3 tcp spt:80 ACCEPT tcp -- 172.17.0.3 172.17.0.2 tcp dpt:80 DROP all -- 0.0.0.0/0 0.0.0.0/0
注意:--link=CONTAINER_NAME:ALIAS 中的 CONTAINER_NAME 目前必須是 Docker 分配的名字,或使用 --name 參數指定的名字。主機名則不會被識別。
10.映射容器端口到宿主主機的實現
默認情況下,容器可以主動訪問到外部網絡的連接,但是外部網絡無法訪問到容器。
容器訪問外部實現【像pptp ***創建之後,需要通過iptables配置轉發到公網一樣】
容器所有到外部網絡的連接,源地址都會被NAT成本地系統的IP地址。這是使用 iptables 的源地址僞裝操作實現的。
查看主機的 NAT 規則。
$ sudo iptables -t nat -nL ... Chain POSTROUTING (policy ACCEPT) target prot opt source destination MASQUERADE all -- 172.17.0.0/16 !172.17.0.0/16 ...
其中,上述規則將所有源地址在 172.17.0.0/16 網段,目標地址爲其他網段(外部網絡)的流量動態僞裝爲從系統網卡發出。MASQUERADE 跟傳統 SNAT 的好處是它能動態從網卡獲取地址。
釋義: MASQUERADE: 地址僞裝,在iptables中有着和SNAT相近的效果,但也有一些區別。 但使用SNAT的時候,出口ip的地址範圍可以是一個,也可以是多個。 例如:如下命令表示把所有10.8.0.0網段的數據包SNAT成192.168.5.3的ip然後發出去 iptables -t nat -A POSTROUTING -s 10.8.0.0/255.255.255.0 -o eth0 -j SNAT --to-source 192.168.5.3 如下命令表示把所有10.8.0.0網段的數據包SNAT成192.168.5.3/192.168.5.4/192.168.5.5等幾個ip然後發出去 iptables -t nat -A POSTROUTING -s 10.8.0.0/255.255.255.0 -o eth0 -j SNAT --to-source 192.168.5.3-192.168.5.5 這就是SNAT的使用方法,即可以NAT成一個地址,也可以NAT成多個地址 但是,對於SNAT,不管是幾個地址,必須明確的指定要SNAT的ip。 假如當前系統用的是ADSL動態撥號方式,那麼每次撥號,出口ip192.168.5.3都會改變而且改變的幅度很大,不一定是192.168.5.3到192.168.5.5範圍內的地址,這個時候如果按照現在的方式來配置iptables就會出現問題了 : 因爲每次撥號後,服務器地址都會變化,而iptables規則內的ip是不會隨着自動變化的,每次地址變化後都必須手工修改一次iptables,把規則裏邊的固定ip改成新的ip,這樣是非常不好用的,MASQUERADE就是針對這種場景而設計的,他的作用是,從服務器的網卡上,自動獲取當前ip地址來做NAT比如下邊的命令: iptables -t nat -A POSTROUTING -s 10.8.0.0/255.255.255.0 -o eth0 -j MASQUERADE 如此配置的話,不用指定SNAT的目標ip了,不管現在eth0的出口獲得了怎樣的動態ip,MASQUERADE會自動讀取eth0現在的ip地址然後做SNAT出去,這樣就實現了很好的動態SNAT地址轉換 SNAT: 是source network address translation的縮寫,即源地址目標轉換,比如,多個PC機使用ADSL路由器共享上網,每個PC機都配置了內網IP,PC機訪問外部網絡的時候,路由器將數據包的報頭中的源地址替換成路由器的ip當外部網絡的服務器比如網站web服務器接到訪問請求的時候他的日誌記錄下來的是路由器的ip地址,而不是pc機的內網ip這是因爲,這個服務器收到的數據包的報頭裏邊的“源地址”,已經被替換了所以叫做SNAT,基於源地址的地址轉換。 DNAT: 是destination network address translation的縮寫,即目標網絡地址轉換,典型的應用是,有個web服務器放在內網配置內網ip,前端有個防火牆配置公網ip,互聯網上的訪問者使用公網ip來訪問這個網站,當訪問的時候,客戶端發出一個數據包這個數據包的報頭裏邊,目標地址寫的是防火牆的公網ip,防火牆會把這個數據包的報頭改寫一次,將目標地址改寫成web服務器的內網ip,然後再把這個數據包發送到內網的web服務器上這樣,數據包就穿透了防火牆,並從公網ip變成了一個對內網地址的訪問了即DNAT,基於目標的網絡地址轉換。
11.外部訪問容器實現
容器允許外部訪問,可以在 docker run 時候通過 -p 或 -P 參數來啓用。
不管用哪種辦法,其實也是在本地的 iptable 的 nat 表中添加相應的規則。
使用 -P 時:
$ iptables -t nat -nL ... Chain DOCKER (2 references) target prot opt source destination DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:49153 to:172.17.0.2:80 使用 -p 80:80 時: $ iptables -t nat -nL Chain DOCKER (2 references) target prot opt source destination DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.2:80
注意:
這裏的規則映射了 0.0.0.0,意味着將接受主機來自所有接口的流量。用戶可以通過 -p IP:host_port:container_port 或 -p IP::port 來指定允許訪問容器的主機上的 IP、接口等,以制定更嚴格的規則。
如果希望永久綁定到某個固定的 IP 地址,可以在 Docker 配置文件 /etc/default/docker 中指定 DOCKER_OPTS="--ip=IP_ADDRESS",之後重啓 Docker 服務即可生效。
12.配置docker0網橋:
Docker 服務默認會創建一個 docker0 網橋(其實有一個 docker0 內部接口),它在內核層連通了其他的物理或虛擬網卡,這就將所有容器和本地主機都放到同一個物理網絡。
Docker 默認指定了 docker0 接口 的 IP 地址和子網掩碼,讓主機和容器之間可以通過網橋相互通信,它還給出了 MTU(接口允許接收的最大傳輸單元),通常是 1500 Bytes,或宿主主機網絡路由上支持的默認值。這些值都可以在服務啓動的時候進行配置。
--bip=CIDR -- IP 地址加掩碼格式,例如 192.168.1.5/24 --mtu=BYTES -- 覆蓋默認的 Docker mtu 配置
也可以在配置文件中配置 DOCKER_OPTS,然後重啓服務。 由於目前 Docker 網橋是 Linux 網橋,用戶可以使用 brctl show 來查看網橋和端口連接信息。
$ sudo brctl show bridge name bridge id STP enabled interfaces docker0 8000.3a1d7362b4ee no veth65f9 vethdda6
*注:brctl 命令在 Debian、Ubuntu 中可以使用 sudo apt-get install bridge-utils 來安裝。
每次創建一個新容器的時候,Docker 從可用的地址段中選擇一個空閒的 IP 地址分配給容器的 eth0 端口。使用本地主機上 docker0 接口的 IP 作爲所有容器的默認網關。
$ sudo docker run -i -t --rm base /bin/bash $ ip addr show eth0 24: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 32:6f:e0:35:57:91 brd ff:ff:ff:ff:ff:ff inet 172.17.0.3/16 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::306f:e0ff:fe35:5791/64 scope link valid_lft forever preferred_lft forever $ ip route default via 172.17.42.1 dev eth0 172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.3 $ exit
13.自定義網橋:
除了默認的 docker0 網橋,用戶也可以指定網橋來連接各個容器。
在啓動 Docker 服務的時候,使用 -b BRIDGE或--bridge=BRIDGE 來指定使用的網橋。【配置在/etc/default/docker中的DOCKER_OPTS】
如果服務已經運行,那需要先停止服務,並刪除舊的網橋。
$ sudo service docker stop $ sudo ip link set dev docker0 down $ sudo brctl delbr docker0 然後創建一個網橋 bridge0。 $ sudo brctl addbr bridge0 $ sudo ip addr add 192.168.5.1/24 dev bridge0 $ sudo ip link set dev bridge0 up
查看確認網橋創建並啓動。
$ ip addr show bridge0 4: bridge0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state UP group default link/ether 66:38:d0:0d:76:18 brd ff:ff:ff:ff:ff:ff inet 192.168.5.1/24 scope global bridge0 valid_lft forever preferred_lft forever
配置 Docker 服務,默認橋接到創建的網橋上。
【在配置文件的DOCKER_OPTS添加一個參數】
$ echo 'DOCKER_OPTS="-b=bridge0"' >> /etc/default/docker $ sudo service docker start
啓動 Docker 服務。 新建一個容器,可以看到它已經橋接到了 bridge0 上。
可以繼續用 brctl show 命令查看橋接的信息。另外,在容器中可以使用 ip addr 和 ip route 命令來查看 IP 地址配置和路由信息。
14.工具作用以及示例【工具爲擴展學習,如用得到,將會單起筆記】:
在介紹自定義網絡拓撲之前,介紹一些工具:
pipework
Jérme Petazzoni 編寫了一個叫 pipework 的 shell 腳本,可以幫助用戶在比較複雜的場景中完成容器的連接。
playground
Brandon Rhodes 創建了一個提供完整的 Docker 容器網絡拓撲管理的 Python庫,包括路由、NAT 防火牆;以及一些提供 HTTP, SMTP, POP, IMAP, Telnet, SSH, FTP 的服務器。
15.編輯網絡配置文件
Docker 1.2.0 開始支持在運行中的容器裏編輯 /etc/hosts, /etc/hostname 和 /etc/resolve.conf 文件。
但是這些修改是臨時的,只在運行的容器中保留,容器終止或重啓後並不會被保存下來。也不會被 docker commit 提交。
16.創建一個點到點連接
默認情況下,Docker 會將所有容器連接到由 docker0 提供的虛擬子網中。
用戶有時候需要兩個容器之間可以直連通信,而不用通過主機網橋進行橋接。
解決辦法很簡單:創建一對 peer 接口,分別放到兩個容器中,配置成點到點鏈路類型即可。
首先啓動 2 個容器:
$ sudo docker run -i -t --rm --net=none base /bin/bash root@1f1f4c1f931a:/# $ sudo docker run -i -t --rm --net=none base /bin/bash root@12e343489d2f:/#
找到進程號,然後創建網絡名字空間的跟蹤文件。
$ sudo docker inspect -f '``.`State`.`Pid`' 1f1f4c1f931a 2989 $ sudo docker inspect -f '``.`State`.`Pid`' 12e343489d2f 3004 $ sudo mkdir -p /var/run/netns $ sudo ln -s /proc/2989/ns/net /var/run/netns/2989 $ sudo ln -s /proc/3004/ns/net /var/run/netns/3004
創建一對 peer 接口,然後配置路由
$ sudo ip link add A type veth peer name B $ sudo ip link set A netns 2989 $ sudo ip netns exec 2989 ip addr add 10.1.1.1/32 dev A $ sudo ip netns exec 2989 ip link set A up $ sudo ip netns exec 2989 ip route add 10.1.1.2/32 dev A $ sudo ip link set B netns 3004 $ sudo ip netns exec 3004 ip addr add 10.1.1.2/32 dev B $ sudo ip netns exec 3004 ip link set B up $ sudo ip netns exec 3004 ip route add 10.1.1.1/32 dev B