Docker詳解(上)

wydilearn發表於2022-07-17

Docker 學習

  • Docker概述
  • Docker安裝
  • Docker命令
    • 映象命令
    • 容器命令
    • 操作命令
    • ...
  • Docker映象
  • 容器資料卷
  • DockerFile
  • Docker網路原理
  • IDEA整合Docker
  • Docker Compose
  • Docker Swarm
  • CI/CD Jenkins

Docker概述

Docker為什麼出現?

一款產品:開發 --> 上線 兩套環境!應用環境,應用配置!

開發 --> 運維 問題:我在我的電腦上可以執行!版本更新,導致服務不可用!對於運維來說,考驗就十分大!

環境配置是十分的麻煩,每一個機器都要部署環境(叢集Redis、ES、Hadoop......)!費時費力。

釋出一個專案(jar + (Redis MySQL jdk ES)),專案能不能都帶上環境安裝打包!

之前在伺服器配置一個應用環境 Redis MySQL jdk ES Hadoop,配置十分麻煩,不能夠跨平臺。

Windows,最後釋出到Linux!

傳統:開發 jar,運維來做!

現在:開發打包部署上線,一套流程做完!

Java --> apk --> 釋出(應用商店) --> 張三使用apk --> 安裝即可用!

Java --> jar(環境) --> 打包專案帶上環境(映象) --> (Docker倉庫:商店) --> 下載我們釋出的映象 --> 直接執行即可!

Docker給以上的問題,提出瞭解決方案!

Docker的思想就來自於集裝箱!

JRE --> 多個應用(埠衝突) --> 原來都是交叉的!

隔離:Docker核心思想:打包裝箱!每個箱子是互相隔離的。

水果 生化武器

Docker 通過隔離機制,可以將伺服器利用到極致!

本質:所有的技術都是因為出現了一些問題,我們需要去解決,才去學習!

Docker的歷史

2010年,幾個搞IT的年輕人,就在美國成立了一家dotCloud

做一些pass的雲端計算服務!LXC 有關的容器技術!

他們將自己的技術(容器化技術)命名 就是 Docker!

Docker 剛剛誕生的時候,沒有引起行業的注意!dotCloud,就活不下去!

開源

開放原始碼!

2013年,Docker開源!

Docker越來越多的人發現了Docker的優點!火了,Docker 每個月都會更新一個版本!

2014年4月9日,Docker1.0釋出!

Docker為什麼這麼火?十分的輕巧!

在容器技術出來之前,我們都是使用虛擬機器技術!

虛擬機器:在Windows中裝一個VMware,通過這個軟體我們可以虛擬出來一臺或者多臺電腦!十分笨重!

虛擬機器也是屬於虛擬化技術,Docker 容器技術,也是一種 虛擬化技術!

vm : linux centos原生映象(一個電腦!) 隔離,需要開啟多個虛擬機器! 幾個G 幾分鐘
docker : 隔離,映象(最核心的環境 4m + jdk + mysql)十分的小巧,執行映象就可以了!小巧! 幾個M KB 秒級啟動!

到現在,所有開發人員都必須要會Docker!

聊聊Docker

Docker基於Go語言開發的!開源專案!

官網:https://www.docker.com/

文件地址:https://docs.docker.com/ Docker的文件是超級詳細的!

倉庫地址:https://hub.docker.com/

Docker能幹嘛

之前的虛擬機器技術!

虛擬機器技術缺點:

  1. 資源佔用十分多

  2. 冗餘步驟多

  3. 啟動很慢!

容器化技術

容器化技術不是模擬的一個完整的作業系統

比較Docker 和 虛擬機器技術的不同:

  • 傳統虛擬機器,虛擬出一套硬體,執行一個完整的作業系統,然後在這個系統上安裝和執行軟體
  • 容器內的應用直接執行在宿主機的核心,容器是沒有自己的核心的,也沒有虛擬我們的硬體,所以就輕便了
  • 每個容器間是互相隔離的,每個容器內都有一個屬於自己的檔案系統,互不影響。

DevOps(開發、運維)

應用更快速的交付和部署

傳統:一堆幫助文件,安裝程式

Docker:打包映象,釋出測試,一鍵執行

更便捷的升級和擴縮容

使用了Docker之後,我們部署應用就和搭積木一樣!

專案打包為一個映象,擴充套件 伺服器A!伺服器B

更簡單的系統運維

在容器化之後,我們的開發、測試環境都是高度一致的。

更高效的計算資源利用

Docker 是核心級別的虛擬化,可以在物理機上可以執行很多的容器例項!伺服器的效能可以被壓榨到極致。

Docker 安裝

Docker的基本組成

映象(image):

docker映象就像一個模板,可以通過這個模板來建立服務,tomcat映象 ==> run ==> tomcat01容器(提供服務),通過這個映象可以建立多個容器(最終服務執行或者專案執行就是在容器中的)。

容器(container):

Docker利用容器技術,獨立執行一個或者一組應用,通過映象來建立。

啟動,停止,刪除,基本命令!

目前可以把這個容器理解為就是一個簡易的linux系統

倉庫(repository):

倉庫就是存放映象的地方!

倉庫分為公有倉庫和私有倉庫!

Docker Hub(預設是國外的)

阿里雲...都有容器伺服器(配置映象加速!)

安裝Docker

環境準備

  1. 需要會一點點的Linux基礎
  2. CentOS 7
  3. 我們使用Xshell連線遠端伺服器進行操作!

環境檢視

# 系統核心是 3.10 以上的
# 系統版本

安裝

幫助文件:

# 1、解除安裝舊的版本
sudo apt-get remove docker docker-engine docker.io containerd runc

# 2、需要的安裝包
yum install -y yum-utils

# 3、設定映象的倉庫
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 阿里雲

# 更新yum軟體包索引
yum makecache fast

# 4、安裝docker  docker-ce 社群版  ee 企業版
yum install docker-ce docker-ce-cli containerd.io

# 5、啟動docker
systemctl start docker

# 6、使用docker version 檢視是否安裝成功

# 7、hello-world
docker run hello-world

# 8、檢視一下下載的這個 hello-world 映象
[root@ls-Cwj2oH9C /]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    feb5d9fea6a5   9 months ago   13.3kB

瞭解:解除安裝docker

# 1、解除安裝依賴
yum remove docker-ce docker-ce-cli containerd.io

# 2、刪除資源
rm -rf /var/lib/docker

# /var/lib/docker  docker的預設工作路徑!

阿里雲映象加速

  1. 登入阿里雲找到容器服務

  2. 找到映象加速的地址

  3. 配置使用

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

回顧HelloWorld流程

底層原理

Docker是怎麼工作的?

Docker是一個Client - Server 結構的系統,Docker的守護程式執行在主機上。通過Socket從客戶端訪問!

DockerServer接收到 Docker - Client 的指令,就會執行這個命令!

Docker 為什麼比 VM 快?

  1. Docker有著比虛擬機器更少的抽象層

  2. Docker利用的是宿主機的核心,vm需要的是Guest OS。

    所以說,新建一個容器的時候,docker不需要像虛擬機器一樣重新載入一個作業系統核心,避免引導操作。虛擬機器是載入Guest OS,分鐘級別的,而docker是利用宿主機的作業系統,省略了這個複雜的過程,秒級!

之後學習完畢所有的命令,再回過頭來看這段理論,就會很清晰!

Docker的常用命令

幫助命令

docker version     # 顯示docker的版本資訊
docker info        # 顯示docker的系統資訊,包括映象和容器的數量
docker 命令 --help  # 幫助命令

幫助文件的地址:https://docs.docker.com/engine/reference/commandline/docker/

映象命令

docker images 檢視所有本地的主機上的映象

[root@ls-Cwj2oH9C /]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    feb5d9fea6a5   9 months ago   13.3kB

# 解釋
REPOSITORY  映象的倉庫源
TAG         映象的標籤
IMAGE ID    映象的id
CREATED     映象的建立時間
SIZE        映象的大小

# 可選項
  -a,--all          # 列出所有映象
  -q,--quiet        # 只顯示映象的id

docker search 搜尋映象

[root@ls-Cwj2oH9C /]# docker search mysql
NAME                           DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql                          MySQL is a widely used, open-source relation…   12821     [OK]       
mariadb                        MariaDB Server is a high performing open sou…   4918      [OK]       
percona                        Percona Server is a fork of the MySQL relati…   580       [OK]       
phpmyadmin                     phpMyAdmin - A web interface for MySQL and M…   564       [OK]      

# 可選項,通過搜尋來過濾
  --filter=STARS=3000  # 搜尋出來的映象就是STARS大於3000的
[root@ls-Cwj2oH9C ~]# docker search mysql --filter=STARS=3000
NAME      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql     MySQL is a widely used, open-source relation…   12821     [OK]       
mariadb   MariaDB Server is a high performing open sou…   4918      [OK]       
[root@ls-Cwj2oH9C ~]# docker search mysql --filter=STARS=5000
NAME      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql     MySQL is a widely used, open-source relation…   12821     [OK]         

docker pull 下載映象

# 下載映象 docker pull 映象名[:tag]
[root@ls-Cwj2oH9C /]# docker pull mysql
Using default tag: latest    # 如果不寫 tag,預設就是latest
latest: Pulling from library/mysql
72a69066d2fe: Pull complete  # 分層下載,docker image的核心 聯合檔案系統
93619dbc5b36: Pull complete 
99da31dd6142: Pull complete 
626033c43d70: Pull complete 
37d5d7efb64e: Pull complete 
ac563158d721: Pull complete 
d2ba16033dad: Pull complete 
688ba7d5c01a: Pull complete 
00e060b6d11d: Pull complete 
1c04857f594f: Pull complete 
4d7cfa90e6ea: Pull complete 
e0431212d27d: Pull complete 
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709  # 簽名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest  # 真實地址

# 等價於它
docker pull mysql
docker pull docker.io/library/mysql:latest

# 指定版本下載
[root@ls-Cwj2oH9C /]# docker pull mysql:5.7
5.7: Pulling from library/mysql
72a69066d2fe: Already exists 
93619dbc5b36: Already exists 
99da31dd6142: Already exists 
626033c43d70: Already exists 
37d5d7efb64e: Already exists 
ac563158d721: Already exists 
d2ba16033dad: Already exists 
0ceb82207cd7: Pull complete 
37f2405cae96: Pull complete 
e2482e017e53: Pull complete 
70deed891d42: Pull complete 
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

docker rmi 刪除映象!

[root@ls-Cwj2oH9C /]# docker rmi -f 映象id  # 刪除指定的映象
[root@ls-Cwj2oH9C /]# docker rmi -f 映象id 映象id 映象id 映象id  # 刪除多個映象
[root@ls-Cwj2oH9C /]# docker rmi -f $(docker images -aq)  # 刪除全部的映象

容器命令

說明:我們有了映象才可以建立容器,linux,下載一個 centos 映象來測試學習

docker pull centos

新建容器並啟動

docker run [可選引數] image

# 引數說明
--name="Name"    容器名字  tomcat01  tomcat02,用來區分容器
-d               後臺方式執行
-it              使用互動方式執行,進入容器檢視內容
-p               指定容器的埠  -p  8080:8080
    -p ip:主機埠:容器埠
    -p 主機埠:容器埠 (常用)
    -p 容器埠
    容器埠
-p                隨機指定埠

# 測試,啟動並進入容器
[root@ls-Cwj2oH9C ~]# docker run -it centos /bin/bash
[root@26c5b40b2e60 /]# ls  # 檢視容器內的centos,基礎版本,很多命令都是不完善的!
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr

# 從容器中退回主機
[root@c103dbc1d4d4 /]# exit
exit
[root@ls-Cwj2oH9C ~]# cd /
[root@ls-Cwj2oH9C /]# ls
bin   dev  home  lib64       media  opt   root  sbin  sys  usr
boot  etc  lib   lost+found  mnt    proc  run   srv   tmp  var

列出所有的執行的容器

# docker ps 命令
    # 列出當前正在執行的容器
-a  # 列出當前正在執行的容器+帶出歷史執行過的容器
-n=?  # 顯示最近建立的容器

[root@ls-Cwj2oH9C /]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@ls-Cwj2oH9C /]# docker ps -a
CONTAINER ID   IMAGE          COMMAND       CREATED          STATUS                          PORTS     NAMES
c103dbc1d4d4   centos         "/bin/bash"   57 seconds ago   Exited (0) 50 seconds ago                 busy_ramanujan
26c5b40b2e60   centos         "/bin/bash"   11 minutes ago   Exited (0) About a minute ago             thirsty_brahmagupta
1aba774b8be5   feb5d9fea6a5   "/hello"      4 hours ago      Exited (0) 4 hours ago                    quizzical_turing
[root@ls-Cwj2oH9C /]# docker ps -aq
c103dbc1d4d4
26c5b40b2e60
1aba774b8be5

退出容器

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

刪除容器

docker rm 容器id                 # 刪除指定的容器,不能刪除正在執行的容器,如果要強制刪除 rm -f
docker rm -f $(docker ps -aq)    # 刪除所有的容器
docker ps -a -q|xargs docker rm  # 刪除所有的容器

啟動和停止容器的操作

docker start 容器id    # 啟動容器
docker restart 容器id  # 重啟容器
docker stop 容器id     # 停止當前正在執行的容器
docker kill 容器id     # 強制停止當前容器

常用其他命令

後臺啟動容器

# 命令 docker run -d 映象名!
[root@ls-Cwj2oH9C /]# docker run -d centos
d3ebfe17b9c02d91f4f45bc9405b6713b7098e9c2f1229cd6523b46f85531c03

# 問題docker ps,發現 centos 停止了

# 常見的坑:docker 容器使用後臺執行,就必須要有一個前臺程式,docker發現沒有應用,就會自動停止
# nginx,容器啟動後,發現自己沒有提供服務,就會立刻停止,就是沒有程式了

檢視日誌

docker logs -f -t --tail 10 容器  沒有日誌

# 自己編寫一段shell指令碼
[root@ls-Cwj2oH9C /]# docker run -d centos /bin/sh -c "while true;do echo kuangshen;sleep 1;done"
be09e0fd41c70e5d114b5c2534acba6ae97a3a12e1b4d0d603077b83c76697de

# [root@ls-Cwj2oH9C /]# docker ps
CONTAINER ID   IMAGE
be09e0fd41c7   centos
d2ae011f21b8   centos

# 顯示日誌
 -tf            # 顯示日誌
 --tail number  # 要顯示的日誌條數
[root@ls-Cwj2oH9C /]# docker logs -tf --tail 10 be09e0fd41c7

檢視容器中程式資訊 ps

# 命令 docker top 容器id
[root@ls-Cwj2oH9C /]# docker top be09e0fd41c7
UID                 PID                 PPID                C                   STIME     
root                23558               23538               0                   15:53     
root                25465               23558               0                   16:09     

檢視映象的後設資料

# 命令
docker inspect 容器id

# 測試
[root@ls-Cwj2oH9C /]# docker inspect be09e0fd41c7
[
    {
        "Id": "be09e0fd41c70e5d114b5c2534acba6ae97a3a12e1b4d0d603077b83c76697de",
        "Created": "2022-07-05T07:53:54.627754682Z",
        "Path": "/bin/sh",
        "Args": [
            "-c",
            "while true;do echo kuangshen;sleep 1;done"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 23558,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2022-07-05T07:53:54.913270812Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
        "ResolvConfPath": "/var/lib/docker/containers/be09e0fd41c70e5d114b5c2534acba6ae97a3a12e1b4d0d603077b83c76697de/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/be09e0fd41c70e5d114b5c2534acba6ae97a3a12e1b4d0d603077b83c76697de/hostname",
        "HostsPath": "/var/lib/docker/containers/be09e0fd41c70e5d114b5c2534acba6ae97a3a12e1b4d0d603077b83c76697de/hosts",
        "LogPath": "/var/lib/docker/containers/be09e0fd41c70e5d114b5c2534acba6ae97a3a12e1b4d0d603077b83c76697de/be09e0fd41c70e5d114b5c2534acba6ae97a3a12e1b4d0d603077b83c76697de-json.log",
        "Name": "/vigilant_tu",
        "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,
            "CgroupnsMode": "host",
            "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/1a375808cf6a2eff0ce527432ddf9fd9b2c5519b1a71b9c6a5931104f24e55ed-init/diff:/var/lib/docker/overlay2/652792c86aac30ea5e1860169ae46b72da12c74efde67ea5aaba90a396e5989f/diff",
                "MergedDir": "/var/lib/docker/overlay2/1a375808cf6a2eff0ce527432ddf9fd9b2c5519b1a71b9c6a5931104f24e55ed/merged",
                "UpperDir": "/var/lib/docker/overlay2/1a375808cf6a2eff0ce527432ddf9fd9b2c5519b1a71b9c6a5931104f24e55ed/diff",
                "WorkDir": "/var/lib/docker/overlay2/1a375808cf6a2eff0ce527432ddf9fd9b2c5519b1a71b9c6a5931104f24e55ed/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "be09e0fd41c7",
            "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 kuangshen;sleep 1;done"
            ],
            "Image": "centos",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20210915",
                "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": "4b2ab1f2e949baa34edcfd36e72e6ed4a80c5f5381f6183b30ee6d9e73e39e44",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/4b2ab1f2e949",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "83295610dca0bd58cf285f6e7238eaae06749bf30433a75ee9d126dd6f92c25f",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.3",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:03",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "4181a198dd37ad281366217d8321f1ca65fd69f9139e73c0a7fc460afc58fa28",
                    "EndpointID": "83295610dca0bd58cf285f6e7238eaae06749bf30433a75ee9d126dd6f92c25f",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.3",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:03",
                    "DriverOpts": null
                }
            }
        }
    }
]

進入當前正在執行的容器

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

# 命令
docker exec -it 容器id bashShell

# 測試
[root@ls-Cwj2oH9C /]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAMES
be09e0fd41c7   centos    "/bin/sh -c 'while t…"   32 minutes ago   Up 32 minutes             vigilant_tu
d2ae011f21b8   centos    "/bin/bash"              45 minutes ago   Up 45 minutes             mystifying_tereshkova
[root@ls-Cwj2oH9C /]# docker exec -it be09e0fd41c7 /bin/bash
[root@be09e0fd41c7 /]# ls
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr
[root@be09e0fd41c7 /]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 07:53 ?        00:00:01 /bin/sh -c while true;do echo kuangshen;sleep 1;don
root      4191     0  0 09:03 pts/0    00:00:00 /bin/bash
root      4214     1  0 09:03 ?        00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /
root      4215  4191  0 09:03 pts/0    00:00:00 ps -ef

# 方式二
docker attach 容器id
# 測試
[root@ls-Cwj2oH9C /]# docker attach be09e0fd41c7
正在執行當前的程式碼...

# docker exec      # 進入容器後開啟一個新的終端,可以在裡面操作(常用)
# docker attach    # 進入容器正在執行的終端,不會啟動新的程式!

從容器內拷貝檔案到主機上

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

# 檢視當前主機目錄下
[root@ls-Cwj2oH9C home]# ls
kuangshen.java
[root@ls-Cwj2oH9C home]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAMES
17c1f83eeda6   centos    "/bin/bash"              32 seconds ago   Up 31 seconds             relaxed_spence
be09e0fd41c7   centos    "/bin/sh -c 'while t…"   2 hours ago      Up 2 hours                vigilant_tu
d2ae011f21b8   centos    "/bin/bash"              2 hours ago      Up 2 hours                mystifying_tereshkova

# 進入docker容器內部
[root@ls-Cwj2oH9C home]# docker attach 17c1f83eeda6
[root@17c1f83eeda6 /]# cd /home
[root@17c1f83eeda6 home]# ls
# 在容器內新建一個檔案
[root@17c1f83eeda6 home]# touch test.java
[root@17c1f83eeda6 home]# exit
exit
[root@ls-Cwj2oH9C home]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED       STATUS       PORTS     NAMES
be09e0fd41c7   centos    "/bin/sh -c 'while t…"   2 hours ago   Up 2 hours             vigilant_tu
d2ae011f21b8   centos    "/bin/bash"              2 hours ago   Up 2 hours             mystifying_tereshkova
[root@ls-Cwj2oH9C home]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS                     PORTS     NAMES
17c1f83eeda6   centos    "/bin/bash"              2 minutes ago   Exited (0) 7 seconds ago             relaxed_spence
be09e0fd41c7   centos    "/bin/sh -c 'while t…"   2 hours ago     Up 2 hours                           vigilant_tu
d2ae011f21b8   centos    "/bin/bash"              2 hours ago     Up 2 hours                           mystifying_tereshkova
d3ebfe17b9c0   centos    "/bin/bash"              3 hours ago     Exited (0) 3 hours ago               gifted_joliot

# 將這個檔案拷貝出來到主機上
[root@ls-Cwj2oH9C home]# docker cp 17c1f83eeda6:/home/test.java /home
[root@ls-Cwj2oH9C home]# ls
kuangshen.java  test.java
[root@ls-Cwj2oH9C home]# 

# 拷貝是一個手動過程,未來我們使用 -v 卷的技術,可以實現,自動同步

小結

attach :                  	##進入指定執行物件
	[root@VM-0-9-centos ~]# docker attach 96763bc9ea4e 
build : 					##通過Dockerfile定製映象
commit : 					##提交當前容器為新的映象
cp : 						##拷貝指定檔案或目錄到主機
	[root@VM-0-9-centos ~]# docker cp 96763bc9ea4e:/home/test.java /home/test_docker_cp/
create :					##建立新的容器,類似於run,但是不啟動容器
	[root@VM-0-9-centos ~]# docker create centos /bin/bash 
diff:						##檢視docker容器變化
events:						##從docker獲取實時容器事件
exec: 						##進入已經啟動的容器執行指令
	[root@VM-0-9-centos ~]# docker exec -it f170a9b28775 /bin/bash
export: 					##到處容器的內容歸為一個tar文件
history:					##展示一個映象形成歷史
images:						##列出系統當前映象
	[root@VM-0-9-centos ~]# docker images -a
import:						## 從tar包中內容中建立一個新的檔案系統
info:						## 檢視系統詳細資訊
	[root@VM-0-9-centos ~]# docker info
inspect:					## 檢視容器詳細資訊
	[root@VM-0-9-centos ~]# docker inspect f170a9b28775
kill: 						## 強制結束指定容器
load:						## 從一個tar包中載入一個映象
login:						## 註冊或者登入一個docker源伺服器
logout:						## 登出
logs:  						## 輸出當前容器日誌資訊
	docker logs -tf 容器id 			 
	docker logs --tail number 容器id #num為要顯示的日誌條數

port:						## 檢視對映埠對應容器內部的源埠
pasue: 						## 暫停容器
ps:							## 列出容器列表
	docker ps     #執行中列表  
	docker ps -a  #所有容器列表
pull: 						## 從docker源映象拉取指定映象
	docker pull mysql	#預設拉取最新版本mysql
push:						## 推送指定映象或庫映象至docker源伺服器
restart: 					## 重啟正在執行的容器
rm: 						## 移除一個或者多個容器
	docker rm -f $(docker ps -aq)	#移除所有容器
rmi:						## 移除一個或者多個映象
run:						## 建立一個容器並執行內容
	docker run -it centos /bin/bash
save: 						## 儲存一個映象為一個tar包
search: 					## 在docker	hub中搜尋映象
	docker search mysql						#搜尋所有mysql映象
	docker search mysql --filter=STARS=3000 #搜尋收藏數大於3000的映象
start:						## 啟動容器
	docker start [id]
stop:						## 停止容器
	docker stop [id]
tag:						## 給源伺服器中映象設定標籤
top:						## 檢視容器中執行的程式資訊
unpause:					## 取消暫停容器
version:  					## 檢視docker版本號
	docker version
wait:						## 擷取容器停止時的退出狀態值

docker的命令十分多,上面我們學習的那些都是最常用的容器和映象的命令,之後我們還會學習很多命令!

作業練習

Docker 安裝 Nginx

# 1、搜尋映象  search  建議大家去docker hub搜尋,可以看到幫助文件
# 2、下載映象  pull
# 3、執行測試
[root@ls-Cwj2oH9C home]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    605c77e624dd   6 months ago   141MB
centos       latest    5d0da3dc9764   9 months ago   231MB

# -d 後臺執行
# --name 給容器命名
# -p 宿主機埠:容器內部埠
[root@ls-Cwj2oH9C home]# docker run -d --name nginx01 -p 3344:80 nginx
fb127ee2c6ba61f9e42c8664673494314122e48017df0875342fbeed80b81e60
[root@ls-Cwj2oH9C home]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                   NAMES
fb127ee2c6ba   nginx     "/docker-entrypoint.…"   4 seconds ago   Up 4 seconds   0.0.0.0:3344->80/tcp, :::3344->80/tcp   nginx01
be09e0fd41c7   centos    "/bin/sh -c 'while t…"   3 hours ago     Up 3 hours                                             vigilant_tu
d2ae011f21b8   centos    "/bin/bash"              3 hours ago     Up 3 hours                                             mystifying_tereshkova
[root@ls-Cwj2oH9C home]# curl localhost:3344

# 進入容器
[root@ls-Cwj2oH9C home]# docker exec -it nginx01 /bin/bash
root@fb127ee2c6ba:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@fb127ee2c6ba:/# cd /etc/nginx
root@fb127ee2c6ba:/etc/nginx# ls
conf.d	fastcgi_params	mime.types  modules  nginx.conf  scgi_params  uwsgi_params
root@fb127ee2c6ba:/etc/nginx# 

埠暴露的概念

思考問題:我們每次改動nginx配置檔案,都需要進入容器內部,十分的麻煩,我們要是可以在容器外部提供一個對映路徑,達到在容器修改檔名,容器內部就可以自動修改 -v 資料卷!

作業:docker來裝一個tomcat

# 官方的使用
docker run -it --rm tomcat:9.0

# 我們之前的啟動都是後臺,停止了容器之後,容器還是可以查到  docker run -it --rm,一般用來測試,用完就刪除

# 下載再啟動
docker pull tomcat

# 啟動執行
docker run -d -p 3355:8080 --name tomcat01 tomcat

# 測試訪問沒有問題

# 進入容器
[root@ls-Cwj2oH9C /]# docker exec -it tomcat01 /bin/bash

# 發現問題:1、linux命令少了  2、沒有webapps  預設是最小的映象,所有不必要的都剔除掉。
# 保證最小可執行的環境

思考問題:我們以後要部署專案,如果每次都要進入容器是不是十分麻煩?我們要是可以在容器外部提供一個對映路徑,webapps,我們在外部放置專案,就自動同步到內部就好了!

作業:部署 es + kibana

# es 暴露的埠很多!
# es 十分的耗記憶體
# es 的資料一般需要放置到安全目錄!掛載
# --net somenetwork ? 網路配置

# 啟動 elasticsearch
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:latest

# 啟動了 linux就卡住了  docker stats 檢視cpu的狀態

# es 是十分耗記憶體的 2.182GiB  1核2G根本跑不動,會卡死,2核4G起步可以執行!

# 檢視 docker stats

# 測試一下es是否成功了
[root@ls-Cwj2oH9C /]# curl localhost:9200
{
  "name" : "7QxbBIY",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "wUTOoYcpSZaSKV4VALlxeQ",
  "version" : {
    "number" : "5.6.8",
    "build_hash" : "688ecce",
    "build_date" : "2018-02-16T16:46:30.010Z",
    "build_snapshot" : false,
    "lucene_version" : "6.6.1"
  },
  "tagline" : "You Know, for Search"
}

# 趕緊關閉,增加記憶體的限制!

# 關閉es,增加記憶體的限制,修改配置檔案  -e  環境配置修改
docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:latest

# 檢視 docker stats

[root@ls-Cwj2oH9C /]# curl localhost:9200
{
  "name" : "FnQQV4P",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "-M8PzTiLTVCNeZ2AZND1Ig",
  "version" : {
    "number" : "5.6.8",
    "build_hash" : "688ecce",
    "build_date" : "2018-02-16T16:46:30.010Z",
    "build_snapshot" : false,
    "lucene_version" : "6.6.1"
  },
  "tagline" : "You Know, for Search"
}

作業:使用kibana連線elasticsearch?思考網路如何才能連線過去!

視覺化

  • portainer(先用這個)

  • Rancher(CI/CD(Continuous Intergration/Continuous Delpoy)持續整合/持續部署再用)

什麼是portainer?

Docker圖形化介面管理工具!提供一個後臺皮膚供我們操作!

docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

訪問測試:http://182.61.20.38:8088/

通過它來訪問了:

管理員登入後選擇Local Docker後的主介面,注意:管理員只有一個

點選local docker進入後的皮膚,可以檢視容器、映象、卷、網路等的詳細資訊

視覺化皮膚平時不會使用,測試使用即可!

Docker映象詳解

映象是什麼

映象是一種輕量級、可執行的獨立軟體包,用來打包軟體執行環境和基於執行環境開發的軟體,它包含執行某個軟體所需的所有內容,包括程式碼、執行時庫、環境變數和配置檔案。

所有的應用,直接打包docker映象,就可以直接跑起來!

如何得到映象:

  • 從遠端倉庫下載
  • 朋友拷貝給你
  • 自己製作一個映象 DockerFile

Docker映象載入原理

UnionFS(聯合檔案系統)

我們下載的時候看到的一層層就是這個!

UnionFS(聯合檔案系統):Union檔案系統(UnionFS)是一種分層、輕量級並且高效能的檔案系統,它支援對檔案系統的修改作為一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬檔案系統下(unite several directories into a single virtual filesystem)。Union檔案系統時Docker映象的基礎。映象可以通過分層來進行繼承,基於基礎映象(沒有父映象),可以製作各種具體的應用映象。

特性:一次同時載入多個檔案系統,但從外面看起來,只能看到一個檔案系統 ,聯合載入會把各層檔案系統疊加起來,這樣最終的檔案系統會包含所有底層的檔案和目錄。

Docker映象載入原理

docker的映象實際上由一層一層的檔案系統組成,這種層級的檔案系統UnionFS。

bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引導載入kernel,Linux剛啟動時會載入bootfs檔案系統,在Docker映象的最底層是bootfs。這一層與我們典型的Linux/Unix系統是一樣的,包含boot載入器和核心。當boot載入完成之後整個核心就都在記憶體中了,此時記憶體的使用權已由bootfs轉交給核心,此時系統也會解除安裝bootfs。

rootfs(root file system),在bootfs之上。包含的就是典型Linux系統中的/dev,/proc,/bin,/etc 等標準目錄和檔案。rootfs就是各種不同的作業系統發行版,比如Ubuntu,Centos等等。

平時我們安裝進虛擬機器的CentOS都是好幾個G,為什麼Docker這裡才200M?

對於一個精簡的OS,rootfs可以很小,只需要包含最基本的命令,工具和程式庫就可以了,因為底層直接用Host的kernel,自己只需要提供rootfs就可以了,由此可見對於不同的linux發行版,rootfs會有差別,因此不同的發行版可以公用bootfs。

虛擬機器是分鐘級別,容器是秒級!

分層理解

分層的映象

我們可以去下載一個映象,注意觀察下載的日誌輸出,可以看到是一層一層的在下載!

思考:為什麼Docker映象要採用這種分層的結構呢?

最大的好處,莫過於是資源共享了!比如有多個映象都從相同的Base映象構建而來,那麼宿主機只需在磁碟上保留一份base映象,同時記憶體中也只需要載入一份base映象,這樣就可以為所有的容器服務了,而且映象的每一層都可以被分享。

檢視映象分層的方式可以通過 docker image inspect 命令!

[root@ls-Cwj2oH9C ~]# docker image inspect redis:latest
[
    // ......
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:08249ce7456a1c0613eafe868aed936a284ed9f1d6144f7d2d08c514974a2af9",
                "sha256:5659b3a1146e8bdda814e4ad825e107088057e8578c83b758ad6aab93700d067",
                "sha256:cf3ae502d7faa4e90c159cc42b63b46a6be04864fe9d04fb0939e2b0c8b1f7c7",
                "sha256:4ca33072d02630d1d55ada52c3bde95a1ffe02ae60da9ef147c836db444f7a0f",
                "sha256:58bcc523fc9281a3a7033280804e841d1fcec71cbd6359c643c7e06a90efb34c",
                "sha256:be56018ff4790f7f1d96f500e9757c27979c37e476e21a2932746b4654955806"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

理解:

所有的Docker映象都起始於一個基礎映象層,當進行修改或增加新的內容時,就會在當前映象層之上,建立新的映象層。

舉一個簡單的例子,假如基於Ubuntu Linux 16.04 建立一個新的映象,這就是新映象的第一層;如果在該映象中新增Python包,就會在基礎映象之上建立第二個映象層;如果繼續新增一個安全補丁,就會建立第三個映象層。

該映象當前已經包含3個映象層,如下圖所示(這只是一個用於演示的很簡單的例子)。

在新增額外的映象層的同時,映象始終保持是當前所有映象的組合,理解這一點非常重要。下圖舉了一個簡單的例子,每個映象層包含 3 個檔案,而映象包含了來自兩個映象層的 6 個檔案。

上圖中的映象層跟之前圖中的略有區別,主要目的是便於展示檔案。

下圖中展示了一個稍微複雜的三層映象,在外部看來整個映象只有 6 個檔案,這是因為最上層中的檔案7是檔案5的一個更新版本。

這種情況下,上層映象層中的檔案覆蓋了底層映象層中的檔案。這樣就使得檔案的更新版本作為一個新映象層新增到映象當中。

Docker通過儲存引擎(新版本採用快照機制)的方式實現映象層堆疊,並保證多映象層對外展示為統一的檔案系統。

Linux上可用的儲存引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顧名思義,每種儲存引擎都基於Linux中對應的檔案系統或者塊裝置技術,並且每種儲存引擎都有其獨有的效能特點。

Docker在Windows上僅支援windowsfilter一種儲存引擎,該引擎基於NTFS檔案系統之上實現了分層和CoW。下圖展示了與系統顯示相同的三層映象。所有映象層堆疊併合並,對外提供統一的檢視。

特點

Docker映象都是隻讀的,當容器啟動時,一個新的可寫層被載入到映象的頂部!

這一層就是我們通常說的容器層,容器之下的都叫映象層!

如何提交一個自己的映象

commit映象

docker commit 提交容器成為一個新的副本

# 命令和git原理類似
docker commit -m="提交的描述資訊" -a="作者" 容器id 目標映象名:[TAG]

實戰測試

# 啟動一個預設的tomcat

# 發現這個預設的tomcat 是沒有webapps應用,映象的原因,官方的映象預設 webapps下面是沒有檔案的!

# 我自己拷貝進去了基本的檔案
[root@ls-Cwj2oH9C ~]# docker exec -it 11cdc75c9c6e /bin/bash
root@11cdc75c9c6e:/usr/local/tomcat# ls
BUILDING.txt	 LICENSE  README.md	 RUNNING.txt  conf  logs	    temp     webapps.dist
CONTRIBUTING.md  NOTICE   RELEASE-NOTES  bin	      lib   native-jni-lib  webapps  work
root@11cdc75c9c6e:/usr/local/tomcat# cp -r webapps.dist/* webapps

# 將我們操作過的容器通過commit提交為一個映象!我們以後就使用我們修改過的映象即可,這就是我們自己的一個修改的映象

學習方式:理解概念,進行實踐,最後實踐和理論相結合!

如果想要儲存當前容器的狀態,就可以通過commit來提交,獲得一個映象
就像我們之前學習的VM快照功能!

到了這裡才算是入門Docker!

容器資料卷

什麼是容器資料卷

docker理念回顧

將應用和環境打包成一個映象!

資料?如果資料都在容器中,那麼我們容器刪除,資料就會丟失! 需求:資料可以持久化

MySQL,容器刪了,刪庫跑路! 需求:MySQL資料可以儲存在本地!

容器之間可以有一個資料共享的技術!Docker容器中產生的資料,同步到本地!

這就是卷技術!目錄的掛載,將我們容器內的目錄,掛載到Linux上面!

總結一句話:容器的持久化和同步操作!容器間也是可以資料共享的!

使用資料卷

方式一:直接使用命令來掛載 -v

docker run -it -v 主機目錄:容器內目錄

# 測試
[root@ls-Cwj2oH9C ~]# docker run -it -v /home/ceshi:/home centos /bin/bash

# 啟動起來之後,我們可以通過 docker inspect 容器id

測試檔案的同步

再來測試:

  1. 停止容器
  2. 宿主機上修改檔案
  3. 啟動容器
  4. 容器內的資料依舊是同步的

好處:我們以後修改只需要在本地修改即可,容器內會自動同步!

實戰:安裝MySQL

思考:MySQL的資料持久化的問題!

# 獲取映象
[root@ls-Cwj2oH9C ~]# docker pull mysql:5.7

# 執行容器,需要做資料掛載!  # 安裝啟動mysql,需要配置密碼,這是要注意的點!
# 官方測試: docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

# 啟動我們的mysql
 -d 後臺執行
 -p 埠對映
 -v 資料卷掛載
 -e 環境配置
 --name 容器名字
[root@ls-Cwj2oH9C ~]# 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

# 啟動成功之後,我們在本地使用Navicat來連線測試一下(sqlyog反覆嘗試都連不上,Navicat一次成功!)
# Navicat 連線到伺服器的3310 --- 3310和容器內的3306對映,這個時候我們就可以連線上了!

# 在本地測試建立一個資料庫test,檢視一下我們對映的路徑是否ok!

# 假如我們將容器刪除
[root@ls-Cwj2oH9C ~]# docker rm -f mysql01

發現,我們掛載到本地的資料卷依舊沒有丟失,這就實現了容器資料持久化功能!

具名和匿名掛載

# 匿名掛載
-v 容器內路徑!
docker run -d -P --name nginx01 -v /etc/nginx nginx

# 檢視所有的volume的情況
[root@ls-Cwj2oH9C ~]# docker volume ls
DRIVER    VOLUME NAME
local     33a9eda0390dd6b15259dbf0fb1b5828f19bfb8f7e09c5467863862b839f1879
local     b3e57bea4d55bfb0f3cb6640ec6f6518f424218e204826c14a220c910def5a31
local     dd326255ea9dfbf32350012c3d61ec0991a1f0c52f694bab76b2c322c0f60f62
local     f8f8c5df2175bf49695d6799c38b64b8843dce08889bdc0fc869749ac239bee4
local     f57aac3e8dc17710ab8a1151ea48ff97354849624a9478ea4fa7a58e1fd3dec2

# 這裡發現,這種就是匿名掛載,我們在 -v 只寫了容器內的路徑,沒有寫容器外的路徑!

# 具名掛載
[root@ls-Cwj2oH9C home]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
a2a98f1b0f43c47c44ee4d2f6b5047d9ffa1c182e674b8238ad377af13ee188b
[root@ls-Cwj2oH9C home]# docker volume ls
DRIVER    VOLUME NAME
local     33a9eda0390dd6b15259dbf0fb1b5828f19bfb8f7e09c5467863862b839f1879
local     b3e57bea4d55bfb0f3cb6640ec6f6518f424218e204826c14a220c910def5a31
local     dd326255ea9dfbf32350012c3d61ec0991a1f0c52f694bab76b2c322c0f60f62
local     f8f8c5df2175bf49695d6799c38b64b8843dce08889bdc0fc869749ac239bee4
local     f57aac3e8dc17710ab8a1151ea48ff97354849624a9478ea4fa7a58e1fd3dec2
local     juming-nginx

# 通過 -v 卷名:容器內路徑
# 檢視一下這個卷

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

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

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

擴充:

# pwd 顯示當前檔案路徑
# 通過 -v 容器內路徑:ro rw 改變讀寫許可權
ro  readonly  # 只讀
rw  readwrite  # 可讀可寫

# 一旦設定了這個容器許可權,容器對我們掛載出來的內容就有限定了!
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx

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

初始DockerFile

DockerFile就是用來構建docker映象的構建檔案!命令指令碼!先體驗一下!

通過這個指令碼可以生成映象,映象是一層一層的,指令碼就是一個個的命令,每個命令都是一層!

# 建立一個dockerfile檔案,名字可以隨機 建議 Dockerfile
# 檔案中的內容 指令(大寫) 引數
FROM centos

VOLUME ["volume01","volume02"]    # 匿名掛載

CMD echo "----end----"
CMD /bin/bash

# 這裡的每個命令,就是映象的一層!

# 啟動自己寫的容器

這個卷和外部一定有一個同步的目錄!匿名掛載,只寫了容器內的目錄!

檢視一下卷掛載的路徑

測試一下剛才的檔案是否同步出去了!

這種方式我們未來使用的十分多,因為我們通常會構建自己的映象!

假設構建映象的時候沒有掛載卷,要手動映象掛載 -v 卷名 : 容器內路徑!

資料卷容器

多個mysql同步資料!

# 啟動3個容器,通過我們剛才自己的映象啟動

# 測試,可以刪除docker01,檢視一下docker02和docker03是否還可以訪問這個檔案
# 測試依舊可以訪問

多個mysql實現資料共享

[root@ls-Cwj2oH9C ~]# 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
[root@ls-Cwj2oH9C ~]# 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 mysql02 --volumes-from mysql01 mysql:5.7

結論:

容器之間配置資訊的傳遞,資料卷容器的生命週期一直持續到沒有容器使用為止。

但是一旦持久化到了本地,這個時候,本地的資料是不會刪除的!

DockerFile

DockerFile介紹

DockerFile是用來構建docker映象的檔案!命令引數指令碼!

構建步驟:

  1. 編寫一個dockerfile檔案
  2. docker build 構建成為一個映象
  3. docker run 執行映象
  4. docker push 釋出映象(DockerHub、阿里雲映象倉庫!)

檢視一下官方是怎麼做的?

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

官方既然可以製作映象,那麼我們也可以!

DockerFile構建過程

基礎知識:

  1. 每個保留關鍵字(指令)都是必須是大寫字母
  2. 執行從上到下順序執行
  3. # 表示註釋
  4. 每一個指令都會建立提交一個新的映象層,並提交!

DockerFile是面向開發的,我們以後要釋出專案,做映象,就需要編寫dockerfile檔案,這個檔案十分簡單!

Docker映象逐漸成為企業交付的標準,必須要掌握!

步驟:開發,部署,運維。。。缺一不可!

DockerFile:構建檔案,定義了一切的步驟,原始碼

DockerImages:通過DockerFile構建生成的映象,最終釋出和執行的產品!

Docker容器:容器就是映象執行起來提供服務的

DockerFile的指令

以前的話我們就是使用別人的,現在我們知道了這些指令後,我們來練習自己寫一個映象!

FROM        # 基礎映象,一切從這裡開始構建
MAINTAINER  # 映象是誰寫的,姓名+郵箱
RUN         # 映象構建的時候需要執行的命令
ADD         # 步驟,tomcat映象,這個tomcat壓縮包!新增內容
WORKDIR     # 映象的工作目錄
VOLUME      # 掛載的目錄
EXPOSE      # 暴露埠配置
CMD         # 指定這個容器啟動的時候要執行的命令,只有最後一個會生效,可被替代
ENTRYPOINT  # 指定這個容器啟動的時候要執行的命令,可以追加命令
ONBUILD     # 當構建一個被繼承的 DockerFile 這個時候就會執行 ONBUILD 的指令,觸發指令
COPY        # 類似ADD,將我們的檔案拷貝到映象中
ENV         # 構建的時候設定環境變數!

實戰測試

Docker Hub中99%映象都是從這個基礎映象過來的 FROM scratch,然後配置需要的軟體和配置來進行構建

建立一個自己的centos

建立出錯可以檢視我的部落格中遇到的錯誤一欄中的相關內容進行解決!

# 1 編寫Dockerfile的檔案
[root@ls-Cwj2oH9C dockerfile]# cat mydockerfile-centos
FROM centos:7.9.2009
MAINTAINER wydilearn<406623380@qq.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum install vim
RUN yum install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "----end----"
CMD /bin/bash

# 2 通過這個檔案構建映象
# 命令 docker build -f dockerfile檔案路徑 -t 映象名:[tag]
Successfully built 4ca77dadd64f
Successfully tagged mycentos:7.9.2009

# 3 測試執行

對比:之前的原生centos

工作目錄預設是根目錄,沒有vim、ifconfig等命令

我們增加之後的映象:

我們可以列出本地映象的變更歷史

我們平時拿到一個映象,可以研究一下它是怎麼做的了!

CMD 和 ENTRYPOINT 區別

CMD            # 指定這個容器啟動的時候要執行的命令,只有最後一個會生效,可被替代
ENTRYPOINT     # 指定這個容器啟動的時候要執行的命令,可以追加命令

測試cmd

# 編寫 dockerfile 檔案
[root@ls-Cwj2oH9C dockerfile]# vim dockerfile-cmd-test
FROM centos
CMD ["ls","-a"]

# 構建映象
[root@ls-Cwj2oH9C dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest .

# run執行,發現我們的ls -a 命令生效
[root@ls-Cwj2oH9C dockerfile]# docker run 08f5a6379ff7
.
..
.dockerenv
anaconda-post.log
bin
dev
etc
home
lib
lib64

# 想追加一個命令 -l  ls -al
[root@ls-Cwj2oH9C dockerfile]# docker run 08f5a6379ff7 -l
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-l": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled 

# CMD的情況下 -l 替換了CMD ["ls","-a"]命令,-l 不是命令所以報錯!

測試 ENTRYPOINT

[root@ls-Cwj2oH9C dockerfile]# vim dockerfile-cmd-entrypoint
FROM centos:7.9.2009
ENTRYPOINT ["ls","-a"]

[root@ls-Cwj2oH9C dockerfile]# docker build -f dockerfile-cmd-entrypoint -t entrypoint-test .
Sending build context to Docker daemon  4.096kB
Step 1/2 : FROM centos:7.9.2009
 ---> eeb6ee3f44bd
Step 2/2 : ENTRYPOINT ["ls","-a"]
 ---> Running in a11a899f08f4
Removing intermediate container a11a899f08f4
 ---> db46b6b11456
Successfully built db46b6b11456
Successfully tagged entrypoint-test:latest
[root@ls-Cwj2oH9C dockerfile]# docker run d74cdaf8abb6
.
..
.dockerenv
anaconda-post.log
bin
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

# 我們的追加命令,是直接拼接在我們的 ENTRYPOINT 命令的後面!
[root@ls-Cwj2oH9C dockerfile]# docker run d74cdaf8abb6 -l
total 64
drwxr-xr-x   1 root root  4096 Jul 12 08:56 .
drwxr-xr-x   1 root root  4096 Jul 12 08:56 ..
-rwxr-xr-x   1 root root     0 Jul 12 08:56 .dockerenv
-rw-r--r--   1 root root 12114 Nov 13  2020 anaconda-post.log
lrwxrwxrwx   1 root root     7 Nov 13  2020 bin -> usr/bin
drwxr-xr-x   5 root root   340 Jul 12 08:56 dev
drwxr-xr-x   1 root root  4096 Jul 12 08:56 etc
drwxr-xr-x   2 root root  4096 Apr 11  2018 home
lrwxrwxrwx   1 root root     7 Nov 13  2020 lib -> usr/lib
lrwxrwxrwx   1 root root     9 Nov 13  2020 lib64 -> usr/lib64
drwxr-xr-x   2 root root  4096 Apr 11  2018 media
drwxr-xr-x   2 root root  4096 Apr 11  2018 mnt
drwxr-xr-x   2 root root  4096 Apr 11  2018 opt
dr-xr-xr-x 173 root root     0 Jul 12 08:56 proc
dr-xr-x---   2 root root  4096 Nov 13  2020 root
drwxr-xr-x  11 root root  4096 Nov 13  2020 run
lrwxrwxrwx   1 root root     8 Nov 13  2020 sbin -> usr/sbin
drwxr-xr-x   2 root root  4096 Apr 11  2018 srv
dr-xr-xr-x  13 root root     0 Jul  9 02:03 sys
drwxrwxrwt   7 root root  4096 Nov 13  2020 tmp
drwxr-xr-x  13 root root  4096 Nov 13  2020 usr
drwxr-xr-x  18 root root  4096 Nov 13  2020 var

Dockerfile中很多命令都十分的相似,我們需要了解它們的區別,我們最好的學習就是對比他們然後測試效果!

實戰:Tomcat映象

  1. 準備映象檔案 tomcat 壓縮包,jdk的壓縮包!

  2. 編寫dockerfile檔案,官方命名 Dockerfile ,build 會自動尋找這個檔案,就不需要 -f 指定了!

    FROM centos:7.9.2009
    MAINTAINER wydilearn<406623380@qq.com>
    
    COPY readme.txt /usr/local/readme.txt
    
    ADD jdk-8u333-linux-x64.tar /usr/local/
    ADD apache-tomcat-10.0.22.tar.gz /usr/local/
    
    RUN yum -y install vim
    
    ENV MYPATH /usr/local
    WORKDIR $MYPATH
    
    ENV JAVA_HOME /usr/local/jdk1.8.0_333
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    ENV CATALINA_HOME /usr/local/apache-tomcat-10.0.22
    ENV CATALINA_BASE /usr/local/apache-tomcat-10.0.22
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
    
    EXPOSE 8080
    
    CMD /usr/local/apache-tomcat-10.0.22/bin/startup.sh && tail -F /usr/local/apache-tomcat-10.0.22/bin
    /logs/catalina.out
    
  3. 構建映象

    # docker build -t diytomcat .
    
  4. 啟動映象

  5. 訪問測試

  6. 釋出專案(由於做了卷掛載,我們直接在本地編寫專案就可以釋出了!)

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns="http://java.sun.com/xml/ns/javaee"
             xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                                 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
             id="WebApp_ID" version="2.5">
    
    </web-app>
    
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>hello,kuangshen</title>
    </head>
    <body>
    Hello World!<br/>
    <%
    System.out.println("----my test web logs----");
    %>
    </body>
    </html>
    

發現:專案部署成功,可以直接訪問ok!

我們以後開發的步驟:需要掌握Dockerfile的編寫!我們之後的一切都是使用docker映象來發布執行!

釋出自己的映象

DockerHub

  1. 地址 https://hub.docker.com/ 註冊自己的賬號!

  2. 確定這個賬號可以登入

  3. 在我們的伺服器上提交自己的映象

    [root@ls-Cwj2oH9C tomcatlogs]# docker login --help
    
    Usage:  docker login [OPTIONS] [SERVER]
    
    Log in to a Docker registry.
    If no server is specified, the default is defined by the daemon.
    
    Options:
      -p, --password string   Password
          --password-stdin    Take the password from stdin
      -u, --username string   Username
    
  4. 登入完畢後就可以提交映象了,就是一步 docker push

    # 給自己要釋出的映象增加一個 tag
    [root@ls-Cwj2oH9C tomcat]# docker tag 52f83276fc08 wydilearn/diytomcat:1.0
    
    # docker push上去即可!自己釋出的映象儘量帶上版本號
    [root@ls-Cwj2oH9C tomcat]# docker push wydilearn/diytomcat:1.0
    The push refers to repository [docker.io/wydilearn/diytomcat]
    3c40fff9f2ee: Pushed 
    fc3bd8b32ed0: Pushed 
    f8c82bfdcfb9: Pushed 
    a5760cf5dc3b: Pushed 
    174f56854903: Mounted from library/centos 
    1.0: digest: sha256:e0fae8f6383fdbf05a1fc89676fd7696949fc16d378f698a60918cb16a0fabb9 size: 1373
    

    提交的時候也是按照映象的層級來進行提交的。

釋出到阿里雲映象服務上

  1. 登入阿里雲

  2. 找到容器映象服務

  3. 建立名稱空間

  4. 建立容器映象

  5. 瀏覽阿里雲

阿里雲容器映象就參考官方地址!

小結

Docker 網路

理解Docker0

清空所有環境

測試

三個網路

# 問題:docker 是如何處理容器網路訪問的?

[root@ls-Cwj2oH9C /]# docker run -d -P --name tomcat01 tomcat

# 檢視容器的內部網路地址 ip addr,發現容器啟動的時候會得到一個 eth0@if2763 IP地址,docker分配的!
[root@ls-Cwj2oH9C /]# docker exec -it 232419b4b0ff /bin/bash  # 進入容器安裝兩個命令
root@232419b4b0ff:/usr/local/tomcat# apt update && apt install -y iproute2
root@232419b4b0ff:/usr/local/tomcat# apt install iputils-ping
root@232419b4b0ff:/usr/local/tomcat# ip addr
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
2762: eth0@if2763: <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@ls-Cwj2oH9C /]# 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.047 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.044 ms

# linux可以ping通容器內部

原理

  1. 我們每啟動一個docker容器,docker就會給docker容器分配一個IP,我們只要安裝了docker,就會有一個網路卡 docker0

    橋接模式,使用的技術是 evth-pair 技術!

    再次測試ip addr

  2. 再啟動一個容器測試,發現又多了一對網路卡!

    # 我們發現這個容器帶來網路卡,都是一對一對的
    # evth-pair 就是一堆的虛擬裝置介面,他們都是成對出現的,一端連著協議,一端彼此相連
    # 正因為有這個特性,evth-pair充當一個橋樑,連線各種虛擬網路裝置
    # OpenStac,Docker容器之間的連線,OVS的連線,都是使用evth-pair技術
    
  3. 我們來測試下tomcat01和tomcat02是否可以ping通!

    # 進入tomcat02
    [root@ls-Cwj2oH9C /]# docker exec -it tomcat02 /bin/bash
    root@fde1226260aa:/usr/local/tomcat# apt update && apt install -y iproute2
    root@fde1226260aa:/usr/local/tomcat# apt install iputils-ping
    root@fde1226260aa:/usr/local/tomcat# 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.087 ms
    64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.071 ms
    

    結論:容器和容器之間是可以互相ping通的!

繪製一個網路模型圖:

結論:tomcat01 和 tomcat02 是共用的一個路由器,docker0。

所有的容器不指定網路的情況下,都是 docker0 路由的,docker會給我們的容器分配一個預設的可用IP

小結

Docker中的所有網路介面都是虛擬的。虛擬的轉發效率高!

只要容器刪除,對應的一對網橋就沒了!

思考一個場景,我們編寫了一個微服務,database url=ip:,專案不重啟資料庫ip換掉了,我們希望可以處理這個問題,可以通過名字來進行訪問容器?

[root@ls-Cwj2oH9C ~]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known

# 如何可以解決呢?
# 通過--link 就可以解決網路連通問題
[root@ls-Cwj2oH9C ~]# docker run -it -d -P --name tomcat03 --link tomcat02 tomcat
371f584079471c6b8934c5ee961d741dba06884e0e85135bd0d224f685f0d6ca
[root@ls-Cwj2oH9C ~]# docker exec -it tomcat03 /bin/bash
root@371f58407947:/usr/local/tomcat# apt update && apt install -y iproute2
root@371f58407947:/usr/local/tomcat# apt install iputils-ping
root@371f58407947:/usr/local/tomcat# 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.111 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.062 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.061 ms

探究:inspect!

其實這個tomcat03就是在本地配置了tomcat02配置

# 檢視 hosts 配置,在這裡原理發現!
[root@ls-Cwj2oH9C ~]# docker exec -it tomcat03 /bin/bash
root@371f58407947:/usr/local/tomcat# 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 fde1226260aa
172.17.0.4	371f58407947

本質探究:--link 就是在hosts配置中增加了一個 172.17.0.3 tomcat02 fde1226260aa

我們現在用Docker,已經不建議使用 --link 了!

自定義網路!不使用docker0!

docker0的問題:它不支援容器名連線訪問!

自定義網路

檢視所有的docker網路

網路模式

bridge:橋接模式 docker(預設,自己建立也使用 bridge 橋接模式)

none:不配置網路

host:和宿主機共享網路

container:容器內網路連通!(用的較少!侷限很大)

三種常見網路模式(補充)

bridged(橋接模式)

虛擬機器和宿主計算機處於同等地位,虛擬機器就像是一臺真實主機一樣存在於區域網中

NAT(網路地址轉換模式)

宿主計算機相當於一臺開啟了DHCP功能的路由器,而虛擬機器則是內網中的一臺真實主機

host-only(僅主機模式)

相當於虛擬機器通過雙絞線和宿主計算機直連,而宿主計算機不提供任何路由服務。因此在Host-only模式下,虛擬機器可以和宿主計算機互相訪問,但是虛擬機器無法訪問外部網路。

測試

# 我們直接啟動的命令 --net bridge,而這個就是我們的docker0
[root@ls-Cwj2oH9C /]# docker run -d -P --name tomcat01 tomcat
[root@ls-Cwj2oH9C /]# docker run -d -P --name tomcat01 --net bridge tomcat

# docker0特點,預設,域名不能訪問,--link可以打通連線!

# 我們可以自定義一個網路!
# --driver bridge
# --subnet 192.168.0.0/16  192.168.0.2 192.168.255.255
# --gateway 192.168.0.1
[root@ls-Cwj2oH9C /]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
c82c2708387b95f0d932ae395fe0dc1d3182d38a47b820584c66e39219541eb4
[root@ls-Cwj2oH9C /]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
1340a553ba22   bridge    bridge    local
6f12b7793243   host      host      local
c82c2708387b   mynet     bridge    local
2581ba94b5d9   none      null      local

我們自己的網路就建立好了!

[root@ls-Cwj2oH9C /]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
e1d698bdf7bd90daf158e00e7f3c69785590198b477e1b45ef0fb2f6d2dd8ed6
[root@ls-Cwj2oH9C /]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
685b7164f606200c809c81858a291374171ed2ddf77e30e24f94fbbbbcdbe2e1
[root@ls-Cwj2oH9C /]# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "c82c2708387b95f0d932ae395fe0dc1d3182d38a47b820584c66e39219541eb4",
        "Created": "2022-07-16T17:38:25.818266785+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "685b7164f606200c809c81858a291374171ed2ddf77e30e24f94fbbbbcdbe2e1": {
                "Name": "tomcat-net-02",
                "EndpointID": "7a3ac62a87388c10907bee1b83800d28968caf47160bec9999c3921a3e5183ff",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            },
            "e1d698bdf7bd90daf158e00e7f3c69785590198b477e1b45ef0fb2f6d2dd8ed6": {
                "Name": "tomcat-net-01",
                "EndpointID": "ea12cb9879b8d6801eabd3510e67e3a546888723ea743eedaec5274cca080ff0",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

# 再次測試ping連線
[root@ls-Cwj2oH9C ~]# docker exec -it tomcat-net-01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.085 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.070 ms

# 現在不使用--link也可以ping名字了!
[root@ls-Cwj2oH9C ~]# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.055 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.063 ms

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

好處:

redis - 不同的叢集使用不同的網路,保證叢集是安全和健康的

mysql - 不同的叢集使用不同的網路,保證叢集是安全和健康的

網路連通

# 測試打通 tomcat01 - mynet

# 連通之後就是將 tomcat01 放到了 mynet 網路下

# 一個容器兩個ip地址!

# 阿里雲服務:公網ip  私網ip

# 01 連通ok
[root@ls-Cwj2oH9C ~]# docker exec -it tomcat01 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.072 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.070 ms

# 02 是依舊打不通的
[root@ls-Cwj2oH9C ~]# docker exec -it tomcat02 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known

結論:假設要跨網路操作別人,就需要使用 docker network connect 連通!

實戰:部署Redis叢集

shell指令碼

# 建立網路卡
[root@ls-Cwj2oH9C /]# docker network create redis --subnet 172.38.0.0/16

# 通過指令碼建立六個redis配置
[root@ls-Cwj2oH9C /]# 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.38.0.1${port}
> cluster-announce-port 6379
> cluster-announce-bus-port 16379
> appendonly yes
> EOF
> done

[root@ls-Cwj2oH9C conf]# 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.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

[root@ls-Cwj2oH9C 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.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

[root@ls-Cwj2oH9C 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.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

[root@ls-Cwj2oH9C 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.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

[root@ls-Cwj2oH9C 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.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

[root@ls-Cwj2oH9C 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.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

# 任意進入一個reids容器,注意使用 /bin/sh 而不是 /bin/bash
[root@ls-Cwj2oH9C conf]# docker exec -it redis-1 /bin/sh

# 建立叢集
/data # redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6
379 172.38.0.15:6379 172.38.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.38.0.15:6379 to 172.38.0.11:6379
Adding replica 172.38.0.16:6379 to 172.38.0.12:6379
Adding replica 172.38.0.14:6379 to 172.38.0.13:6379
M: f142bdcc5c5d7ac81eb70d91da9987b71a79d2e2 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
M: 3ab93307a4de5df775702779665ca4583abe5210 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
M: abe4ba6a98b5fe967d952ffc06060d7c07474821 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
S: ca57da80daea08a065f5add0a607edde9d11e7eb 172.38.0.14:6379
   replicates abe4ba6a98b5fe967d952ffc06060d7c07474821
S: e9664d81440a18689a1d8cd00f7a191f78f0979c 172.38.0.15:6379
   replicates f142bdcc5c5d7ac81eb70d91da9987b71a79d2e2
S: f972b8b774941d383a26ab31cc337c5017657ba0 172.38.0.16:6379
   replicates 3ab93307a4de5df775702779665ca4583abe5210
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
...
>>> Performing Cluster Check (using node 172.38.0.11:6379)
M: f142bdcc5c5d7ac81eb70d91da9987b71a79d2e2 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: abe4ba6a98b5fe967d952ffc06060d7c07474821 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: ca57da80daea08a065f5add0a607edde9d11e7eb 172.38.0.14:6379
   slots: (0 slots) slave
   replicates abe4ba6a98b5fe967d952ffc06060d7c07474821
S: f972b8b774941d383a26ab31cc337c5017657ba0 172.38.0.16:6379
   slots: (0 slots) slave
   replicates 3ab93307a4de5df775702779665ca4583abe5210
S: e9664d81440a18689a1d8cd00f7a191f78f0979c 172.38.0.15:6379
   slots: (0 slots) slave
   replicates f142bdcc5c5d7ac81eb70d91da9987b71a79d2e2
M: 3ab93307a4de5df775702779665ca4583abe5210 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

/data # redis-cli -c
127.0.0.1:6379> cluster info
127.0.0.1:6379> cluster nodes
127.0.0.1:6379> set a b

[root@ls-Cwj2oH9C ~]# docker stop redis-3
redis-3

127.0.0.1:6379> get a
-> Redirected to slot [15495] located at 172.38.0.14:6379
"b"

docker搭建redis叢集完成!

我們使用了docker之後,所有的技術都會慢慢的變得簡單起來!

SpringBoot微服務打包Docker映象

  1. 構建springboot專案

    @RestController
    public class HelloController {
    
        @RequestMapping("/hello")
        public String hello(){
            return "hello,wydilearn";
        }
    }
    
  2. 打包應用

  3. 編寫dockerfile

    FROM java:8
    
    COPY *.jar /app.jar
    
    CMD ["--server.port=8080"]
    
    EXPOSE 8080
    
    ENTRYPOINT ["java","-jar","/app.jar"]
    
  4. 構建映象

    [root@ls-Cwj2oH9C home]# mkdir idea
    [root@ls-Cwj2oH9C home]# cd idea
    [root@ls-Cwj2oH9C idea]# ls
    demo1-0.0.1-SNAPSHOT.jar  Dockerfile
    [root@ls-Cwj2oH9C idea]# docker build -t wydilearn .
    
  5. 釋出執行!

    [root@ls-Cwj2oH9C idea]# docker run -d -P --name wydilearn-springboot-web wydilearn
    cd4d8f37d9e980af091eceac6ef30f51b9291fc415c53457285353881e19f84b
    [root@ls-Cwj2oH9C idea]# docker ps
    CONTAINER ID   IMAGE       COMMAND                  CREATED          STATUS          PORTS                                         NAMES
    cd4d8f37d9e9   wydilearn   "java -jar /app.jar …"   37 seconds ago   Up 36 seconds   0.0.0.0:49163->8080/tcp, :::49163->8080/tcp   wydilearn-springboot-web
    [root@ls-Cwj2oH9C idea]# curl localhost:49163
    {"timestamp":"2022-07-17T04:04:03.880+00:00","status":404,"error":"Not Found","path":"/"}
    [root@ls-Cwj2oH9C idea]# curl localhost:49163/hello
    

以後我們使用了Docker之後,給別人交付的就是一個映象即可!

到了這裡我們已經完全夠用了Docker!

未完待續。。。

相關文章