Docker的基本操作

風靈使發表於2018-09-17
#1.列出當前系統中所有的docker映象
docker image ls 
#舊版本:docker images
#該命令會列出倉庫、映象名(tag)、映象ID、建立時間、映象大小
#docker的映象是多層儲存結構的,由於docker使用的是Union FS檔案系統,相同的層檔案只需要儲存一份;
#因此映象的總大小可能比列出來的總和要小的多;可以用使用以下命令檢視映象、容器、資料卷所佔用的空間:
docker system df

#2.虛懸映象
#如果我們使用docker build 構建同名映象或者使用docker pull拉取同名映象,本地的同名映象的倉庫和映象名就會變成<none>;
#此時的映象稱為虛懸映象,此類映象已經沒有存在的必要,可以刪除:
#專門顯示此類映象的命令:
docker image ls -f dangling=true

#刪除此類映象的命令:
docker image purne

#3.中間層映象
#由於docker是多層結構,在使用一段時間後,系統中會出現很多中間層依賴映象,預設的docker image ls只顯示頂層映象;如果希望
#檢視所有映象,可以使用以下命令:(可能會看到很多無標籤的映象,此類映象為其他映象的依賴映象,不能刪除)
docker image ls -a
docker image ls -a -q (只顯示映象Id)


#4.更多檢視指令
#4.1檢視指定倉庫映象
docker image ls ubuntu

#4.2 檢視指定映象
docker image ls ubuntu:14.04

#4.3檢視自從某個時間之後的映象
docker image ls -f since=ubuntu:14.04

#4.4按指定格式顯示映象(格式按照go的模板引數格式)
docker image ls --format "{{.ID}}: {{.Repository}}"


#5.刪除映象(只能刪除沒有容器的映象;如果使用該映象執行了容器,則需先刪除依賴的容器再刪除該映象)
docker image rm [映象id] [映象名]
#對應老版本的docker rmi
#由於映象是分層儲存的,刪除過程會一層一層刪除;並且docker多個標籤可以對應一個映象,當刪除一個標籤時,還有其他標籤指向
#該映象時,docker image rm 只會執行untagged指令,不會執行deleted指令,只有當沒有標籤對應該映象時;才會真正刪除該映象

#刪除所有映象
docker image rm $(docker image ls -q)

Docker Volume操作

1.建立單獨的volume

docker volume create --name test_v 

2.通過執行時+ -v引數來指定volume

docker run -it -v /data ubuntu:14.04 bash

以上兩個命令docker會在本地主機上自動生成一個隨機目錄掛載到容器內

3.執行時指定目錄掛載到容器

docker run -it -v `pwd`:/data ubuntu:14.04 bash

指定當前目錄掛載到容器的/data目錄上,此時如果映象本身指定了/data作為volume,則原來的目錄內的檔案不會拷貝到容器中;主機的當前目錄檔案會拷貝到容器的/data目錄;

4.執行時指定容器卷掛載到容器

docker run -it -v test_v:/data ubuntu:14.04 bash

此時如果docker volumels中如果沒有test_v這個容器卷,則docker會自動建立名為test_v的容器卷;

如果執行容器時,沒有指定目錄或者容器卷,而使用docker自動生成的目錄作為卷掛載到容器中的,
執行docker rm container -v會把卷中的所有檔案一併刪除;其他兩種方式的檔案不會刪除

linux網路橋接

檢視網路名字空間

ip netns list

檢視當前的網橋、網路卡列表

ip link list

建立網路名字空間

ip netns add netns_test

新增一對虛擬網路卡

ip link add veth_1 type veth peer name eth_1

將其中一塊虛擬網路卡新增進網路名字空間netns_test

ip link set eth_1 netns netns_test

給網路名字空間的網路卡配置ip

ip netns exec netns_test ip addr add 10.0.0.2/24 dev eth_1

啟動網路名字空間裡面的虛擬網路卡

ip netns exec netns_test ip link set dev eth_1 up

給主機的虛擬網路卡配置Ip

ip addr add 10.0.0.1/24 dev veth_1

啟動主機的虛擬網路卡

ip link set dev veth_1 up

網路名字空間的虛擬網路卡ping主機的網路卡

ip netns exec netns_test ping 10.0.0.1

主機虛擬網路卡ping網路名字空間的虛擬網路卡

ping 10.0.0.2

刪除網路名字空間

ip netns delete netns_test

刪除網路名字空間虛擬網路卡

ip netns exec netns_test ip link delete eth_1

刪除虛擬網路卡

ip link delete veth_1

刪除網橋

brctl delbr br_name

從網橋上的移除網路卡

brctl delif br_name eth_name1 eth_name2

預設情況下,docker中所有容器的虛擬網路卡都是成對存在的,一個存在主機(veth[xxxxx]),掛載在docker0這個網橋上,另一個掛載在容器的網路名字空間裡面(eth0);所以,主機上的所有容器都可以通過內網IP進行通訊。

練習:配置docker容器的網路

1.首先,啟動兩沒有網路配置的容器

docker run --rm -it --net=none --name docker1 ubuntu:14.04 bash
docker run --rm -it --net=none --name docker2 ubuntu:14.04 bash

2.查詢兩docker容器的程式id,並對各自的網路名字空間設定軟連結

docker inspect --format '{{ .State.Pid}}' docker1
6225 
docker inspect --format '{{ .State.Pid}}' docker2
6385

sudo ln -s /proc/6225/ns/net /var/run/netns/netns_docker_1
sudo ln -s /proc/6385/ns/net /var/run/netns/netns_docker_1

3.新增兩對(4塊)虛擬網路卡

sudo ip link add veth1 type veth peer name eth1
sudo ip link add veth2 type veth peer name eth2

4.將兩塊網路卡分別設定進相應容器的網路名字空間

sudo ip link set eth1 netns netns_docker_1
sudo ip link set eth2 netns netns_docker_2

5.分別給網路名字空間裡面的網路卡設定ip,並啟動網路卡

sudo ip netns exec netns_docker_1 ip addr add 10.0.0.2/24 dev eth1
sudo ip netns exec netns_docker_2 ip addr add 10.0.0.3/24 dev eth2
sudo ip netns exec netns_docker_1 ip link set dev eth1 up
sudo ip netns exec netns_docker_2 ip link set dev eth2 up

6.新增虛擬網橋,並將剛才建立的虛擬網路卡中的剩餘兩塊配置在網橋上,並啟動

sudo brctl addbr br0
brctl addif br0 veth1 veth2
sudo ifconfig br0 up
sudo ifconfig veth1 up
sudo ifconfig veth2 up

7.在兩容器中通訊


tools.py

#!/bin/env  python
#-*- encoding:utf-8 -*-

import os
import json
import hashlib
import urlparse
import functools
import requests


#1.獲取映象tag列表
TAG_LIST_URL = "http://127.0.0.1:5000/v2/ubuntu/tags/list"
#2.獲取映象的manifest
MANIFEST_INFO_URL = "http://127.0.0.1:5000/v2/ubuntu/manifests/16.04"
#3.獲取服務中的倉庫列表
REPOSITORIES_LIST_URL = "http://127.0.0.1:5000/v2/_catalog"

headers = {
    'Accept': 'application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.docker.distribution.manifest.v1+prettyjws, application/json, application/vnd.docker.distribution.manifest.v2+json'
}


DOMAIN = "http://127.0.0.1:5000/v2/"
DOCKERPATH = "/var/lib/docker"
DOCKERPATH = "/data/docker"
DOCKERDRIVER = "overlay2"

def read_json(fn, key, default=None):
    """get data from json file"""
    if not os.path.exists(fn):
        return default
    with open(fn) as fd:
        data = fd.read()
        try:
            return json.loads(data).get(key, default)
        except:
            pass
    return default

def read_data(fn):
    """read data from normal file"""
    if not os.path.exists(fn):
        return ""
    with open(fn) as fd:
        return fd.read().strip()
    return ""

def get_manifest_info(image, tag):
    """request image manifest, which contains config and layers info"""
    url = urlparse.urljoin(DOMAIN, image+"/manifests/"+tag)
    rep = requests.get(url, headers=headers)
    headdigest = rep.headers['docker-content-digest'].split(":")[1]
    contdigest = hashlib.sha256(rep.text).hexdigest()
    if headdigest == contdigest:
        print(rep.text)
        return rep.text
    return ""

def echo_image_info(imageid):
    path = os.path.join(DOCKERPATH, "image", DOCKERDRIVER,
                        "imagedb/content/sha256", imageid)
    if not os.path.exists(path):
        print("Image[%s] metadata:%s not exists "%(imageid, path))
        return
    diffids = read_json(path, "rootfs", {}).get("diff_ids", [])
    laymeta = diffid_to_layermetadata(diffids)
    laymeta = map(lambda x:
                  DOCKERPATH+"/image/"+DOCKERDRIVER+"/layerdb/sha256/"+x,
                  laymeta)
    layers = map(laymeta_to_layer, laymeta)
    imageinfo = {
        "image_metadata": path,
        "diff_ids": diffids,
        "layers_metapath": laymeta,
        "layers_path": layers,
    }
    print(json.dumps(imageinfo, indent=4))

def laymeta_to_layer(laypath):
    layer = read_data(laypath+"/cache-id")
    return DOCKERPATH+"/"+DOCKERDRIVER+"/"+layer if layer else ""

def diffid_to_layermetadata(diffids):
    """通過diffid計算各層layer的目錄名,layer後設資料的存放位置"""
    if not diffids: return diffids
    digest = []
    digest.append(diffids[0].split(":")[1])
    def calc_chainid(sli, x, y):
        chainid = hashlib.sha256(x + " " + y).hexdigest()
        sli.append(chainid)
        return "sha256:"+chainid
    reduce(functools.partial(calc_chainid, digest), diffids)
    return digest

def calc_chainid(diffids):
    """chainid的計算方法"""
    difflen = len(diffids)
    if difflen == 1:
        return diffids[0]
    elif difflen == 2:
        return "sha256:"+hashlib.sha256(diffids[0] + " " +
                                        diffids[1]).hesdigest()
    return calc_chainid([calc_chainid(diffids[:difflen-1]), diffids[difflen-1]])

def main():
    data = get_manifest_info("ubuntu", "16.04")
    imageid = json.loads(data).get("config", {}).get("digest", "").split(":")[1]
    print("Image:[ubuntu:16.04] ID:[%s]"%imageid)
    echo_image_info(imageid)


if __name__ == "__main__":
    main()

centos_docker_install.sh

#!/bin/bash
#Centos7 安裝docker

#1.刪除舊版本
sudo yum remove -y docker-ce docker docker-common docker-selinux docker-engine

#2.安裝依賴包
sudo yum install -y yum-utils device-mapper-persistent-data lvm

#3.替換國內源
sudo yum-config-manager --add-repo https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo
#阿里源
#sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#官方源
#sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

#4.安裝docker-ce軟體包
sudo yum makecache fast
sudo yum install -y docker-ce

#5.預設情況下, docker 命令會使用 Unix socket 與 Docker 引擎通訊。而只有 root 使用者和docker 組的使用者才可以訪問 
#Docker 引擎的 Unix socket。出於安全考慮,一般 Linux 系統上不會直接使用 root 使用者。因此,更好地做法是將需要使
#用 docker 的使用者加入 docker使用者組
sudo groupadd docker
sudo usermod -aG docker $USER

#6.開啟開機啟動(新版本)
sudo mkdir /etc/docker && sudo cp ./daemon.json /etc/docker/ -f
sudo systemctl enable docker
sudo systemctl start docker


#預設配置下,如果在 CentOS 使用 Docker CE 看到下面的這些警告資訊:
#	WARNING: bridge-nf-call-iptables is disabled
#	WARNING: bridge-nf-call-ip6tables is disabled
#請新增核心配置引數以啟用這些功能。
#$ sudo tee -a /etc/sysctl.conf <<-EOF
#net.bridge.bridge-nf-call-ip6tables = 1
#net.bridge.bridge-nf-call-iptables = 1
#net.ipv4.ip_forward = 1
#EOF
#然後重新載入 sysctl.conf 即可
#$ sudo sysctl -p

#7.配置映象加速器
#vi /etc/docker/daemon.json
#新增以下內容
#{
#	"registry-mirrors": [
#		"https://registry.docker-cn.com"
#	]
#}
#重啟服務
#sudo systemctl daemon-reload
#sudo systemctl restart docker

相關文章