Docker最新版19.03 詳細教程

狂神說JAVA的嗶哩嗶哩主頁

文章目錄


Docker 容器本質上是宿主機上的一個進程。Docker 通過 namespace 實現了資源隔離,通過 cgroups 實現了資源的限制,通過寫時複製機制(copy-on-write)實現了高效的文件操作。

Docker有五個命名空間:進程、網絡、掛載、宿主和共享內存,爲了隔離有問題的應用,Docker運用Namespace將進程隔離,爲進程或進程組創建已隔離的運行空間,爲進程提供不同的命名空間視圖。這樣,每一個隔離出來的進程組,對外就表現爲一個container(容器)。需要注意的是,Docker讓用戶誤以爲自己佔據了全部資源,但這並不是”虛擬機”。

概念

Docker 中的三個概念:鏡像,容器,倉庫

鏡像(image):

Docker 鏡像就是一個只讀的模板,鏡像可以用來創建 Docker 容器。Docker 提供了一個很簡單的機制來創建鏡像或者更新現有的鏡像,用戶甚至可以直接從其他人那裏下載一個已經做好的鏡像來直接使用。鏡像是一種文件結構。Dockerfile中的每條命令都會在文件系統中創建一個新的層次結構,文件系統在這些層次上構建起來,鏡像就構建於這些聯合的文件系統之上。Docker官方網站專門有一個頁面來存儲所有可用的鏡像,網址是:index.docker.io。

例如:一個鏡像可以包含一個完整的CentOS操作系統環境,裏面僅安裝了Nginx或用戶需要的其他應用程序。鏡像可以用來創建Docker容器。

容器( Container):

容器是從鏡像創建的運行實例。它可以被啓動、開始、停止、刪除。每個容器都是相互隔離的、保證安全的平臺。可以把容器看做是一個簡易版的 Linux 環境,Docker 利用容器來運行應用。鏡像是隻讀的,容器在啓動的時候創建一層可寫層作爲最上層。

注意:鏡像是隻讀的,容器在啓動的時候創建一層可寫層作爲最上層。

倉庫:

倉庫是集中存放鏡像文件的場所,有時候把倉庫和倉庫註冊服務器(Registry)混爲一談,並不嚴格區分。倉庫註冊服務器(Registry)上往往存放着多個倉庫,每個倉庫中又包含了多個鏡像,每個鏡像有不同的標籤(tag)。目前,最大的公開倉庫是 Docker Hub,存放了數量龐大的鏡像供用戶下載。

倉庫分爲公開倉庫(Public)和私有倉庫(Private)兩種形式。

Docker倉庫用來保存我們的images,當我們創建了自己的image之後我們就可以使用push命令將它上傳到公有或者私有倉庫,這樣下次要在另外一臺機器上使用這個image時候,只需要從倉庫上pull下來就可以了。

注意:Docker 倉庫的概念跟 Git 類似,註冊服務器可以理解爲 GitHub 這樣的託管服務。

一、基礎環境

基礎配置

NAT
192.168.0.10	K8s-master
192.168.0.20	K8s-node01
192.168.0.30	K8s-node02

LAN
172.16.0.10	K8s-master
172.16.0.20	K8s-node01
172.16.0.30	K8s-node02

基礎優化配置三臺環境

echo 'net.ipv4.ip_forward=1 ' >>/etc/sysctl.conf 
echo 'net.ipv4.tcp_tw_recycle=1 ' >>/etc/sysctl.conf
echo 'net.ipv4.tcp_tw_reuse=1 ' >>/etc/sysctl.conf 
sysctl -p
chmod +x /etc/rc.d/rc.local
yum install -y mlocate lrzsz tree vim nc nmap wget bash-completion bash-completion-extras htop iotop iftop lsof net-tools sysstat unzip bc psmisc ntpdate wc telnet-server bind-utils sshpass

配置yum源

curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

在master節點上分發ssh祕鑰

[root@K8s-master ~]# cat fenfa_pub.sh 
#!/bin/bash
ssh-keygen -t rsa -f ~/.ssh/id_rsa -P ''
for ip in 20 30 
do
 sshpass -p123456 ssh-copy-id -o StrictHostKeyChecking=no 172.16.0.$ip
done

sh fenfa_pub.sh

在master節點上爲其他node節點分發hosts文件

[root@k8s-master ~]# cat /etc/hosts
172.16.0.10	k8s-master
172.16.0.20	k8s-node01
172.16.0.30	K8s-node02

for ip in 20 30 ;do scp -rp /etc/hosts 172.16.0.$ip:/etc/hosts ;done

二、最新版19.03安裝

https://docs.docker.com/engine/install/centos/

注意:確保自己的linux系統內核版本高於3.10,並且系統是64位,才能體驗Docker。

[root@k8s-master ~]# uname -r
3.10.0-957.el7.x86_64

官方幫助文檔:

較舊的Docker版本稱爲dockerdocker-engine。如果已安裝這些程序,請卸載它們以及相關的依賴項。

# 1. 卸載舊版本
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
                  
# 2. 使用存儲庫安裝
yum install -y yum-utils

# 3. 設置鏡像倉庫(修改爲國內源地址)
yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 5. 更新索引
yum makecache fast

# 4. 安裝docker相關的依賴 默認最新版(docker-ce:社區版 ee:企業版)
yum install docker-ce docker-ce-cli containerd.io -y

#5. 安裝特定docker版本(先列出列出可用版本)
yum list docker-ce --showduplicates | sort -r
yum install docker-ce-19.03.9 docker-ce-cli-19.03.9 containerd.io

# 6. 啓動docker
systemctl start docker
systemctl enable docker

# 7. 查看版本
[root@k8s-master ~]# docker --version
Docker version 19.03.11, build 42e35e61f3

配置docker鏡像加速器

鏡像加速器:阿里雲加速器,daocloud加速器,中科大加速器

Docker 中國官方鏡像加速:https://registry.docker-cn.com

mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://registry.docker-cn.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker

卸載docker

# 1. 卸載依賴
yum remove docker-ce docker-ce-cli containerd.io

# 2. 刪除資源(默認工作路徑)
rm -rf /var/lib/docker

ansible命令部署多臺docker環境(需要配置ssh免祕鑰)

# 1. 安裝ansible
yum install ansible -y

# 2. 添加hosts文件列表(所有節點的IP地址)
[root@k8s-master ~]# vim /etc/ansible/hosts
...
[master]
172.16.0.10
[node]
172.16.0.20
172.16.0.30

# 3. 測試連通性
[root@k8s-master ~]# ansible all -a 'hostname'
172.16.0.20 | CHANGED | rc=0 >>
k8s-node01
172.16.0.30 | CHANGED | rc=0 >>
k8s-node02
172.16.0.10 | CHANGED | rc=0 >>
k8s-master

# 3.卸載舊版本(沒有寫playbook文件)
ansible all -m yum -a 'name=docker,docker-client,docker-client-latest.docker-common,docker-latest,docker-latest-logrotate,docker-logrotate,docker-engine state=absent'
# 4. 安裝yum-utils
ansible all -m yum -a 'name=yum-utils state=installed'
# 5. 設置國內鏡像倉庫
ansible all -m shell -a 'yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo'
# 6. 更新yum
ansible all -m shell -a 'yum makecache fast'
# 7. 安裝docker相關的依賴
ansible all -m yum -a 'name=docker-ce,docker-ce-cli,containerd.io state=installed'
# 8. 啓動docker
ansible all -m service -a 'name=docker state=started enabled=yes'

三、Docker常用命令

幫助命令

官方命令文檔

docker version		#顯示docker版本信息
docker info				#顯示docker系統信息,包括鏡像和容器的數量
docker --help			#幫助

鏡像命令

https://docs.docker.com/engine/reference/commandline/images/

[root@openvpn ~]# docker images
REPOSITORY          TAG     IMAGE ID      CREATED       SIZE
kylemanna/openvpn   2.4  c504c01ae011   2 years ago   15.6MB

#解釋
REPOSITORY  鏡像的倉庫源
TAG         鏡像的標籤 
IMAGE ID    鏡像的id         
CREATED     鏡像的創建時間 
SIZE        鏡像的大小

#可選參數
-a --all		#列出所有鏡像
-q --quiet	#只顯示鏡像ID

搜索鏡像命令

https://docs.docker.com/engine/reference/commandline/search/

[root@k8s-master ~]# docker search mysql --filter=stars=5000
NAME                DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
mysql               MySQL is a widely used, open-source relation…   9636                [OK]    

#可選參數
--filter=stars=5000		#顯示至少x個星標的

下載鏡像命令

https://docs.docker.com/engine/reference/commandline/pull/

#下載鏡像 docker pull [鏡像名:tag]
[root@k8s-master ~]# docker pull mysql
Using default tag: latest	#如果不寫tag,默認下載latest
latest: Pulling from library/mysql
8559a31e96f4: Pull complete #分層下載,docker image的核心 聯合文件系統
d51ce1c2e575: Pull complete 
c2344adc4858: Pull complete 
fcf3ceff18fc: Pull complete 
16da0c38dc5b: Pull complete 
b905d1797e97: Pull complete 
4b50d1c6b05c: Pull complete 
c75914a65ca2: Pull complete 
1ae8042bdd09: Pull complete 
453ac13c00a3: Pull complete 
9e680cd72f08: Pull complete 
a6b5dc864b6c: Pull complete 
Digest: sha256:8b7b328a7ff6de46ef96bcf83af048cb00a1c86282bfca0cb119c84568b4caf6
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest	#真實地址

#等同的命令
docker pull mysql
docker pull docker.io/library/mysql:latest

#通過tag下載
[root@k8s-master ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
8559a31e96f4: Already exists 	#已下載的分層跳過,直接下載修改的內容
d51ce1c2e575: Already exists 
c2344adc4858: Already exists 
fcf3ceff18fc: Already exists 
16da0c38dc5b: Already exists 
b905d1797e97: Already exists 
4b50d1c6b05c: Already exists 
d85174a87144: Pull complete 
a4ad33703fa8: Pull complete 
f7a5433ce20d: Pull complete 
3dcd2a278b4a: Pull complete 
Digest: sha256:32f9d9a069f7a735e28fd44ea944d53c61f990ba71460c5c183e610854ca4854
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

刪除鏡像命令

#刪除鏡像
docker rmi -f [鏡像id] [鏡像id]

-f	強制刪除圖像

#刪除所有鏡像
docker rmi `docker images -qa`

導出鏡像

# 導出鏡像
docker image save centos -o docker-centos7.6.tar.gz

導入鏡像

# 導入鏡像
docker load -i docker-centos7.6.tar.gz

容器命令

說明:有了鏡像纔可以創建容器,在linux裏 下載一個centos的鏡像來測試

[root@k8s-master ~]# docker pull centos	

新建容器並啓動

docker run [參數] image

#參數說明
--name='Name' 區分容器
-d						後臺方式運行
-it						使用交互方式運行,進入容器查看內容
-p [小寫]			 指定容器的端口 -p 8080:8080
	-p ip:主機端口:容器端口
	-p 主機端口:容器端口
	-p 容器端口
-P [大寫]			 隨機指定端口
-rm						容器退出後隨之將其刪除

#啓動並進入容器
[root@k8s-master ~]# docker run -it centos:latest  /bin/bash
[root@f17bd1e56cbf /]# ls
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr

#從容器中退回主機
[root@f17bd1e56cbf /]# exit
exit
[root@k8s-master ~]#

容器資源限制的參數
在這裏插入圖片描述

列出所有的運行的容器

#docker ps 命令
-a 		#列出當前所有的容器
-q		#顯示容器的編號
-n=1	#顯示最近創建的容器

[root@k8s-master /]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@k8s-master /]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
f17bd1e56cbf        centos:latest       "/bin/bash"         6 minutes ago       Exited (0) 3 minutes ago                       exciting_benz

退出容器

exit				#直接容器停止並退出
ctrl +P +Q	#容器不停止退出

[root@8df0a450ef49 /]# #輸入ctrl+PQ
[root@8df0a450ef49 /]# read escape sequence
[root@k8s-master /]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
8df0a450ef49        centos              "/bin/bash"         48 seconds ago      Up 48 seconds                           elegant_nash

刪除容器

docker rm 容器id								#刪除指定的容器,不能正在刪除正在運行的容器
docker rm -f $(docker ps -aq)  	#刪除所有容器
docker ps -aq|xargs docker rm		#刪除所有容器

啓動和停止容器的操作

docker start 			#啓動容器
docker restart		#重啓容器
docker stop				#關閉當前運行的容器
docker kill				#強制關閉當前容器
docker stats 			#容器佔用內存狀態

常用其他命令

後臺啓動容器

#問題!
#命令 docker run -d [鏡像名] 啓動容器失敗
[root@k8s-master /]# docker run -d centos
045d6e51f4ebf39aec13bfe19172ceb34081bd69921108f684cfc879bc58ab29

#docker ps 會發現centos停止了
[root@k8s-master /]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
045d6e51f4eb        centos              "/bin/bash"         7 seconds ago       Exited (0) 6 seconds ago                       optimistic_benz

#常見的坑,docker 容器使用後臺運行,就必須要有一個前臺進程,docker發現沒有應用,就會自動停止

查看日誌

https://docs.docker.com/engine/reference/commandline/logs/

#運行一個容器,會發現沒有日誌
docker logs -f -t --tail 10 [容器id]

-f 			#跟蹤日誌輸出
-t			#顯示時間戳
--tail	#從日誌末尾開始顯示的行數

#編寫一個shell腳本運行容器
"while true;do echo 666666;sleep 1;done"
[root@k8s-master /]# docker run -d centos /bin/sh -c "while true;do echo 666666;sleep 1;done"
d297ff12a815e8c1dd86ad951c30caca389ec5e854b6948c8b93d0e26ed7e10e
[root@k8s-master /]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
d297ff12a815        centos              "/bin/sh -c 'while t…"   2 seconds ago       Up 1 second                             angry_ardinghelli

#顯示日誌
[root@k8s-master /]# docker logs -f -t --tail 5 d297ff12a815
2020-06-18T09:38:26.352615139Z 666666
2020-06-18T09:38:27.357596179Z 666666
2020-06-18T09:38:28.363849798Z 666666
2020-06-18T09:38:29.369256113Z 666666
2020-06-18T09:38:30.377091746Z 666666

查看容器中進程信息

# docker top [容器id]
[root@k8s-master /]# docker top 480d8e4936dc
UID      PID      PPID    C      STIME    TTY         TIME      	CMD
root    12812     12794   0      17:42    pts/0      00:00:00   /bin/bash

查看容器元數據

# docker inspect [容器id]

[root@k8s-master /]# docker inspect d297ff12a815
[
    {
        "Id": "d297ff12a815e8c1dd86ad951c30caca389ec5e854b6948c8b93d0e26ed7e10e",
        "Created": "2020-06-18T09:37:38.560647732Z",
        "Path": "/bin/sh",
        "Args": [
            "-c",
            "while true;do echo 666666;sleep 1;done"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 12246,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2020-06-18T09:37:39.066548855Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:831691599b88ad6cc2a4abbd0e89661a121aff14cfa289ad840fd3946f274f1f",
        "ResolvConfPath": "/var/lib/docker/containers/d297ff12a815e8c1dd86ad951c30caca389ec5e854b6948c8b93d0e26ed7e10e/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/d297ff12a815e8c1dd86ad951c30caca389ec5e854b6948c8b93d0e26ed7e10e/hostname",
        "HostsPath": "/var/lib/docker/containers/d297ff12a815e8c1dd86ad951c30caca389ec5e854b6948c8b93d0e26ed7e10e/hosts",
        "LogPath": "/var/lib/docker/containers/d297ff12a815e8c1dd86ad951c30caca389ec5e854b6948c8b93d0e26ed7e10e/d297ff12a815e8c1dd86ad951c30caca389ec5e854b6948c8b93d0e26ed7e10e-json.log",
        "Name": "/angry_ardinghelli",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {},
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "CapAdd": null,
            "CapDrop": null,
            "Capabilities": null,
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "private",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "ConsoleSize": [
                0,
                0
            ],
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": null,
            "BlkioDeviceWriteBps": null,
            "BlkioDeviceReadIOps": null,
            "BlkioDeviceWriteIOps": null,
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DeviceRequests": null,
            "KernelMemory": 0,
            "KernelMemoryTCP": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": null,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/262154243dfb5fcc88ee7ebc33f14eb633ab80762c3c590ae6dd47963fa9c258-init/diff:/var/lib/docker/overlay2/c136121eb67e6c71677589843a6b4a68655638d12f4c79ce634d224b7239228e/diff",
                "MergedDir": "/var/lib/docker/overlay2/262154243dfb5fcc88ee7ebc33f14eb633ab80762c3c590ae6dd47963fa9c258/merged",
                "UpperDir": "/var/lib/docker/overlay2/262154243dfb5fcc88ee7ebc33f14eb633ab80762c3c590ae6dd47963fa9c258/diff",
                "WorkDir": "/var/lib/docker/overlay2/262154243dfb5fcc88ee7ebc33f14eb633ab80762c3c590ae6dd47963fa9c258/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "d297ff12a815",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "while true;do echo 666666;sleep 1;done"
            ],
            "Image": "centos",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20200611",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS"
            }
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "536bd691e3316eca9f9ad9902a9cfa7b0b37df0a384dc617a87453355a17fea0",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/536bd691e331",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "4e4b82daee88df3a954ce8b905ba24c894858668d28211d47e0617641911c6ae",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:02",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "35ca8cfcee1b97f050ae2e99c9f0c46b94009313ecb938325043f8d685cb93ba",
                    "EndpointID": "4e4b82daee88df3a954ce8b905ba24c894858668d28211d47e0617641911c6ae",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]

進入當前正在運行的容器

# 通常容器都是使用後臺方式運行的,需要進入容器,修改一些配置

#方式一
#打開了新的終端,可以在裏操作
docker exec -it [容器id] /bin/bash

[root@k8s-master /]# docker exec -it f1b799deb1b5 /bin/bash
[root@f1b799deb1b5 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@f1b799deb1b5 /]# ps -ef
UID         PID   PPID  C STIME TTY          TIME CMD
root          1      0  0 09:56 pts/0    00:00:00 /bin/bash
root         14      0  0 09:57 pts/1    00:00:00 /bin/bash
root         28      1  0 09:57 pts/0    00:00:00 ps -ef



#方式二
#進入容器當前正在執行的終端
docker attach [容器id]

[root@k8s-master ~]# docker  attach f1b799deb1b5
[root@f1b799deb1b5 /]# 

從容器內拷貝文件到主機

docker cp 容器id:容器內id 目的主機路徑

#進入容器創建一個文件
[root@k8s-master ~]# docker attach f1b799deb1b5
[root@f1b799deb1b5 /]# echo {a..z} >test.txt
[root@f1b799deb1b5 /]# cat /test.txt 
a b c d e f g h i j k l m n o p q r s t u v w x y z

#將容器的文件拷貝到主機上
[root@k8s-master ~]# docker cp f1b799deb1b5:/test.txt /tmp/

[root@k8s-master ~]# ls /tmp/test.txt 
/tmp/test.txt
[root@k8s-master ~]# cat /tmp/test.txt 
a b c d e f g h i j k l m n o p q r s t u v w x y z

#拷貝是一個手動過程,之後使用 -v 卷的技術,可以實現自動同步;主機目錄和容器目錄同步

查看鏡像、容器、數據卷所佔用的空間

# docker system df

[root@k8s-master ~]# docker system df
TYPE                TOTAL               ACTIVE           SIZE            RECLAIMABLE
Images              1                   1                215.3MB         0B (0%)
Containers          1                   0                   104B         104B (100%)
Local Volumes       2                   0                   0B           0B
Build Cache         0                   0                   0B           0B

四、測試docker鏡像運行各種環境

1. 測試運行一個nginx容器,端口映射到主機的3344

[root@k8s-master ~]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
8559a31e96f4: Pull complete 
8d69e59170f7: Pull complete 
3f9f1ec1d262: Pull complete 
d1f5ff4f210d: Pull complete 
1e22bfa8652e: Pull complete 
Digest: sha256:21f32f6c08406306d822a0e6e8b7dc81f53f336570e852e25fbe1e3e3d0d0133
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

[root@k8s-master ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              831691599b88        2 days ago          215MB
nginx               latest              2622e6cca7eb        9 days ago          132MB

[root@k8s-master ~]# docker run -d --name nginx01 -p 3344:80 nginx:latest 
145afc9f6eaa994b51d2c00bb28613bff2b1f9a48ea7f26a3c591bd40102cdd9

[root@k8s-master ~]# curl -I 127.0.0.1:3344
HTTP/1.1 200 OK
Server: nginx/1.19.0
Date: Fri, 19 Jun 2020 03:13:22 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 26 May 2020 15:00:20 GMT
Connection: keep-alive
ETag: "5ecd2f04-264"
Accept-Ranges: bytes

# 進入容器
[root@k8s-master ~]# docker exec -it nginx01 /bin/bash
root@145afc9f6eaa:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@145afc9f6eaa:/# cd /etc/nginx/
root@145afc9f6eaa:/etc/nginx# ls
conf.d		koi-utf  mime.types  nginx.conf   uwsgi_params
fastcgi_params	koi-win  modules     scgi_params  win-utf

2. 測試運行一個tomcat的容器,端口映射到主機的3355

https://hub.docker.com/_/tomcat

# 下載鏡像再啓動
docker pull tomcat
# 啓動運行
docker run -d -p 3355:8080 --name tomcat01 tomcat

# 訪問此容器會報錯404,是因爲tomcat官網鏡像沒有webapps,鏡像源把所有鏡像不必要的都剔除了,默認是最小可運行環境

# 進入容器,將默認的webapps.dist的內容拷貝一份到webapps目錄下
[root@k8s-master ~]# docker exec -it tomcat01 /bin/bash
root@23e4e460879b:/usr/local/tomcat# cp -a webapps.dist/* webapps/

# 再一次訪問就成功了
[root@k8s-master ~]# curl -I 127.0.0.1:3355
HTTP/1.1 200 
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 19 Jun 2020 03:39:34 GMT

每次改動服務配置文件,都需要進入容器內部,十分麻煩,我們可以在容器外映射一個路徑,達到在宿主機修改文件內容,容器內部就可以自動同步修改,就是數據卷的操作

3. 測試部署一套elasticsearch+kibana的日誌監控的容器

https://hub.docker.com/_/elasticsearch

啓動一臺es容器

# es暴露的端口很多
# es十分耗內存
# es數據一般需要放置到安全目錄掛載

# 啓動elasticsearch
[root@k8s-master ~]# docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2

#訪問
[root@k8s-master ~]# curl 127.0.0.1:9200
{
  "name" : "7426e97975a1",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "aNGISnU9QZm3qQw9obQiPg",
  "version" : {
    "number" : "7.6.2",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
    "build_date" : "2020-03-26T06:34:37.794943Z",
    "build_snapshot" : false,
    "lucene_version" : "8.4.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

使用命令dcker stats查看es容器的內存佔用情況太大

# 關閉剛剛啓動的es容器,增加內存的限制,修改配置文件 -e 環境配置修改
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m"  elasticsearch:7.6.2

[root@k8s-master ~]# curl  127.0.0.1:9200
{
  "name" : "66fdfb9147aa",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "7vONQG4HSjKXdtpMmEzbIg",
  "version" : {
    "number" : "7.6.2",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
    "build_date" : "2020-03-26T06:34:37.794943Z",
    "build_snapshot" : false,
    "lucene_version" : "8.4.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

啓動一臺kibana容器

# 運行一臺kibana7.6.2的容器,並添加到elasticsearch容器的網絡中,使用--link或者創建自定義網絡
docker run -d --name kibana --link elasticsearch -p 5601:5601 kibana:7.6.2

# 訪問查看;選擇一個樣本數據進行測試是否與es連接




五、Docker可視化面板

# Portainer
基於Go,是一個輕量級的圖形化界面管理工具,可輕鬆管理Docker主機。

# Rancher
開源的企業級容器管理平臺,Rancher提供了在生產環境中使用管理Docker和Kubernetes的全棧化容器部署與管理平臺。(CICD)

# cAdvisor
Google開發的容器監控工具, 會顯示當前容器的資源使用情況,包括 CPU、內存、網絡、文件系統等,顯示容器列表。

啓動一臺portainer容器(不常用,測試學習)

[root@k8s-master ~]# docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

訪問8088端口 http://192.168.0.10:8088

六、Docker鏡像講解

1. Docker鏡像加載原理

UnionFS(聯合文件系統)

下載鏡像時看到的一層層的就是這個!

UnionFS(聯合文件系統)

是一種分層、輕量級並且高性能的文件系統,它支持對文件系統的修改作爲一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬文件系統下。UnionFS是Docker鏡像的基礎,鏡像可以通過分層來進行繼承,基於基礎鏡像(沒有父鏡像),可以製作各種具體的應用鏡像。

2. Docker commit定製鏡像

docker不建議再通過這種方式構建鏡像;具體原因如下

手工創建,容易出錯,效率低並且可重複性弱。

無法對鏡像進行審計,存在安全隱患。

學習commit定製鏡像的原因:

dockerfile構建鏡像,底層也是docker commit一層一層構建新鏡像的,學習的目的是更加深入地理解構建過程和鏡像分層結構。

三個步驟

  • 運行容器

  • 修改容器

  • 將容器保存爲新的鏡像

# 第一步: 啓動運行一個官方鏡像的tomcat容器
[root@k8s-master ~]# docker run -it -d -p 8080:8080 --name tomcat02 tomcat
[root@k8s-master ~]# docker exec -it tomcat02 /bin/bash

# 第二步: 修改內容,將默認的webapps.dist/下內容複製到webapps下
root@81fd44790b38:/usr/local/tomcat# cp -a webapps.dist/* webapps/

# 第三步: commit提交
--a	#是指定修改的作者
--m	#是記錄本次修改的內容
[root@k8s-master ~]# docker commit -a "lichenxing" -m "cp -a webapps.dist/* webapps/" tomcat02 tomcat02:V1.0
sha256:405a3c097a00380667ab5e3d4ed30458e5483cbb3182640c9275b2f82bc15f5d

# 第四步: 查看提交的鏡像
[root@k8s-master ~]# docker images
REPOSITORY        TAG              IMAGE ID            CREATED             SIZE
tomcat02          V1.0             405a3c097a00        34 seconds ago      652MB
tomcat            latest           2eb5a120304e        9 days ago          647MB

七、Dokcer數據卷

容器的持久化和同步操作!容器間也是可以數據共享的!

容器刪除後,數據還在主機上保存。

1. 使用數據卷

# 方式一: 直接使用命令掛載 -v
docker run -it -v 主機目錄:容器目錄

[root@k8s-master ~]# docker run -it -v /home/ceshi/:/home centos /bin/bash
[root@06b7f2dc16ec /]# ls /home/

# 容器掛載的/home/ceshi目錄自動生成
[root@k8s-master ~]# ll /home/
total 0
drwxr-xr-x. 2 root root  6 Jun 19 16:36 ceshi

# 查看容器的詳細信息(Mounts部分)
[root@k8s-master ~]# docker inspect 06b7f2dc16ec
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/home/ceshi",	# 主機內的地址
                "Destination": "/home",		# docker容器內的地址
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],

# 主機目錄和容器目錄都爲空,在容器內添加文件
[root@06b7f2dc16ec /]# cd /home/
[root@06b7f2dc16ec home]# touch test.java

# 在主機上查看,已經同步過來了
[root@k8s-master ~]# ll /home/ceshi/
total 0
-rw-r--r--. 1 root root 0 Jun 19 16:43 test.java

# 在主機上追加文件內容
[root@k8s-master ~]# echo {a..z} > /home/ceshi/test.java

# 在容器內查看文件
[root@06b7f2dc16ec home]# cat test.java
a b c d e f g h i j k l m n o p q r s t u v w x y z

修改只需要在主機本地修改即可,容器可以自動同步。

補充:

使用 --mount 標記可以指定掛載一個本地主機的目錄到容器中去,如果使用mount時,宿主機中沒有這個文件會報錯,而不是像-v,沒有這個文件也會自動創建。

# 掛載一個主機目錄作爲數據卷:(-v 和 --mount的對比)
docker run -d -P --name web \
    # -v /src/webapp:/opt/webapp \
    --mount type=bind,source=/src/webapp,target=/opt/webapp \
    training/webapp \
    python app.py
    
上面的命令加載主機的 /src/webapp 目錄到容器的 /opt/webapp目錄。這個功能在進行測試的時候十分方便,比如用戶可以放置一些程序到本地目錄中,來查看容器是否正常工作。本地目錄的路徑必須是絕對路徑,以前使用 -v 參數時如果本地目錄不存在 Docker 會自動爲你創建一個文件夾,現在使用 --mount 參數時如果本地目錄不存在,Docker 會報錯。

# Docker 掛載主機目錄的默認權限是 讀寫,用戶也可以通過增加readonly指定爲只讀。
docker run -d -P --name web \
    # -v /src/webapp:/opt/webapp:ro \
    --mount type=bind,source=/src/webapp,target=/opt/webapp,readonly \
    training/webapp \
    python app.py

# 掛載一個本地主機文件作爲數據卷:--mount標記也可以從主機掛載單個文件到容器中
docker run -it \
   # -v /root/.bash_history:/root/.bash_history \
   --mount type=bind,source=/root/.bash_history,target=/root/.bash_history \
   ubuntu:17.10 \
   bash
   
# 這樣就可以記錄在容器輸入過的命令了。
root@2affd44b4667:/# history
1  ls
2  history

2. 安裝MySQL

https://hub.docker.com/_/mysql

# 下載mysql5.7的官方鏡像
docker pull mysql:5.7

# 運行一臺mysql容器 (需要設置mysql密碼; 映射配置文件和數據文件;通過官方鏡像倉庫查看啓動容器的命令)
[root@k8s-master ~]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
0d709657652353d906f710118144ea401c6ce539c825abd2aa019e889278944c

#查看主機映射目錄
[root@k8s-master home]# ls 
ceshi  lcx  mysql
[root@k8s-master home]# cd mysql/
[root@k8s-master mysql]# ls
conf  data
[root@k8s-master mysql]# ls data/
auto.cnf    client-cert.pem  ibdata1      ibtmp1              private_key.pem  server-key.pem
ca-key.pem  client-key.pem   ib_logfile0  mysql               public_key.pem   sys
ca.pem      ib_buffer_pool   ib_logfile1  performance_schema  server-cert.pem

通過本地第三方工具 SQLyog登陸mysql容器


新建一個數據庫 test

# 查看主機映射目錄也已經同步了test庫目錄
[root@k8s-master mysql]# ls data/
auto.cnf         client-key.pem  ib_logfile1         private_key.pem  sys
ca-key.pem       ib_buffer_pool  ibtmp1              public_key.pem   test
ca.pem           ibdata1         mysql               server-cert.pem
client-cert.pem  ib_logfile0     performance_schema  server-key.pem

3. 容器數據持久化

# 將容器刪除後,數據已經保留下來了
[root@k8s-master ~]# docker rm -f mysql01
mysql01

[root@k8s-master mysql]# ls data/
auto.cnf         client-key.pem  ib_logfile1         private_key.pem  sys
ca-key.pem       ib_buffer_pool  ibtmp1              public_key.pem   test
ca.pem           ibdata1         mysql               server-cert.pem
client-cert.pem  ib_logfile0     performance_schema  server-key.pem

4. 具名和匿名掛載

匿名掛載:沒有名字

# 啓動一個nginx容器, 選擇隨機端口和隨機掛載路徑(只寫了容器內的路徑,沒有寫容器外的路徑)
[root@k8s-master ~]# docker run -d -P --name nginx01 -v /etc/nginx nginx:latest

# 查看所有卷的情況(都是匿名卷,沒有名字)
[root@k8s-master ~]# docker volume ls
DRIVER              VOLUME NAME
local               6350e9d05a6611859fd3de283d1ea41eb234fc8720ec2d7a415d343ebc4e8de4
local               a1b15cc90674c1d69f2f77e3b35543886d4f7ac40975f3dffe200df64e8e9b64
local               bd43717a0bbfebd513b69fafa7ec3824805136b9ed7afd57605bfd3fedfd5662
local               e8c6ff6336476cd8bbd65bee93e18ce1c073ab7901631d55312421f40fbde38d
local               f2ecc7f10858285cda52f3a87bcc5e845f0de90785c56235744c9380cb7872cf

具名掛載:擁有名字

# 再啓動一個nginx容器 
[root@k8s-master ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx:latest 
c446916349eefb151bf29f8ab657458e16deee7a46d65a3afa72b75a0ea30612

# 查看所有卷的情況(有名字爲juming-nginx的卷)
[root@k8s-master ~]# docker volume ls
DRIVER              VOLUME NAME
local               6350e9d05a6611859fd3de283d1ea41eb234fc8720ec2d7a415d343ebc4e8de4
local               a1b15cc90674c1d69f2f77e3b35543886d4f7ac40975f3dffe200df64e8e9b64
local               bd43717a0bbfebd513b69fafa7ec3824805136b9ed7afd57605bfd3fedfd5662
local               e8c6ff6336476cd8bbd65bee93e18ce1c073ab7901631d55312421f40fbde38d
local               f2ecc7f10858285cda52f3a87bcc5e845f0de90785c56235744c9380cb7872cf
local               juming-nginx

# 查看具名掛載卷的路徑
[root@k8s-master ~]# docker volume inspect juming-nginx 
[
    {
        "CreatedAt": "2020-06-19T17:52:09+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
        "Name": "juming-nginx",
        "Options": null,
        "Scope": "local"
    }
]

所有的docker容器內的卷,沒有指定目錄的情況下都是在/var/lib/docker/volumes/xxx/_data

通過具名掛載可以方便的找到我們的卷,大多數情況在使用的是具名掛載

# 如何確定是具名掛載還是匿名掛載,還是指定路徑掛載?
-v 容器內路徑						 #匿名掛載
-v 卷名:容器內路徑					#具名掛載
-v /宿主機路徑:容器內路徑		#指定路徑掛載

擴展:

# 通過 -v 容器內路徑:ro/rw 改變讀寫權限
ro	readonly	#只讀	
rw	readwrite	#可讀可寫

# 一旦設置了容器的讀寫權限,容器對我們掛載出來的內容就會有了權限了。
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx:latest
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx:latest

# ro 只要看到ro就說明此路徑是隻能通過宿主機來操作,容器內部是無法操作修改的!

5. Dockerfile的基礎操作

dockerfile 就是用來構建docker鏡像的構建文件! 命令腳本。

# 創建一個存放dockerfile文件的目錄
mkdir -p /home/docker-test-volume

# 編寫一個dockerfile,生成鏡像(指令都爲大寫)
# 每行命令,就是鏡像的一層!
[root@k8s-master docker-test-volume]# cat dockerfile1
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "----end----"
CMD /bin/bash

# 生成dockerfile文件
[root@k8s-master docker-test-volume]# docker build -f dockerfile1 -t lichenxing/centos:1.0 ./
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos
 ---> 831691599b88
Step 2/4 : VOLUME ["volume01","volume02"]
 ---> Running in 9a58f0ee53e5
Removing intermediate container 9a58f0ee53e5
 ---> 494b993538b5
Step 3/4 : CMD echo "----end----"
 ---> Running in 380c5748e66a
Removing intermediate container 380c5748e66a
 ---> 6f77f010dee6
Step 4/4 : CMD /bin/bash
 ---> Running in 002cd526e782
Removing intermediate container 002cd526e782
 ---> 62fd78da2572
Successfully built 62fd78da2572
Successfully tagged lichenxing/centos:1.0

# 查看生成的鏡像
[root@k8s-master docker-test-volume]# docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
lichenxing/centos     1.0                 62fd78da2572        43 seconds ago      215MB

# 使用生成的鏡像創建一臺容器
[root@k8s-master docker-test-volume]# docker run -it lichenxing/centos:1.0 /bin/bash
[root@1af48762856e /]# 

# 查看目錄,可以看到在dockerfile中自動掛載的數據卷
[root@1af48762856e /]# ls -l
total 0
lrwxrwxrwx.   1 root root   7 May 11  2019 bin -> usr/bin
drwxr-xr-x.   5 root root 360 Jun 23 03:31 dev
drwxr-xr-x.   1 root root  66 Jun 23 03:31 etc
drwxr-xr-x.   2 root root   6 May 11  2019 home
lrwxrwxrwx.   1 root root   7 May 11  2019 lib -> usr/lib
lrwxrwxrwx.   1 root root   9 May 11  2019 lib64 -> usr/lib64
drwx------.   2 root root   6 Jun 11 02:35 lost+found
drwxr-xr-x.   2 root root   6 May 11  2019 media
drwxr-xr-x.   2 root root   6 May 11  2019 mnt
drwxr-xr-x.   2 root root   6 May 11  2019 opt
dr-xr-xr-x. 130 root root   0 Jun 23 03:31 proc
dr-xr-x---.   2 root root 162 Jun 11 02:35 root
drwxr-xr-x.  11 root root 163 Jun 11 02:35 run
lrwxrwxrwx.   1 root root   8 May 11  2019 sbin -> usr/sbin
drwxr-xr-x.   2 root root   6 May 11  2019 srv
dr-xr-xr-x.  13 root root   0 Jun 23 01:36 sys
drwxrwxrwt.   7 root root 145 Jun 11 02:35 tmp
drwxr-xr-x.  12 root root 144 Jun 11 02:35 usr
drwxr-xr-x.  20 root root 262 Jun 11 02:35 var
drwxr-xr-x.   2 root root   6 Jun 23 03:31 volume01		#生成鏡像時自動掛載的數據卷目錄
drwxr-xr-x.   2 root root   6 Jun 23 03:31 volume02		#生成鏡像時自動掛載的數據卷目錄

## 這兩個卷一定有一個與外部同步的目錄
# 在卷目錄下創建一個文件
[root@1af48762856e /]# cd volume01/
[root@1af48762856e volume01]# touch container.txt

# 在宿主機上查看此容器的元數據可以看到卷掛載到了外部的某個目錄下
[root@k8s-master docker-test-volume]# docker inspect 1af48762856e
...
"Mounts": [
    {
        "Type": "volume",
        "Name": "588dd712d0817140680bd2d7fad6d85bf837cbf9f1ad8c435d06ff98d076f259",
        "Source": "/var/lib/docker/volumes/588dd712d0817140680bd2d7fad6d85bf837cbf9f1ad8c435d06ff98d076f259/_data",
        "Destination": "volume02",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    },
    {
        "Type": "volume",
        "Name": "fbd1a9f5c760ef7b592c4b31aaaa3ab4887d650b40397476012d4d942b151bc6",
        "Source": "/var/lib/docker/volumes/fbd1a9f5c760ef7b592c4b31aaaa3ab4887d650b40397476012d4d942b151bc6/_data",
        "Destination": "volume01",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    }
],

# 可以看到volume01的掛載目錄是路徑,cd切換到目錄下查看已經同步了創建的文件
/var/lib/docker/volumes/fbd1a9f5c760ef7b592c4b31aaaa3ab4887d650b40397476012d4d942b151bc6/_data/
[root@k8s-master _data]# ll
total 0
-rw-r--r--. 1 root root 0 Jun 23 11:35 container.txt

通常構建自己的鏡像時,沒有掛在卷,要手動鏡像掛載 -v 卷名:容器內路徑

6. 數據卷容器

創建三臺容器來進行測驗數據卷共享 (使用剛剛通過dockerfile生成的鏡像)

--volumes-from	# 只要通過此參數,則可以實現容器間的數據共享

# 創建第一臺容器docker01,掛載的數據卷下沒有內容
[root@k8s-master ~]#  docker run -it --name docker01 lichenxing/centos:1.0 
[root@eac7afb4cb11 /]# ls -l
total 0
....
drwxr-xr-x.   2 root root   6 Jun 23 05:54 volume01
drwxr-xr-x.   2 root root   6 Jun 23 05:54 volume02
[root@eac7afb4cb11 /]# ls volume01
[root@eac7afb4cb11 /]# ls volume02


# 創建的第二臺容器docker02,掛載的爲docker上的數據卷,也沒有內容
[root@k8s-master ~]#  docker run -it --name docker02 --volumes-from docker01 lichenxing/centos:1.0 
[root@a493d7a3d2ca /]# ls -l
total 0
....
drwxr-xr-x.   2 root root   6 Jun 23 05:54 volume01
drwxr-xr-x.   2 root root   6 Jun 23 05:54 volume02
[root@a493d7a3d2ca /]# ls  volume01 
[root@a493d7a3d2ca /]# ls  volume02


# 在docker01容器上的數據卷目錄創建文件
[root@k8s-master ~]# docker attach docker01
[root@eac7afb4cb11 /]# touch /volume01/docker01

# 在docker02容器上查看,docker01的數據卷目錄下文件也已經同步過來了
[root@k8s-master ~]# docker attach docker02 
[root@a493d7a3d2ca /]# ls /volume01/
docker01


# 創建第三臺容器docker03,將docker01的數據卷掛載; 並且再創建一個docker03文件
# 可以發現容器docker01上的數據卷內容都同步了
[root@k8s-master ~]#  docker run -it --name docker03 --volumes-from docker01 lichenxing/centos:1.0 
[root@336c364cb4fa /]# ls -l /volume01/
total 0
-rw-r--r--. 1 root root 0 Jun 23 06:01 docker01
[root@336c364cb4fa /]# touch /volume01/docker03

# 在容器docker01上查看也同步了
[root@k8s-master ~]# docker attach docker01
[root@eac7afb4cb11 /]# ls -l volume01/
total 0
-rw-r--r--. 1 root root 0 Jun 23 06:01 docker01
-rw-r--r--. 1 root root 0 Jun 23 06:07 docker03

刪除容器docker01後,其他容器的數據卷內容沒有丟失-拷貝機制

[root@k8s-master ~]# docker rm -f docker01 
docker01

[root@k8s-master ~]# docker attach docker02 
[root@a493d7a3d2ca /]# ls -l /volume01/
total 0
-rw-r--r--. 1 root root 0 Jun 23 06:01 docker01
-rw-r--r--. 1 root root 0 Jun 23 06:07 docker03
[root@a493d7a3d2ca /]# read escape sequence

[root@k8s-master ~]# docker attach docker03
[root@336c364cb4fa /]# ls -l /volume01/
total 0
-rw-r--r--. 1 root root 0 Jun 23 06:01 docker01
-rw-r--r--. 1 root root 0 Jun 23 06:07 docker03
[root@336c364cb4fa /]# read escape sequence

可以運用在多個mysql實現數據共享

# 例子 mysql01
[root@k8s-master ~]# docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

# 例子 mysql02; 掛載mysql01的數據卷
[root@k8s-master ~]# docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7

結論

  • 容器之間配置信息的傳遞,數據卷容器的生命週期一直持續到沒有容器使用爲止。
  • 一旦持久化到本地目錄,本地的數據是不會刪除的。

九、Dockerfile

1. Dockerfile介紹

dockerfile 就是用來構建docker鏡像的構建文件! 命令腳本!

構建步驟

  • 編寫一個dockerfile文件
  • docker build構建成爲一個鏡像
  • docker run 運行鏡像
  • docker push 發佈鏡像(dockerHub、私有倉庫)

查看一下官方是怎麼編寫的

很多官方鏡像都是基礎包,很多功能沒有,我們通常會自己搭建自己的鏡像!

2. Dockerfile構建

基礎知識

  • 每個指令都必須是大寫字母
  • 執行從上到下順序執行
  • "#"表示註釋
  • 每一個指令都會創建提交一個新的鏡像層,並提交!

  • Dockerfile是面向開發,我們以後要發佈項目,做鏡像,就需要編寫dockerfile文件。

  • Docker鏡像逐漸成爲企業交付的標準。

  • Dockerfile :構建文件,定義了一切的步驟,源代碼。

  • DockerImages:通過DockerFile構建生成的鏡像,最終發佈和運行的產品,原來是jar包 war包

  • Docker容器:容器就是鏡像運行起來提供的服務器

3. Dockerfile的指令

FROM				  #指定基礎鏡像
MAINTAINER		 #指定鏡像創建者信息(姓名+郵箱)
RUN						#執行構建命令
CMD						#設置容器啓動時執行的操作(只有最後一個會生效,可被替代)
ENTRYPOINT		 #設置容器啓動時執行的操作(可以追加命令)
USER					#設置容器的用戶
EXPOSE				#指定容器需要映射到宿主機的端口
ENV						#用於設置環境變量
ADD						#從src複製文件到容器的dest路徑(會自動解壓tar包)
VOLUME				#指定掛載點
WORKDIR				#工作目錄
ONBUILD				#在子鏡像中執行,構建一個被繼承,就會運行此指令,觸發指令
COPY					#類似ADD,將文件拷貝到鏡像中(不會解壓tar包)

4. 自己寫一個Dockerfile文件構建鏡像

Docker Hub中,99%鏡像都是從這個基礎鏡像FROM scratch過來的,然後配置需要的軟件和配置進行構建。這個鏡像是虛擬的概念,並不實際存在,它表示一個空白的鏡像。如果你以scratch爲基礎鏡像的話,意味着不以任何鏡像爲基礎,接下來所寫的指令將作爲鏡像第一層開始存在。有的人可能感覺很奇怪,沒有任何基礎鏡像,我怎麼去執行我的程序呢,其實對於 Linux 下靜態編譯的程序來說,並不需要有操作系統提供運行時支持,所需的一切庫都已經在可執行文件裏了,因此直接FROM scratch會讓鏡像體積更加小巧。

# 創建一個存放dockerfile文件的目錄
mkdir -p /home/dockerfile
cd /home/dockerfile/
# 編寫dockerfile文件
[root@k8s-master dockerfile]# cat mydockerfile-centos 
FROM centos
MAINTAINER lichenxing<[email protected]>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash
# 進行構建
#docker build "."最後的"."號,其實是在指定鏡像構建過程中的上下文環境的目錄
docker build -f [dockerfile文件路徑] -t 鏡像名:[tag] .

[root@k8s-master dockerfile]#docker build -f mydockerfile-centos -t mycentos:0.1 .
....
Successfully built 754ab894cdb8
Successfully tagged mycentos:0.1
# 查看構建成功的鏡像
[root@k8s-master dockerfile]# docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
mycentos              0.1                 754ab894cdb8        3 minutes ago       295MB

測試運行

## 這是構建之前的官方centos鏡像
[root@k8s-master dockerfile]# docker run -it centos
[root@5a792ccff9b2 /]# pwd		#工作目錄默認根目錄
/
[root@5a792ccff9b2 /]# vim		#沒有vim命令
bash: vim: command not found
[root@5a792ccff9b2 /]# ifconfig	#沒有ifconfig命令
bash: ifconfig: command not found

## 這是通過dockerfile構建完成的鏡像mycentos:0.1
[root@k8s-master dockerfile]# docker run -it mycentos:0.1 
[root@8ebed8ffcb20 local]# pwd		##工作目錄修改爲/usr/local
/usr/local
[root@8ebed8ffcb20 local]# which vim	#有vim命令
/usr/bin/vim
[root@8ebed8ffcb20 local]# which ifconfig #有ifconfig命令
/usr/sbin/ifconfig

查看鏡像的構建歷史記錄

通過此方法,可以在拿到一個鏡像時,研究一下是怎麼做到的

5. RUN 執行命令

是否可以像 Shell 腳本一樣把每個命令對應一個 RUN 呢?

  • Dockerfile 中每一個指令都會建立一層,RUN 也不例外。每一個 RUN 的行爲,就和剛纔我們手工建立鏡像的過程一樣:新建立一層,在其上執行這些命令,執行結束後,commit 這一層的修改,構成新的鏡像。
  • 每個指令新建一層這是完全沒有意義的,而且很多運行時不需要的東西,都被裝進了鏡像裏,比如編譯環境、更新的軟件包等等。結果就是產生非常臃腫、非常多層的鏡像,不僅僅增加了構建部署的時間,也很容易出錯。 這是很多初學 Docker 的人常犯的一個錯誤。
  • Union FS 是有最大層數限制的,比如 AUFS,曾經是最大不得超過 42 層,現在是不得超過 127 層。
  • 一些下載 創建 刪除的命令沒有必要建立很多層,這只是一層的事情。因此,這裏沒有使用很多個 RUN 對一一對應不同的命令,而是僅僅使用一個 RUN 指令,並使用&&將各個所需命令串聯起來,簡化爲1層。
  • 在撰寫 Dockerfile 的時候,要經常提醒自己,這並不是在寫 Shell 腳本,而是在定義每一層該如何構建。
  • 最後建議添加清理的命令,刪除爲了編譯構建所需要的各種軟件,清理所有下載、展開的文件,緩存文件。這是很重要的一步,鏡像是多層存儲,每一層的東西並不會在下一層被刪除,會一直跟隨着鏡像。因此鏡像構建時,一定要確保每一層只添加真正需要添加的東西,任何無關的東西都應該清理掉。製作出了很臃腫的鏡像的原因之一,就是忘記了每一層構建的最後一定要清理掉無關文件。

6. CMD 和 ENTRYPOINT 區別

CMD						#設置容器啓動時執行的操作(只有最後一個會生效,可被替代)
ENTRYPOINT		 #設置容器啓動時執行的操作(可以追加命令)

測試 CMD

# 編寫一個簡單的CMD的dockerfile文件
[root@k8s-master dockerfile]# cat dockerfile-cmd-test 
FROM centos
CMD ["ls","-a"]

# 進行構建鏡像
[root@k8s-master dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest .
....
Successfully built 0a29d7f31b12
Successfully tagged cmdtest:latest

# 運行一個CMD鏡像的容器,可以看到,直接輸出dockerfile中寫的CMD指令
[root@k8s-master dockerfile]# docker run cmdtest 
.
..
.dockerenv
bin
dev
etc
home
...


# 再次運行容器,最近一個命令"-l"  [ls -al]
[root@k8s-master dockerfile]# docker run cmdtest -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\": executable file not found in $PATH": unknown.

## CMD的清理向下"-l"替換了CMD ["ls","-a"]命令, "-l"不是命令所以會報錯
[root@k8s-master dockerfile]# docker run cmdtest ls -al
total 0
drwxr-xr-x.   1 root root   6 Jun 23 09:41 .
drwxr-xr-x.   1 root root   6 Jun 23 09:41 ..
-rwxr-xr-x.   1 root root   0 Jun 23 09:41 .dockerenv
lrwxrwxrwx.   1 root root   7 May 11  2019 bin -> usr/bin
drwxr-xr-x.   5 root root 340 Jun 23 09:41 dev
drwxr-xr-x.   1 root root  66 Jun 23 09:41 etc
drwxr-xr-x.   2 root root   6 May 11  2019 home
....

測試 ENTRYPOINT

# 編寫一個ENTRYPOINT的dockerfile文件
[root@k8s-master dockerfile]# cat dockerfile-cmd-entrypoint
FROM centos
ENTRYPOINT ["ls","-a"]

# 進行構建鏡像
[root@k8s-master dockerfile]# docker build -f dockerfile-cmd-entrypoint -t entrypoint .
....
Successfully built 120ba8d637f5
Successfully tagged entrypoint:latest


# 運行一個ENTRYPOINT鏡像的容器,發現和CMD沒有區別
[root@k8s-master dockerfile]# docker run entrypoint
.
..
.dockerenv
bin
dev
etc
home
....


# 再次運行容器,追加一個參數 "-l";會發現直接就輸出了詳細信息
# 追加的命令,是直接拼接在 ENTRYPOINT 命令的後面,而不會去替換命令
[root@k8s-master dockerfile]# docker run entrypoint -l
total 0
drwxr-xr-x.   1 root root   6 Jun 23 09:48 .
drwxr-xr-x.   1 root root   6 Jun 23 09:48 ..
-rwxr-xr-x.   1 root root   0 Jun 23 09:48 .dockerenv
lrwxrwxrwx.   1 root root   7 May 11  2019 bin -> usr/bin
drwxr-xr-x.   5 root root 340 Jun 23 09:48 dev
drwxr-xr-x.   1 root root  66 Jun 23 09:48 etc
drwxr-xr-x.   2 root root   6 May 11  2019 home
....

Dockerfile中很多命令都十分的相似,我們需要了解他們的區別,最好的學習方法就是對比它們。

7. 測試 Tomcat鏡像(ADD COPY)

1. 準備鏡像文件,tomcat壓縮包,jdk的壓縮包

2. 編寫dockerfile文件

建議官方命名 Dockerfilebuild時就不需要-f指定了

[root@k8s-master tomcat]# cat Dockerfile
FROM centos
MAINTAINER lichenxing<[email protected]>

COPY readme.txt /usr/local/readme.txt

ADD jdk-8u60-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.0.27.tar.gz /usr/local/

RUN yum -y install vim 

ENV MYPATH /usr/local
WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk1.8.0_60
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.0.27
ENV CATALINA_BASH /usr/local/apache-tomcat-8.0.27
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-8.0.27/bin/startup.sh && tail -F /url/local/apache-tomcat-8.0.27/bin/logs/catalina.out

3. 構建鏡像

[root@k8s-master tomcat]# pwd
/home/dockerfile/build/tomcat
[root@k8s-master tomcat]# docker build -t diytomcat ./
....
Successfully built e256e862f380
Successfully tagged diytomcat:latest

4. 運行此鏡像的容器

# 將webapps目錄下的一些日誌或者代碼可以掛載到宿主機的目錄下

[root@k8s-master tomcat]# docker run -d -p 9090:8080 --name lcxtomcat -v /home/dockerfile/build/tomcat/test:/usr/local/apache-tomcat-8.0.27/webapps/test -v /home/dockerfile/build/tomcat/tomcatlogs:/usr/local/apache-tomcat-8.0.27/logs/ diytomcat
f1c38b290af2d88ca5ccfc99b5baaea77cc43d9de6a8ce75d6443125f74d2c3a

# 可以看到掛載到宿主機的目錄已經同步
[root@k8s-master tomcat]# pwd
/home/dockerfile/build/tomcat
[root@k8s-master tomcat]# ls
apache-tomcat-8.0.27.tar.gz  Dockerfile  jdk-8u60-linux-x64.tar.gz  readme.txt  test  tomcatlogs
[root@k8s-master tomcat]# ll tomcatlogs/
total 20
-rw-r--r--. 1 root root 6539 Jun 24 17:41 catalina.2020-06-24.log
-rw-r--r--. 1 root root 6539 Jun 24 17:41 catalina.out
-rw-r--r--. 1 root root    0 Jun 24 17:41 host-manager.2020-06-24.log
-rw-r--r--. 1 root root  280 Jun 24 17:41 localhost.2020-06-24.log
-rw-r--r--. 1 root root    0 Jun 24 17:41 localhost_access_log.2020-06-24.txt
-rw-r--r--. 1 root root    0 Jun 24 17:41 manager.2020-06-24.log

5. 進入tomcat容器中查看

[root@k8s-master tomcat]# docker exec -it lichenxingtomcat /bin/bash
[root@f1c38b290af2 local]# pwd
/usr/local
[root@f1c38b290af2 local]# ls
apache-tomcat-8.0.27  etc    include	  lib	 libexec     sbin   src
bin		      games  jdk1.8.0_60  lib64  readme.txt  share
[root@f1c38b290af2 local]# ls -l apache-tomcat-8.0.27/
total 92
-rw-r--r--. 1 root root 57011 Sep 28  2015 LICENSE
-rw-r--r--. 1 root root  1444 Sep 28  2015 NOTICE
-rw-r--r--. 1 root root  6741 Sep 28  2015 RELEASE-NOTES
-rw-r--r--. 1 root root 16204 Sep 28  2015 RUNNING.txt
drwxr-xr-x. 2 root root  4096 Sep 28  2015 bin
drwxr-xr-x. 1 root root    22 Jun 24 09:41 conf
drwxr-xr-x. 2 root root  4096 Sep 28  2015 lib
drwxr-xr-x. 2 root root   197 Jun 24 09:41 logs
drwxr-xr-x. 2 root root    30 Sep 28  2015 temp
drwxr-xr-x. 1 root root    18 Jun 24 09:41 webapps
drwxr-xr-x. 1 root root    22 Jun 24 09:41 work
[root@f1c38b290af2 local]# ls -l apache-tomcat-8.0.27/webapps/
total 8
drwxr-xr-x.  3 root root 4096 Sep 28  2015 ROOT
drwxr-xr-x. 14 root root 4096 Sep 28  2015 docs
drwxr-xr-x.  6 root root   83 Sep 28  2015 examples
drwxr-xr-x.  5 root root   87 Sep 28  2015 host-manager
drwxr-xr-x.  5 root root  103 Sep 28  2015 manager
drwxr-xr-x.  2 root root    6 Jun 24 09:41 test
[root@f1c38b290af2 local]# ls -l apache-tomcat-8.0.27/logs/
total 20
-rw-r--r--. 1 root root 6539 Jun 24 09:41 catalina.2020-06-24.log
-rw-r--r--. 1 root root 6539 Jun 24 09:41 catalina.out
-rw-r--r--. 1 root root    0 Jun 24 09:41 host-manager.2020-06-24.log
-rw-r--r--. 1 root root  280 Jun 24 09:41 localhost.2020-06-24.log
-rw-r--r--. 1 root root    0 Jun 24 09:41 localhost_access_log.2020-06-24.txt
-rw-r--r--. 1 root root    0 Jun 24 09:41 manager.2020-06-24.log
# 測試連接性
[root@f1c38b290af2 local]# curl -I 127.0.0.1:8080
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Date: Wed, 24 Jun 2020 09:48:16 GMT

宿主機的9090端口

6. 上傳一個web站點的壓縮包到test目錄下進行測試

[root@k8s-master tomcat]# pwd
/home/dockerfile/build/tomcat
[root@k8s-master tomcat]# cd ./test/
[root@k8s-master test]# ll
total 20316
-rw-r--r--.  1 root root 20797013 Jun 24 18:02 jpress-web-newest.war
drwxr-xr-x.  3 root root       38 Sep 19  2016 META-INF
-rw-r--r--.  1 root root       96 Jul 27  2016 robots.txt
drwxr-xr-x. 11 root root      139 Sep 19  2016 static
drwxr-xr-x.  4 root root       31 Sep 19  2016 templates
drwxr-xr-x.  6 root root       75 Jun 24 18:02 WEB-INF

先不用做安裝,只測試。沒有數據庫環境

  • 在主機的test目錄下就可以修改代碼文件。
# 可以在宿主機上直接查看訪問的日誌文件
[root@k8s-master tomcat]# tail -f tomcatlogs/catalina.out 

JFinal action report -------- 2020-06-24 10:05:59 ------------------------------
Controller  : io.jpress.install.InstallController.(InstallController.java:1)
Method      : step2
Interceptor : io.jpress.core.interceptor.JI18nInterceptor.(JI18nInterceptor.java:1)
              io.jpress.interceptor.GlobelInterceptor.(GlobelInterceptor.java:1)
              io.jpress.interceptor.AdminInterceptor.(AdminInterceptor.java:1)
              io.jpress.core.interceptor.HookInterceptor.(HookInterceptor.java:1)
              io.jpress.install.InstallInterceptor.(InstallInterceptor.java:1)
--------------------------------------------------------------------------------

8. 發佈鏡像到DockerHub

官方DockerHub倉庫

https://hub.docker.com/

需要註冊自己的賬戶,確認可以登錄

在服務器上提交鏡像到官方倉庫

[root@k8s-master tomcat]# docker login -u 245684979
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

# 爲封裝好的鏡像打一個標籤
# 這裏要注意 給自己鏡像命名的時候格式應該是: docker註冊用戶名/鏡像名,不然是push不上去的
[root@k8s-master tomcat]# docker tag diytomcat:latest 245684979/diytomcat:1.0

[root@k8s-master tomcat]# docker push 245684979/diytomcat:1.0 
The push refers to repository [docker.io/245684979/diytomcat]
0877995fc452: Pushing  9.192MB/57.19MB
5dedcbd44b60: Pushing  2.864MB/12.94MB
f675325f4324: Pushing  1.607MB/364.8MB
c966da79fa06: Pushing   2.56kB
eb29745b8228: Pushing  6.019MB/215.3MB
...

提交的時候也是按照鏡像的成績來進行提交的,提交成功後在DockerHub就可以看到了

9. 發佈鏡像到阿里雲鏡像倉庫

登陸阿里雲

找到容器鏡像服務

創建命名空間

創建容器鏡像

瀏覽操作指南

[root@k8s-master ~]# docker push registry.cn-beijing.aliyuncs.com/lichenxing/lcxtomcat:1.0 
The push refers to repository [registry.cn-beijing.aliyuncs.com/lichenxing/lcxtomcat]
0877995fc452: Pushed 
5dedcbd44b60: Pushed 
f675325f4324: Pushed 
c966da79fa06: Pushed 
eb29745b8228: Pushed 
1.0: digest: sha256:2e3c25e752897e3c166cc3b372bddefb3de5db0fb04d1f8a883580e04bdd6c90 size: 1372

10. 發佈鏡像到私有倉庫

有時候使用 Docker Hub 這樣的公共倉庫可能不方便,用戶可以創建一個本地倉庫供私人使用。docker-registry是官方提供的工具,可以用於構建私有的鏡像倉庫。

普通的registry

默認情況下,倉庫會被創建在容器的/var/lib/registry目錄下。可以通過 -v 參數來將鏡像文件存放在本地的指定路徑。

# 運行官方registry鏡像
docker run -d -p 5000:5000 --restart=always --name registry -v /opt/myregistry:/var/lib/registry  registry

# 將鏡像加速器地址改爲本地
[root@k8s-master ~]# cat  /etc/docker/daemon.json 
{
  "registry-mirrors": ["https://registry.docker-cn.com"],
  "insecure-registries": ["192.168.0.10:5000"]
}
systemctl restart docker

#  給鏡像打標籤
docker tag diytomcat 192.168.0.10:5000/lcxtomcat:1.0

# 上傳鏡像到私有倉庫
[root@k8s-master ~]# docker push 192.168.0.10:5000/lcxtomcat
The push refers to repository [192.168.0.10:5000/lcxtomcat]
0877995fc452: Pushed 
5dedcbd44b60: Pushed 
f675325f4324: Pushed 
c966da79fa06: Pushed 
eb29745b8228: Pushed 
1.0: digest: sha256:2e3c25e752897e3c166cc3b372bddefb3de5db0fb04d1f8a883580e04bdd6c90 size: 1372

# 查看私有倉庫上傳的鏡像
[root@k8s-master ~]# curl 127.0.0.1:5000/v2/_catalog
{"repositories":["lcxtomcat"]}

十、Docker網絡

  • None:不爲容器配置任何網絡功能,–net=none
  • Container:與另一個運行中的容器共享Network Namespace,–net=container:containerID(K8S)
  • Host:與宿主機共享Network Namespace,–network=host 性能最高
  • Bridge:Docker設計的NAT網絡模型(默認)

# 清除所有容器和鏡像環境
docker rm -f $(docker ps -aq)
docker rmi `docker images -qa`
# 啓動一臺容器
[root@k8s-master ~]# docker run -d -P --name tomcat01 tomcat

# 查看容器的網卡信息
[root@k8s-master ~]# docker exec -it tomcat01 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
21: eth0@if22: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

# linux宿主機可以ping通容器內部
[root@k8s-master ~]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.060 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.053 ms

原理:

  • 每啓動一個docker容器,docker都會給容器分配一個ip,我們只要按照了docker,就會有一個網卡docker0,Bridge橋接模式使用的技術是evth-pair技術。
  • evth-pair 就是一對的虛擬設備接口,他們都是成對出現的,一段連着協議,一段彼此相連,正因爲有這個特性,evth-pair充當一個橋樑,專門連接各種虛擬網絡設備。每開啓運行一個容器,就會增加一對兒對應的網卡。
  • Openstack、Docker、OVS都是使用的 evth-pair技術。
  • 容器刪除,對應的網橋也被刪除

1. Bridge模式

Docker進程啓動時,會在主機上創建一個名爲docker0的虛擬網橋,此主機上啓動的Docker容器會連接到這個虛擬網橋上。虛擬網橋的工作方式和物理交換機類似,這樣主機上的所有容器就通過交換機連在了一個二層網絡中。從docker0子網中分配一個 IP 給容器使用,並設置 docker0 的 IP 地址爲容器的默認網關。在主機上創建一對虛擬網卡veth pair設備,Docker 將 veth pair 設備的一端放在新創建的容器中,並命名爲eth0(容器的網卡),另一端放在主機中,以vethxxx這樣類似的名字命名,並將這個網絡設備加入到 docker0 網橋中。可以通過brctl show命令查看。

bridge模式是 docker 的默認網絡模式,不寫–net參數,就是bridge模式。使用docker run -p時,docker 實際是在iptables做了DNAT規則,實現端口轉發功能。可以使用iptables -t nat -vnL查看。

–link 容器互聯

隨着 Docker 網絡的完善,強烈建議大家將容器加入自定義的 Docker 網絡來連接多個容器,而不是使用 --link 參數。

思考:編寫一個微服務,database url=ip:,項目不重啓,數據庫ip換掉了,我們希望可以處理這個問題,可以用名字來進行訪問容器嗎?

# 創建倆臺容器 tomcat01和tomcat02
 docker run -it -d -P --name tomcat01 245684979/diytomcat:1.0
 docker run -it -d -P --name tomcat02 245684979/diytomcat:1.0
 
 # 嘗試相互ping不能ping通
 [root@k8s-master ~]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known

# 創建tomcat03容器,使用--link,即可解決了網絡連通問題
docker run -it -d -P  --name tomcat03 --link tomcat02 245684979/diytomcat:1.0

# 通過容器tomcat03來ping容器tomcat02可以ping通了
[root@k8s-master ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.055 ms

# 反向是不可以ping通 02 ping 03
[root@k8s-master ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known

查看網絡的信息

# 查看網絡詳細信息
[root@k8s-master ~]# docker network inspect cd3809ba6584
[
    {
        "Name": "bridge",
        "Id": "cd3809ba6584494c86e9802d3dfc6424bb33226c93b80bd31d9f43dd25c200c2",
        "Created": "2020-06-29T11:20:18.826585474+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "07926c954f2ad324dc977bed26af4953713355dcc5b67aea97f18830984bfce5": {
                "Name": "tomcat02",
                "EndpointID": "ff5fc39a60e1c6291afed28de6c2d14a5c43554e9a6dbff04495ee4d4ae0ec64",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",	# 爲tomcat02分配的IP
                "IPv6Address": ""
            },
            "b423584cb2f658703f42bfc8fe9fe40e61b3b9b7d29d4bee5af213340e9058ae": {
                "Name": "tomcat01",
                "EndpointID": "2e6d7bf8db206b2392eec7b959c5c695e61e1826e1eb03f3e8d0d012b3a3cc63",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",	# 爲tomcat01分配的IP
                "IPv6Address": ""
            },
            "b820e4afdccdb8a50045c77de6e575bff0df692ed144673e2cb2bb2259a76c08": {
                "Name": "tomcat03",
                "EndpointID": "d7bf4b2f4b213f6497cfcfdac40c827d104f56dee5a6cd14fade2b48d8ae9f54",
                "MacAddress": "02:42:ac:11:00:04",
                "IPv4Address": "172.17.0.4/16",	# 爲tomcat03分配的IP
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]
# 查看tomcat03的信息,可以看到links指定的是tomcat02
[root@k8s-master ~]# docker inspect tomcat03
....
            "Links": [
                "/tomcat02:/tomcat03/tomcat02"
            ],
....

# 通過查看tomcat03的hosts文件也可以看到
[root@k8s-master ~]# docker exec -it tomcat03 cat /etc/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.3	tomcat02 07926c954f2a		# 指定了tomcat02
172.17.0.4	b820e4afdccd
  • --link 就是在hosts配置中增加了一個主機名的解析
  • 隨着 Docker 網絡的完善,建議將容器加入自定義的 Docker 網絡來連接多個容器,而不是使用 --link 參數
  • docker0問題 不支持容器名連接訪問。

自定義網絡

查看網絡

# 查看網絡
[root@k8s-master ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
cd3809ba6584        bridge              bridge              local
018532904f4e        host                host                local
edfe5b0c21a1        none                null                local
# 清除測試的所有容器
docker rm -f $(docker ps -aq)

# 創建一臺容器; --network brigde 就是docker0
docker run  -d -P --name tomcat01 --network bridge tomcat

# 創建一個網絡mynet
# --driver  : 網絡模式
# --subnet  : 子網地址
# --gateway : 子網的網關地址
docker network create --driver  bridge --subnet 172.20.0.0/16 --gateway 172.20.0.1 mynet

# 查看自己創建的網絡詳細信息
[root@k8s-master ~]# docker network inspect mynet 
[
    {
        "Name": "mynet",
        "Id": "ea720ae53f20b83193bca0c1dbb6296165539aa4c547f1ef37028e705b87da6c",
        "Created": "2020-06-29T14:33:22.194817791+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.20.0.0/16",	#子網
                    "Gateway": "172.20.0.1"		#網關
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

啓動兩臺容器;指定創建的自定義網絡

docker run -d -P --name tomcat-net01 --net mynet tomcat
docker run -d -P --name tomcat-net02 --net mynet tomcat
# 再次查看網絡詳情,可以看到啓動的容器的IP
[root@k8s-master ~]# docker network inspect mynet
....
        "Containers": {
            "2767e468d20157e43b67174eeef94267ce2b3a5b9f66446b24fd17c06549fdb3": {
                "Name": "tomcat-net01",
                "EndpointID": "abadd831f2591a0d2aed089abac60292cfc0925193d6f3394131955140118750",
                "MacAddress": "02:42:ac:14:00:02",
                "IPv4Address": "172.20.0.2/16",
                "IPv6Address": ""
            },
            "4a70bba89baf3e98b4f3e35de9ee19d5363f06c592dff2bf81134fbc187ac0a0": {
                "Name": "tomcat-net02",
                "EndpointID": "8cdf9df77303ec7c3562e4b216d09ac5c5a39a7d7a5a1563b93ea7f5fd4d5060",
                "MacAddress": "02:42:ac:14:00:03",
                "IPv4Address": "172.20.0.3/16",
                "IPv6Address": ""
            }
        },
        
# 再次測試ping連接; ping主機名也可以ping通了
[root@k8s-master ~]# docker exec -it tomcat-net01 ping 172.20.0.3
PING 172.20.0.3 (172.20.0.3) 56(84) bytes of data.
64 bytes from 172.20.0.3: icmp_seq=1 ttl=64 time=0.111 ms

[root@k8s-master ~]# docker exec -it tomcat-net01 ping tomcat-net02
PING tomcat-net02 (172.20.0.3) 56(84) bytes of data.
64 bytes from tomcat-net02.mynet (172.20.0.3): icmp_seq=1 ttl=64 time=0.042 ms

--------------------------------------
##現在不使用--link也可以ping通主機名了

自定義的網絡docker都已經幫我們維護好了對應的關係,平時也推薦這樣使用網絡。

優勢:

  • Redis:不同的集羣使用不同的網絡,保證集羣是安全和健康的
  • MySQL:不同的集羣使用不同的網絡,保證集羣是安全和健康的

2. Host 模式

如果啓動容器的時候使用host模式,那麼這個容器將不會獲得一個獨立的Network Namespace,而是和宿主機共用一個 Network Namespace。容器將不會虛擬出自己的網卡,配置自己的 IP 等,而是使用宿主機的 IP 和端口。但是,容器的其他方面,如文件系統、進程列表等還是和宿主機隔離的。

# 運行一個host網絡的容器
docker run -it -d -P --name tomcat-host01 --net host tomcat

# 查看此容器的ip地址和宿主機一致
[root@k8s-master ~]# docker exec -it tomcat-host01 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:8a:1a:eb brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.10/24 brd 192.168.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe8a:1aeb/64 scope link 
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:8a:1a:f5 brd ff:ff:ff:ff:ff:ff
    inet 172.16.0.10/24 brd 172.16.0.255 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe8a:1af5/64 scope link 
       valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:8d:a8:1d:4b brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:8dff:fea8:1d4b/64 scope link 
       valid_lft forever preferred_lft forever
21: br-45945e527658: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:16:06:bd:c9 brd ff:ff:ff:ff:ff:ff
    inet 172.20.0.1/16 brd 172.20.255.255 scope global br-45945e527658
       valid_lft forever preferred_lft forever
    inet6 fe80::42:16ff:fe06:bdc9/64 scope link 
       valid_lft forever preferred_lft forever

3. Container 模式

這個模式指定新創建的容器和已經存在的一個容器共享一個 Network Namespace,而不是和宿主機共享。新創建的容器不會創建自己的網卡,配置自己的 IP,而是和一個指定的容器共享 IP、端口範圍等。同樣,兩個容器除了網絡方面,其他的如文件系統、進程列表等還是隔離的。兩個容器的進程可以通過 lo 網卡設備通信。

# 運行一個centos鏡像容器
[root@k8s-master ~]# docker run -it -d --name centos01  centos
[root@k8s-master ~]# docker exec -it centos01 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
28: eth0@if29: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

# 運行一個Container模式的容器; 指定centos01容器;查看網絡
[root@k8s-master ~]# docker run -it -d --name centos-container --network container:centos01 centos
[root@k8s-master ~]# docker exec -it centos-container ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
28: eth0@if29: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

4. None模式

使用none模式,Docker 容器擁有自己的 Network Namespace,但是,並不爲Docker 容器進行任何網絡配置。也就是說,這個 Docker 容器沒有網卡、IP、路由等信息。需要我們自己爲 Docker 容器添加網卡、配置 IP 等。

# 運行一個none模式的容器
docker run -it -d --name centos-none --network none centos

# 進入容器查看網卡發現沒有ip地址
[root@k8s-master ~]# docker exec -it centos-none ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever

5. 網絡連通


# 用bridge模式的容器去ping自定義網絡的容器;發現ping不通,因爲網絡不同
[root@k8s-master ~]# docker exec -it tomcat01 ping tomcat-net01
ping: tomcat-net01: Name or service not known

測試 將默認 bridge 模式的容器 tomcat01 和 自定義 mynet 網絡打通

docker network connect mynet tomcat01
# 查看mynet網絡詳情
docker network inspect mynet

# 一個容器 兩個ip地址!
[root@k8s-master ~]# docker exec -it tomcat01 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
32: eth0@if33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
40: eth1@if41: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:14:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.20.0.4/16 brd 172.20.255.255 scope global eth1
       valid_lft forever preferred_lft forever

# 可以ping通了
[root@k8s-master ~]# docker exec -it tomcat01 ping tomcat-net01
PING tomcat-net01 (172.20.0.2) 56(84) bytes of data.
64 bytes from tomcat-net01.mynet (172.20.0.2): icmp_seq=1 ttl=64 time=0.045 ms

# 而其他的是依舊ping不通的
[root@k8s-master ~]# docker exec -it tomcat02 ping tomcat-net01
ping: tomcat-net01: Name or service not known

總結:如果要跨網絡操作其他容器,就需要使用 docker network connect連通。

6. 部署一個Redis集羣

# 創建一個redis網絡
docker network create redis --subnet 172.30.0.0/16

# 執行一下命令創建6套redis目錄和配置文件
for port in $(seq 1 6);\
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.30.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done


[root@k8s-master ~]# tree /mydata/redis/
/mydata/redis/
├── node-1
│   └── conf
│       └── redis.conf
├── node-2
│   └── conf
│       └── redis.conf
├── node-3
│   └── conf
│       └── redis.conf
├── node-4
│   └── conf
│       └── redis.conf
├── node-5
│   └── conf
│       └── redis.conf
└── node-6
    └── conf
        └── redis.conf
        
# 依次啓動6臺redis容器
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.30.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
-v /mydata/redis/node-2/data:/data \
-v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.30.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
-v /mydata/redis/node-3/data:/data \
-v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.30.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
-v /mydata/redis/node-4/data:/data \
-v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.30.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
-v /mydata/redis/node-5/data:/data \
-v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.30.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /mydata/redis/node-6/data:/data \
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.30.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
# 查看啓動的redis容器
[root@k8s-master ~]# docker ps -a
CONTAINER ID        IMAGE                    COMMAND                  CREATED              STATUS              PORTS                                              NAMES
85de61b9c858        redis:5.0.9-alpine3.11   "docker-entrypoint.s…"   4 seconds ago        Up 2 seconds        0.0.0.0:6376->6379/tcp, 0.0.0.0:16376->16379/tcp   redis-6
0a1c84984623        redis:5.0.9-alpine3.11   "docker-entrypoint.s…"   5 seconds ago        Up 3 seconds        0.0.0.0:6375->6379/tcp, 0.0.0.0:16375->16379/tcp   redis-5
747dc6d77115        redis:5.0.9-alpine3.11   "docker-entrypoint.s…"   46 seconds ago       Up 45 seconds       0.0.0.0:6374->6379/tcp, 0.0.0.0:16374->16379/tcp   redis-4
0f88ca73c73a        redis:5.0.9-alpine3.11   "docker-entrypoint.s…"   About a minute ago   Up About a minute   0.0.0.0:6373->6379/tcp, 0.0.0.0:16373->16379/tcp   redis-3
3ca265147808        redis:5.0.9-alpine3.11   "docker-entrypoint.s…"   About a minute ago   Up About a minute   0.0.0.0:6372->6379/tcp, 0.0.0.0:16372->16379/tcp   redis-2
c9b5fea846b9        redis:5.0.9-alpine3.11   "docker-entrypoint.s…"   3 minutes ago        Up 3 minutes        0.0.0.0:6371->6379/tcp, 0.0.0.0:16371->16379/tcp   redis-1
# 創建redis集羣
[root@k8s-master ~]# docker exec -it redis-1 /bin/sh
/data # redis-cli --cluster create 172.30.0.11:6379 172.30.0.12:6379 172.30.0.13:6379 172.30.0.14:637
79 172.30.0.15:6379 172.30.0.16:6379 --cluster-replicas 1
-------------------------
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.30.0.15:6379 to 172.30.0.11:6379
Adding replica 172.30.0.16:6379 to 172.30.0.12:6379
Adding replica 172.30.0.14:6379 to 172.30.0.13:6379
M: ef62648c7f22c87109e3a4004e0b7b2a9717c5ca 172.30.0.11:6379
   slots:[0-5460] (5461 slots) master
M: 18eeb76c35d2185d39ecf0700cb486446f78065d 172.30.0.12:6379
   slots:[5461-10922] (5462 slots) master
M: 89a2b7bc56f838794f3b4492745f33a55f2af842 172.30.0.13:6379
   slots:[10923-16383] (5461 slots) master
S: 22acd8c91964e59f767fe95468210e876b65aa63 172.30.0.14:6379
   replicates 89a2b7bc56f838794f3b4492745f33a55f2af842
S: 7d37c75d6f6868e0eb50505763c6dcca533a7252 172.30.0.15:6379
   replicates ef62648c7f22c87109e3a4004e0b7b2a9717c5ca
S: c9726603df7d4a132ce012dd68ad829a69553ec9 172.30.0.16:6379
   replicates 18eeb76c35d2185d39ecf0700cb486446f78065d
Can I set the above configuration? (type 'yes' to accept): yes		#輸入yes
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.		#集羣配置完畢
# 查看redis集羣
/data # redis-cli -c 
127.0.0.1:6379> CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:85
cluster_stats_messages_pong_sent:88
cluster_stats_messages_sent:173
cluster_stats_messages_ping_received:83
cluster_stats_messages_pong_received:85
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:173

# 三主三從
127.0.0.1:6379> CLUSTER NODES
7d37c75d6f6868e0eb50505763c6dcca533a7252 172.30.0.15:6379@16379 slave ef62648c7f22c87109e3a4004e0b7b2a9717c5ca 0 1593426397000 5 connected
c9726603df7d4a132ce012dd68ad829a69553ec9 172.30.0.16:6379@16379 slave 18eeb76c35d2185d39ecf0700cb486446f78065d 0 1593426397015 6 connected
22acd8c91964e59f767fe95468210e876b65aa63 172.30.0.14:6379@16379 slave 89a2b7bc56f838794f3b4492745f33a55f2af842 0 1593426398022 4 connected
18eeb76c35d2185d39ecf0700cb486446f78065d 172.30.0.12:6379@16379 master - 0 1593426397518 2 connected 5461-10922
89a2b7bc56f838794f3b4492745f33a55f2af842 172.30.0.13:6379@16379 master - 0 1593426397518 3 connected 10923-16383
ef62648c7f22c87109e3a4004e0b7b2a9717c5ca 172.30.0.11:6379@16379 myself,master - 0 1593426396000 1 connected 0-5460
# 存一個值;可以看到存到了172.30.0.13,是master節點
127.0.0.1:6379> set a b
-> Redirected to slot [15495] located at 172.30.0.13:6379
OK

# 在其他窗口將redis-3 關閉
[root@k8s-master ~]# docker stop redis-3 
redis-3

# 再次進入到redis集羣查看之前的值;已經存到172.30.0.14節點上了
/data # redis-cli -c
127.0.0.1:6379> get a 
-> Redirected to slot [15495] located at 172.30.0.14:6379
"b"


部署redis集羣完成!

十一、 Docker Compose

十二、 Docker Swarm

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章