docker_note_4_數據卷和數據卷容器

14. 數據卷和數據卷容器

  1. 本節課主要講解如何在Docker內部及容器之間管理數據。
    容器中管理數據主要有兩種方式:
    數據卷(Data volumes)
    數據卷容器(Data volume containers)
  2. 數據卷:是一個可供一個或多個容器使用的特殊目錄,它繞過UFS,可以提供很多有用的特性:
    a.數據卷可以在容器之間共享和重用
    b.對數據卷的修改會立馬生效
    c.對數據卷的更新,不會影響鏡像
    d.卷會一直存在,直到沒有容器使用
    *數據卷的使用,類似於Linux 下對目錄或文件進行mount。
  3. 創建數據卷
    docker run -d -P -it --name web1 -v /webapp training/webapp /bin/bash
    -v標記創建一個數據卷並且掛載到容器裏。
    --name指定容器的名稱
    -d是指守護狀態下運行(daemon)
    -P 隨機爲容器分配外網到容器的IP映射
    
    啓動之後,使用docker attach命令進入守護狀態運行的容器中
    除此之外,還可以掛載主機目錄作爲數據卷
    docker run -d -P -it --name web2 -v /root/docker:/opt/docker training/webapp /bin/bash
    docker掛載的數據卷默認是可讀可寫的
    若要指定爲只讀,可以加權限限制:ro
    docker run -d -P -it --name web3 -v /root/docker:/opt/docker:ro training/webapp /bin/bash
    也可以掛載單個文件到容器
    docker run -d -P -it --name web4 -v ~/.bash_history:/.bash_history training/webapp /bin/bash
    解決容器內部permission denied問題:
    在運行容器的時候,給容器加特權,及加上--privileged=true參數。使用該參數,容器內的root擁有真正的root權限.否則,容器內的root只是外部的一個普通用戶權限
    sudo docker run -itd -P --name data5 --privileged=true  -v  ~/download:/opt/download centos /bin/bash
    
  4. 數據卷容器:是一個正常的容器,專門用來提供數據卷供其他容器掛載
    建立數據卷容器:
    sudo docker run -idt -v /database --name db_ori training/postgres /bin/bash
    sudo docker run --name db_0 -idt -e POSTGRES_PASSWORD=password --volumes-from db_ori postgres /bin/bash
    
    在其他容器中使用–volumes-from掛載db容器中的數據卷
    sudo docker run --name db_0 -idt -e POSTGRES_PASSWORD=password --volumes-from db_ori postgres /bin/bash
    
    可以看到數據卷容器,在多個容器中掛載之後是數據共享的。
  5. 數據卷不會被自動刪除,要刪除一個數據卷,必須在刪除最後一個掛着該數據卷的容器是指定-v參數,如下
    docker rm -v name

15.數據卷容器備份、恢復、遷移數據卷

  1. 使用數據捲來備份數據,通過指定本地的一個文件路徑,對應到容器中的路徑,運行tar命令將重要的文件打包備份。
    # docker run --volumes-from db -v $(pwd):/docker --name db6 -it centos /bin/bash	
    sudo docker run -d -it --volumes-from db_ori -v $(pwd):/download --name db6 -e POSTGRES_PASSWORD=password --privileged=true centos /bin/bash
    
    將database目錄備份打包到docker目錄下
    tar cvf ./docker/database_20171022_bak.tar database
    [root@8e0e678bc7be download]# tar cvf ./database.tar /database/
    
    完成之後退出容器,發現本地目錄的docker目錄下有從數據卷容器打包備份出來的database.tar文件
  2. 恢復數據卷容器:
    要將數據恢復到數據卷容器,首先要創建一個帶有數據卷的容器db10
    docker run -d -it -v /db10 --name database2 centos /bin/bash
    然後創建另外一個容器,掛載database2容器,只有使用tar xvf解壓文件到掛載的容器卷中。
    docker run -it -d --volumes-from database2 -v $(pwd):/docker centos /bin/bash

16.Docker容器綁定外部IP和端口

  1. Docker允許通過外部訪問容器或者容器之間互聯的方式來提供網絡服務。
  2. 首先是外部訪問容器:
    容器啓動之後,容器中可以運行一些網絡應用,通過-p或-P參數來指定端口映射,使用-P(大寫)標記時,docker會隨機選擇一個端口映射到容器內部開放的網絡端口上。此時訪問本機的32786端口就可以訪問到容器內web應用提供的界面。也可以使用docker logs來查看應用的信息,使用-p(小寫)則可以指定要映射的端口,並且在一個指定端口上只可以綁定一個容器,支持的格式有:
ip:hostport:containerport ip::containerport hostport:containerport
docker run -d -p 5000:5000 training/webapp python app.py

看到本地5000端口已經被映射,換一個端口5001運行成功,在頁面上輸入5001端口訪問如下
docker 默認會映射本地所有的地址。現在我們來嘗試一下映射到指定地址的指定端口
docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py
然後要訪問容器中的應用只能通過127.0.0.1這個ip訪問。
接下來是綁定本機的任意端口到容器的5000端口
docker run -d -p 127.0.0.1::5000 training/webapp python app.py
還可以指定通信協議
docker run -d -p 5003:5000/udp training/webapp python app.py
3. 那我們怎樣來查看docker裏面容易綁定和映射的端口及Ip地址呢?可以使用docker port
4. 需要注意的是:
a. 容器內部有自己的內部網絡和ip地址,可以使用docker inspect來查看
b. 在啓動容器的時候,可以多次使用-p標記來綁定多個端口
docker run -d -p 5005:5000 -p 5006:80 training/webapp python app.py

17.容器互聯

  1. 除了端口映射之外,容器互聯是另一種跟容器應用交互的方式。它會在源容器和接收容器之間建立一個隧道,接收容器可以看到源容器指定的信息。
  2. 要實現容器互聯,需要爲容器指定一個好記的名字,通過–name來制定,若不指定,docker會隨機生成一個容器的名稱,但這不利於記憶。
    docker inspect可以查看容器的很多信息。查看容器名稱可以使用
    docker inspect -f "{{.Name}}" test1
    不指定-f "{{.Name}}"則會顯示所有的信息
    若一個容器是臨時的,運行完成之後要自動刪除,需要加上–rm標記。
  3. 容器互聯:使用--link參數,可以讓容器之間安全的進行交互
    a. 先穿件一個數據庫容器
    docker run -d --name db training/postgres
    b. 新建一個容器和postgres容器互聯
    docker run -d -P --name web --link db:db training/webapp python app.py
    –link表示建立容器互聯,參數爲name:alias,name是要鏈接的容器名稱,alias是我們取得別名
    通過–link的方式,是web和db建立了鏈接,我們可以查看下web容器的環境變量
    docker run --rm --name web2 --link db:db training/webapp env
    可以看到環境變量中以要鏈接的容器的名字的別名的大寫作爲前綴,和db建立連接之後,除了web容器環境變量發生了變
    化,在web容器的hosts文件也發生了變化,我們可以看下
    docker run -it --rm --link db:db training/webapp /bin/bash
    這裏面有兩個ip,一個是web的,一個是db的,我們可以用ping命令查看這個兩個ip之間能否ping通
    建立鏈接沒問題!
    我們啓動db容器的時候,沒有通過-p指定端口,避免了數據庫端口暴露在外部網絡,這樣很安全。

18.一個完整的例子

  1. 例子主要完成自己鏡像的製作,端口映射,Dockerfile文件編寫,鏡像上傳DockerHub完成鏡像的分享。
    首先選擇一個合適的目錄:
    /root/docker/hello
  2. 首先創建Dockerfile:裏面定義了我們構建鏡像的指令步驟。具體定義如下:
    #一個基礎的python運行環境
    FROM python
    #設置工作目錄
    WORKDIR /app
    #將當前系統文件夾內容複製到容器的app目錄
    ADD . /app
    #安裝必要的依賴包
    RUN pip install -r softwares.txt
    #開放端口,供容器外訪問
    EXPOSE 80
    #定義環境變量
    ENV NAME Hello_docker
    #運行命令
    CMD [“python”,“app.py”]
    在Dockerfile中定義了我們要在容器中運行pip install命令安裝軟件,軟件定義在softwares.txt中,要使用python命
    令運行app.py文件,因此這兩個文件需要我們定義
    softwares.txt文件定義內容
Flask
Redis

app.py文件內容

from flask import Flask
from redis import Redis, RedisError
import os
import socket# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)app = Flask(_
_name__)@app.route("/")
def hello():
	try:
		visits = redis.incr("counter")
	except RedisError:
		visits = "<i>cannot connect to Redis, counter disabled</i>" 
		html = "<h3>Hello {name}!</h3>" \
		"<b>Hostname:</b> {hostname}<br/>" \
		"<b>Visits:</b> {visits}"
return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)

if __name__ == "__main__":
	app.run(host='0.0.0.0', port=80)
  1. 使用docker buil構建鏡像
    docker build -t hello .
    運行完成之後
    使用docker images查看
    查看/app目錄有Dockerfile、app.py、softwares.txt三個文件
    使用-p映射宿主機端口9876,啓動容器hello
    docker run -p 9876:80 hello
    網頁訪問,這裏配置了hosts文件,hadoop2對應的機器ip如下:
    由於沒有啓動redis,很明顯app.py文件中拋出了不能夠連接到redis中。這個地方出來使用瀏覽器驗證,也可以使用
    curl http://hadoop2:9876來驗證
    這個地方我們沒有配置redis,那我們就來配置下redis吧
    首先使用docker search redis
    國內網速較慢,選擇紅框中的鏡像,下載要快些。
    啓動docker
    啓動redis容器
    docker run --name redis -d redis
    使用docker-pid redis找到redis容器對應的進程id
    使用nsenter --target 23348 --mount --uts --ipc --net --pid進入這個守護進程
    在根目錄下有run.sh腳本
    chmod 700 run.sh賦予運行權限
    執行./run.sh
    redis啓動起來了
    我們再啓動一個容器,運行我們的hello鏡像
    docker run -d --name hello --link redis:redis -p 9876:80 hello
    通過nsenter工具進入這個容器中,修改app目錄下的app.py文件。將
    redis = Redis(host=“redis”, db=0, socket_connect_timeout=2, socket_timeout=2)改爲:
    redis = Redis(host=“redis”, db=0, socket_connect_timeout=2,
    socket_timeout=2,password=‘QOiTIvQ4ST2NVZHiT97wXme2OrV2xmka’)
    保存退出容器,重啓docker restart hello容器
    現在瀏覽器中訪問:hadoop2:9876
    刷新瀏覽器可以看到redis中記錄的訪問數在增加了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章