1. 程式人生 > 其它 >手擼狂神版Docker筆記

手擼狂神版Docker筆記

Docker

Docker學習

  • Docker概述
  • Docker安裝
  • Docker命令
    • 映象命令
    • 容器命令
    • 操作命令
  • Docker映象
  • 容器的資料卷
  • DockerFIle
  • Docker網路原理
  • IDEA整合Docker
  • Docker Compose
  • Docker Swarm
  • CI\CD jenkins

Docker概述

Docker為什麼會出現?

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

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

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

釋出一個專案(Jar+ (Redis,ES, Hadoop)),專案為什麼不帶上環境安裝打包

在伺服器上配置十分麻煩,不能夠跨平臺

Windows開發,釋出到Linux

傳統開發: 開發人員做專案,運維人員做部署

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

java – apk – 釋出(應用商店) --使用者使用apk-- 安裝即用

java — jar(環境) — 打包上線自帶環境(映象) —(Docker倉庫: 商店) — 下載我們釋出的映象 — 直接執行即可

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

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

文件地址: https://docs.docker.com/get-docker/

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

Docker能幹嘛?

之前的虛擬機器技術

虛擬機器技術缺點:

  • 資源佔用十分多

  • 冗餘技術多

  • 啟動很慢

容器化技術

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

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

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

DevOps(開發,運維)

更快速的交付和部署

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

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

更便捷的升級和擴縮容

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

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

更簡單的系統運維

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

更高效的計算資源利用:

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

Docker安裝

Docker的基本組成

映象(image):

docker映象好比一個模板,可以通過這個模板來建立容器服務,tomcat映象===>run ==>tomcat01容器(提供伺服器)

通過這個映象可以建立多個容器(最終服務執行或者專案執行就是在容器中的)

容器(container):

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

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

倉庫(repository):

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

倉庫分為共有倉庫和私有倉庫

Docker Hub(預設是國外的)

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

安裝Docker

環境準備

  1. 需要會一點點Linux基礎
  2. CentOS7
  3. 使用Xshell連線遠端伺服器

環境檢視

 # 檢視系統核心
[root@iZ2zeheduaqlfxyl598si8Z /]# uname -r
3.10.0-1062.18.1.el7.x86_64
# 系統版本
[root@CZP ~]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

安裝Docker

檢視幫助文件

# 一, 解除安裝舊的版本
$ sudo 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 \
    https://download.docker.com/linux/centos/docker-ce.repo # 預設是國外的

yum-config-manager \
    --add-repo \
    https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 推薦使用
# 更新yum軟體包索引
yum makecache fast
# 安裝docker    
sudo yum install docker-ce docker-ce-cli containerd.io 
# 啟動docker
systemctl start docker
# 檢視docker版本
docker version

下載映象

docker pull [要下載的軟體]

檢視下載的映象

docker images

解除安裝docker

yum remove docker-ce docker-ce-cli containerd.io

rm -rf /var/lib/docker#docker預設工作路徑

阿里雲配置Docker映象加速

執行命令

sudo mkdir -p /etc/docker

sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["阿里雲映象加速地址"]
}
EOF

sudo systemctl daemon-reload

sudo systemctl restart docker

底層原理

Docker是怎麼工作的?

Docker是一個C/S結構的系統,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     # 檢視某個具體的命令

映象命令

檢視下載的所有映象

# docker images
REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
mysql                     5.6                 8de95e6026c3        20 hours ago        302MB
redis                     latest              36304d3b4540        12 days ago         104MB
mysql                     latest              30f937e841c8        2 weeks ago         541MB
centos/mysql-57-centos7   latest              f83a2938370c        8 months ago        452MB
# 解釋
REPOSITORY 映象的倉庫名
TAG 映象的標籤
IMAGE ID 映象ID
CREATED 映象建立時間
SIZE 映象的大小

# 可選項
Options:
  -a, --all             # 列出所有映象
  -q, --quiet           # 只顯示映象ID

搜尋映象

# docker search 

[root@CZP ~]# docker search mysql
NAME	DESCRIPTION									STARS	OFFICIAL	AUTOMATED	
mysql	MySQL is a widely used, open-source relation…  9604     [OK]                

# 可選項,通過收藏來過濾
--filter=stars=3000 # 搜尋出來的映象收藏就是大於3000的

下載映象

# docker pull 

[root@CZP ~] # docker pull nginx [:tag]
Using default tag: latest # 如果不寫tag 預設使用最新版本
latest: Pulling from library/nginx
8559a31e96f4: Pull complete  # 分層下載,docker image核心 聯合檔案系統
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 # 真實地址

# docker pull nginx 等價於 dicker pull docker.io/library/nginx:latest


#指定版本下載

刪除映象

# docker rmi 

# 刪除指定的容器
[root@CZP ~]# docker rm -f 8de95e6026c3 
# 刪除全部的容器
[root@CZP ~]# docker rm -f $(docker -ap) 

容器命令

說明 : 有了映象才可以建立容器,

docker pull [image]

新建容器並啟動

# docker run  [可選引數] image

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

列出所有執行的容器

# docker ps 命令	(不加引數)列出當前正在執行的容器

# 引數說明
-a		# 列出當前正在執行的容器+歷史執行過的容器
-n=?	# 顯示最近建立的容器
-q		# 只顯示容器的編號

[root@CZP ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@CZP ~]# docker ps -a 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                    PORTS               NAMES
919e58ff5521        redis               "docker-entrypoint.s…"   20 hours ago        Exited (0) 16 hours ago                       redis

退出容器

exit 		 # 直接容器停止並退出
ctrl + p + q # 直接退出容器

刪除容器

docker rm 容器id						# 刪除指定容器(可一次刪除多個,各id之間用空格隔開)
docker rm -f[遞迴] $(docker ps -aq) 	# 遞迴刪除所有的容器
docker ps -a | xargs docker rm 		 # 遞迴刪除所有的容器

啟動和停止容器的操作

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

常用的其他命令

後臺啟動容器

# 命令docker run -d 映象名

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

檢視日誌

docker logs -f -t --tail 容器

# 引數說明
	-tf				# 顯示日誌
	--tail number 	# 要顯示的日誌條數
	
    [root@localhost ~]# docker logs -tf --tail 10 centosv1
    2021-06-26T01:38:12.739000465Z [root@ef24fc0af36a /]# docker ps
    2021-06-26T01:38:12.739180686Z bash: docker: command not found
    2021-06-26T01:38:21.504914487Z [root@ef24fc0af36a /]# exit
    2021-06-26T01:38:21.504931415Z exit
	

檢視容器中程序資訊

docker top 容器id 

[root@CZP ~]# docker top 63d4c4115212
UID                 PID                 PPID                C                   STIME 
polkitd             2319                2301                0                   12:33

檢視映象元資料

# 命令
docker inspect 容器id


# 測試
[root@CZP ~]# docker inspect 63d4c4115212 
[
    {
        "Id": "63d4c41152126cae276b69e1100520f9d6d867f950e488b5488de68181b7870b",
        "Created": "2020-06-10T04:33:13.666827714Z",
        "Path": "docker-entrypoint.sh",
        "Args": [
            "redis-server"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 2319,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2020-06-10T04:33:14.008260846Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:36304d3b4540c5143673b2cefaba583a0426b57c709b5a35363f96a3510058cd",
        "ResolvConfPath": "/var/lib/docker/containers/63d4c41152126cae276b69e1100520f9d6d867f950e488b5488de68181b7870b/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/63d4c41152126cae276b69e1100520f9d6d867f950e488b5488de68181b7870b/hostname",
        "HostsPath": "/var/lib/docker/containers/63d4c41152126cae276b69e1100520f9d6d867f950e488b5488de68181b7870b/hosts",
        "LogPath": "/var/lib/docker/containers/63d4c41152126cae276b69e1100520f9d6d867f950e488b5488de68181b7870b/63d4c41152126cae276b69e1100520f9d6d867f950e488b5488de68181b7870b-json.log",
        "Name": "/redis",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {
                "6379/tcp": [
                    {
                        "HostIp": "",
                        "HostPort": "6379"
                    }
                ]
            },
            "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/db63749d3abd5e587a88360e27fc9b5b0db7069b45e2bd8c48c75e25eba89100-init/diff:/var/lib/docker/overlay2/30d298e0d46edd68a8cbb588247384b9516d1140f5ca592b7f0b1c04618111f0/diff:/var/lib/docker/overlay2/af6963cd652870740eec10549b2a6c8f08b94edb3a3cea1a42d727026bb6d5a0/diff:/var/lib/docker/overlay2/af514c78199cdcfb30194921b892782dacbe1a3f439167f2f434b2f5a55ab5c3/diff:/var/lib/docker/overlay2/b1e020f1a03a66483794af0cf20d59e8dfa471f692ecaa145398d30500370a2a/diff:/var/lib/docker/overlay2/e55685d1f4ea504c3df5c3cbe822ab000f6412d3eff50b6b8ba097fb551ad922/diff:/var/lib/docker/overlay2/df78a0d3f0dbc449650ce5605d67ff45e93dbadc4fe93d2b7552203a31ab46a8/diff",
                "MergedDir": "/var/lib/docker/overlay2/db63749d3abd5e587a88360e27fc9b5b0db7069b45e2bd8c48c75e25eba89100/merged",
                "UpperDir": "/var/lib/docker/overlay2/db63749d3abd5e587a88360e27fc9b5b0db7069b45e2bd8c48c75e25eba89100/diff",
                "WorkDir": "/var/lib/docker/overlay2/db63749d3abd5e587a88360e27fc9b5b0db7069b45e2bd8c48c75e25eba89100/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [
            {
                "Type": "volume",
                "Name": "f544b94e9e0129e7f438b851edbfc94a82c96e6fdda44179d38e20f800878a6a",
                "Source": "/var/lib/docker/volumes/f544b94e9e0129e7f438b851edbfc94a82c96e6fdda44179d38e20f800878a6a/_data",
                "Destination": "/data",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
        "Config": {
            "Hostname": "63d4c4115212",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "6379/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "GOSU_VERSION=1.12",
                "REDIS_VERSION=6.0.4",
                "REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.0.4.tar.gz",
                "REDIS_DOWNLOAD_SHA=3337005a1e0c3aa293c87c313467ea8ac11984921fab08807998ba765c9943de"
            ],
            "Cmd": [
                "redis-server"
            ],
            "Image": "36304d3b4540",
            "Volumes": {
                "/data": {}
            },
            "WorkingDir": "/data",
            "Entrypoint": [
                "docker-entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": {}
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "5f8321169dfd067e45f2921d73984d0d76e953cd642d93990d1ed8a3227ad53f",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {
                "6379/tcp": [
                    {
                        "HostIp": "0.0.0.0",
                        "HostPort": "6379"
                    }
                ]
            },
            "SandboxKey": "/var/run/docker/netns/5f8321169dfd",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "33eafd9f86d5e7a3b29ed09fe75d8eb27e0227a07607960550dfef7f620a6872",
            "Gateway": "172.18.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.18.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:12:00:02",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "228826a97a0b066a01811c098e4c4985804598571b9c8d9ad4205a0ee75c8b5b",
                    "EndpointID": "33eafd9f86d5e7a3b29ed09fe75d8eb27e0227a07607960550dfef7f620a6872",
                    "Gateway": "172.18.0.1",
                    "IPAddress": "172.18.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:12:00:02",
                    "DriverOpts": null
                }
            }
        }
    }

進入當前正在執行的容器

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

# 命令
docker exec -it 容器id  bashshell 預設命令列

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

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

docker cp 容器id:容器內路徑 目的主機路徑
  attach      Attach  to a running container 											# 進入容器內部,不啟動新的程序
  build       Build an image from a Dockerfile 											# 通過dockerfile 定製映象
  commit      Create a new image from a container's changes 							# 提交當前容器為新的映象
  cp          Copy files/folders between a container and the local filesystem 			# 從容器中拷貝指定的檔案或者目錄到宿主機上
  create      Create a new container 													# 建立一個新的容器,同run 但不啟動容器
  diff        Inspect changeson a container's filesystem 								# 檢視docker容器變化
  events      Get real time events from the server										# 從docker服務獲取容器實時事件
  exec        Run a command in a running container										# 在已存在的容器上執行命令
  export      Export a container's filesystem as a tar archive							# 匯出容器的內容流作為一個tar歸檔檔案[對應import]
  history     Show the history of an image												# 展示一個映象形成歷史
  images      List images																# 列出系統當前映象
  import      Import the contents from a tarball to create a filesystem image			# 從tar包中的內容建立一個新的檔案系統映像[對應export]
  info        Display system-wide information											# 顯示系統相關資訊
  inspect     Return low-level information on Docker objects							# 檢視容器詳細資訊
  kill        Kill one or more running containers										# kill指定docker容器
  load        Load an image from a tar archive or STDIN									# 從一個tar包載入一個映象[對應save]
  login       Log in to a Docker registry												# 註冊或者登入一個docker源伺服器
  logout      Log out from a Docker registry											# 從當前docker registry退出
  logs        Fetch the logs of a container												# 輸出當前容器日誌資訊
  pause       Pause all processes within one or more containers							# 暫停容器
  port        List port mappings or a specific mapping for the container				# 檢視對映埠對應的容器內部源埠
  ps          List containers															# 列出容器列表
  pull        Pull an image or a repository from a registry								# 從docker映象源伺服器拉取指定映象或庫映象
  push        Push an image or a repository to a registry								# 推送指定映象或庫映象至docker源伺服器
  rename      Rename a container														# 重新命名容器
  restart     Restart one or more containers											# 重啟執行的容器
  rm          Remove one or more containers												# 移除一個或多個容器
  rmi         Remove one or more images													# 移除一個或多個映象(沒有容器使用當前映象才可刪除,否則需要刪除相關容器或者使用-f引數強制刪除)
  run         Run a command in a new container											# 建立一個新的容器並執行一個命令
  save        Save one or more images to a tar archive (streamed to STDOUT by default)	# 儲存一個映象為一個tar包[對應load]
  search      Search the Docker Hub for images											# 在docker hub中搜索映象
  start       Start one or more stopped containers										# 啟動容器
  stats       Display a live stream of container(s) resource usage statistics			# 檢視cpu的狀態
  stop        Stop one or more running containers										# 停止容器
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE						# 給源中映象打標籤
  top         Display the running processes of a container								# 檢視容器中執行的程序資訊
  unpause     Unpause all processes within one or more containers						# 取消暫停容器
  update      Update configuration of one or more containers							# 更新一個或多個容器的配置
  version     Show the Docker version information										# 檢視docker版本號
  wait        Block until one or more containers stop, then print their exit codes		# 擷取容器停止時的退出狀態值

Docker 安裝Nginx

#1. 搜尋映象 search 建議大家去docker搜尋,可以看到幫助文件
#2. 拉取映象 pull
#3、執行測試
# -d 後臺執行
# --name 給容器命名
# -p 宿主機埠:容器內部埠
➜  ~ docker run -d --name nginx00 -p 82:80 nginx
75943663c116f5ed006a0042c42f78e9a1a6a52eba66311666eee12e1c8a4502
➜  ~ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
75943663c116        nginx               "nginx -g 'daemon of…"   41 seconds ago      Up 40 seconds       0.0.0.0:82->80/tcp   nginx00
➜  ~ curl localhost:82   #測試
<!DOCTYPE html>,,,,

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

作業:docker 來裝一個tomcat

# 官方的使用
docker run -it --rm tomcat:9.0
# 之前的啟動都是後臺,停止了容器,容器還是可以查到, docker run -it --rm image 一般是用來測試,用完就刪除
--rm       Automatically remove the container when it exits
#下載
docker pull tomcat
#啟動執行
docker run -d -p 8080:8080 --name tomcat01 tomcat
#測試訪問有沒有問題
curl localhost:8080

#進入容器
➜  ~ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
db09851cf82e        tomcat              "catalina.sh run"   28 seconds ago      Up 27 seconds       0.0.0.0:8080->8080/tcp   tomcat01
➜  ~ docker exec -it db09851cf82e /bin/bash             
root@db09851cf82e:/usr/local/tomcat# 
# 發現問題:1、linux命令少了。 2.沒有webapps

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

作業:部署es+kibana

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

# 啟動elasticsearch
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
# 測試一下es是否成功啟動
➜  ~ curl localhost:9200
{
  "name" : "d73ad2f22dd3",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "atFKgANxS8CzgIyCB8PGxA",
  "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"
}
➜  ~ docker stats # 檢視docker容器使用記憶體情況

CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDS
bd4094db247f        elasticsearch       1.57%               1.226GiB / 3.7GiB   33.13%              0B / 0B             0B / 0B             42
94b00b6f6172        tomcat              0.18%               78.58MiB / 3.7GiB   2.07%               1.69kB / 2.47kB     0B / 0B             37
d458bc50a808        nginx01             0.00%               1.883MiB / 3.7GiB   0.05%               5.22kB / 6.32kB     0B / 0B             3
63d4c4115212        redis               0.14%               9.637MiB / 3.7GiB   0.25%               10.8kB / 14.2kB     0B / 0B             7
# elasticsearch十分佔用記憶體,需要修改配置檔案 -e 限制其啟動的記憶體
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e ES_JAVA_OPTS= 
"-Xms64m -Xmx 512m"  elasticsearch:7.6.2
[root@CZP ~]# curl localhost:9200
{
  "name" : "bd4094db247f",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "U3TfPp1rQ6uitn0WMh6pRQ",
  "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"
}

docker和kibana如何連線

視覺化

  • portainer(先用這個)
docker run -d -p 8080:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
  • Rancher(CI/CD再用)

什麼是portainer?

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

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

訪問測試: 外網: 8088 http://外網ip:8088/

進入之後的面板

Docker映象講解

映象是什麼

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

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

如何得到映象:

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

Docker映象載入原理

UnionFs(聯合檔案系統查詢)

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

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

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

Docker映象載入原理

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

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

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

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

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

分層理解

分層的映象

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

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

最大好處,我覺得莫過於資源共享了!比如有多個映象都從相同的Base映象構建而來,那麼宿主機

只需在磁碟上保留一份base映象,同時記憶體中也只需要載入一份base映象,這樣就可以為所有的容器服務了,而且映象的每一層都可以被共享

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

[root@CZP ~]# docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
nginx                 latest              2622e6cca7eb        32 hours ago        132MB
portainer/portainer   latest              cd645f5a4769        9 days ago          79.1MB
redis                 latest              36304d3b4540        13 days ago         104MB
mysql                 latest              30f937e841c8        2 weeks ago         541MB
tomcat                9.0                 1b6b1fe7261e        3 weeks ago         647MB
elasticsearch         7.6.2               f29a1ee41030        2 months ago        791MB
elasticsearch         latest              5acf0e8da90b        20 months ago       486MB
[root@CZP ~]# docker image inspect redis
[
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:ffc9b21953f4cd7956cdf532a5db04ff0a2daa7475ad796f1bad58cfbaf77a07",
                "sha256:d4e681f320297add0ede0554524eb9106d8c3eb3a43e6e99d79db6f76f020248",
                "sha256:59bd5a888296b623ae5a9efc8f18285c8ac1a8662e5d3775a0d2d736c66ba825",
                "sha256:c112794a20c5eda6a791cbec8700fb98eab30671a2248ac7e2059b475c46c45f",
                "sha256:bf8b736583f08c02b92f8a75ac5ea181e4d74107876177caa80ddad8b6b57a72",
                "sha256:6ef422d19214800243b28017d346c7ab9bfe63cb198a39312d1714394b232449"
            ]
    }
]

理解:

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

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

該映象已經包含3個映象層,如下圖所示(這只是一個簡單的例子)


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

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

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

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

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

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

Docker在Windows上僅支援windosfilter一種儲存引擎,該引擎基於NTFS檔案系統之上實現了分層和CoW[1]

下圖展示了與系統顯示相同的三層映象,所有的映象層堆疊合並,對外提供統一的檢視層

特點

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

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

如何提交一個自己的映象

commit映象

docker commit 提交容器成為一個新的映象

# 命令和git原理類似
docker commit -m="提交的描述資訊" -a="作者" 容器ID 目標映象名:[tag]
[root@CZP ~]# docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                                            NAMES
db186da947d7        portainer/portainer   "/portainer"             16 hours ago        Up 16 hours         0.0.0.0:8088->9000/tcp                           interesting_shockley
bd4094db247f        elasticsearch:7.6.2   "/usr/local/bin/dock…"   17 hours ago        Up 17 hours         0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp   elasticsearch
94b00b6f6172        tomcat:9.0            "catalina.sh run"        17 hours ago        Up 17 hours         0.0.0.0:8080->8080/tcp                           tomcat
d458bc50a808        nginx                 "/docker-entrypoint.…"   18 hours ago        Up 18 hours         0.0.0.0:80->80/tcp                               nginx01
63d4c4115212        36304d3b4540          "docker-entrypoint.s…"   22 hours ago        Up 22 hours         0.0.0.0:6379->6379/tcp                           redis
[root@CZP ~]# docker commit -a="czp" -m="add basic webapps app" 94b00b6f6172 tomcat_9.0:1.0
sha256:75e6ea173695b146c9ddf9d5865e7bdeb78e69c84d2d3520e516cd9f498a1e9a
[root@CZP ~]# docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
tomcat_9.0            1.0                 75e6ea173695        8 seconds ago       652MB
nginx                 latest              2622e6cca7eb        33 hours ago        132MB
portainer/portainer   latest              cd645f5a4769        9 days ago          79.1MB
redis                 latest              36304d3b4540        13 days ago         104MB
mysql                 latest              30f937e841c8        2 weeks ago         541MB
tomcat                9.0                 1b6b1fe7261e        3 weeks ago         647MB
elasticsearch         7.6.2               f29a1ee41030        2 months ago        791MB
elasticsearch         latest              5acf0e8da90b        20 months ago       486MB

容器資料卷

什麼是容器資料卷

docker的理念回顧

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

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

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

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

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

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

使用資料卷

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

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

# 啟動起來我們可以使用 docker inspect 容器id
# 將宿主機的/root/test掛載到tomcat的/home目錄
[root@CZP ~]# docker run -d -p 9999:8080 -v /root/test:/home --name="tomcat01"  1b6b1fe7261e
015001911b67f5e357b93c6bb05ebaf07aebe4f3abc455f9aa439afd83b9af78
[root@CZP ~]# docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                                            NAMES
015001911b67        1b6b1fe7261e          "catalina.sh run"        16 seconds ago      Up 15 seconds       0.0.0.0:9999->8080/tcp                           tomcat01
db186da947d7        portainer/portainer   "/portainer"             17 hours ago        Up 17 hours         0.0.0.0:8088->9000/tcp                           interesting_shockley
bd4094db247f        elasticsearch:7.6.2   "/usr/local/bin/dock…"   18 hours ago        Up 17 hours         0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp   elasticsearch
94b00b6f6172        tomcat:9.0            "catalina.sh run"        18 hours ago        Up 18 hours         0.0.0.0:8080->8080/tcp                           tomcat
d458bc50a808        nginx                 "/docker-entrypoint.…"   18 hours ago        Up 18 hours         0.0.0.0:80->80/tcp                               nginx01
63d4c4115212        36304d3b4540          "docker-entrypoint.s…"   22 hours ago        Up 22 hours         0.0.0.0:6379->6379/tcp                           redis

# 進入tomcat內部
[root@CZP test]# docker exec -it tomcat01 /bin/bash
root@015001911b67:/usr/local/tomcat# cd /home
# 在home目錄建立b.java
root@015001911b67:/home# touch b.java
root@015001911b67:/home# read escape sequence
[root@CZP test]# cd /root/test
[root@CZP test]# ll
total 0
-rw-r--r-- 1 root root 0 Jun 11 11:03 b.java # b.java顯示掛載成功

實戰: 安裝Mysql

思考: mysql的資料持久化的問題, data目錄

# 獲取映象
[root@CZP ~]# docker pull mysql:5.7


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

# 啟動mysql
-d  後臺執行
-p  埠對映
-v  埠對映
-e  環境配置
--name 容器名

[root@CZP czp]# docker run -d -p 3306:3306 -v /usr/czp/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=sa --name mysql mysql:5.7

# 啟動成功之後,我們在本地使用sqlyog來連線測試一下

# sqlyog-連線到伺服器的埠 ---伺服器埠和容器埠對映,這個時候我們就可以連線上了

假設我們將容器刪除

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

具名掛載和匿名掛載

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

# 檢視所有的卷的情況
[root@CZP data]# docker volume ls

local               2c04226b82b31e3cddb80b5fffa17685883ff8c256024525b3a65b07b8281110

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


# 具名掛載
[root@CZP data]# docker run -d -p 9099:80 -v nginxConfig:/etc/nginx 2622e6cca7eb
bd7ebf502166e5569ea3fb5eddaf41f4ff9a70df62b9143861dd702ae8c1cb31
[root@CZP data]# docker volume ls
DRIVER              VOLUME NAME
local               nginxConfig
# 通過 -v 卷名:容器內路徑
# 檢視一下這個卷

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

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

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

擴充套件:

# 通過 -v  容器內路徑: ro rw 改變讀寫許可權
ro read only
read and write

# 一旦設定了容器許可權,容器對掛載出來的內容就有限定了!
docker -run -P -name nginx01 -v /etc/nginx:ro nginx
docker -run -P -name nginx01 -v /etc/nginx:rw nginx
ro : 只要看到ro就說明這個路徑只能通過宿主機來改變,容器內部無法操作

初始Dockerfile

Dockerfile就是用來構建Dockerfile映象的檔案! 命令指令碼!

# 建立一個dockerfile檔案,名字可以隨機 建議 dockerfile
# 檔案中的內容

FROM centos

VOLUME ["volume01","volume02"]

CMD echo "---end---"
CMD /bin/hash

這個卷和外部一定有一個同步的目錄

檢視一下卷掛載的路徑

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

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

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

資料卷容器

兩個Mysql同步資料!

# 啟動三個容器,通過我們剛才自己的映象啟動
# 測試: 可以刪除docker01,檢視一下docker02和docker03是否還可以訪問這個檔案
# 測試依舊可以訪問

結論:

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

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

Dockerfile

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

構建步驟:

  1. 編寫一個dockerfile指令碼
  2. docker build 構建成為一個映象
  3. docker run 執行映象
  4. docker push釋出映象(Docker hub , 阿里雲映象倉庫! )

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

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

Dockerfile構建過程

很多指令:

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

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

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

步驟: 開發,部署,上線,運維…缺一不可

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

DockerImages: 通過DockerFile構建生成的映象,最終釋出執行的產品,原來是一個jar,war

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

DockerFile的指令

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

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

實戰測試

Docker Hub 中99%映象都是從centos基礎映象過來的,然後配置需要的軟體

建立一個自己的centos

# 1 編寫一個DOckerfile的檔案

FROM centos

MAINTAINER czp<[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---"


# 2. 通過這個檔案構建映象
# 命令 docker build -f dockerfile檔案路徑 -t
Successfully built 5ebc296aad5a
Successfully tagged mycentos:1.0

# 3. 測試執行

增強之後的映象

我們可以列出本地程序的歷史

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

CMD 和ENTRYPOINT的區別

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

測試cmd命令

# 編寫
[root@CZP dockerfile]# cat dockerfile-centos-test 
FROM centos
CMD ["ls","-a"]


# 構建映象
[root@CZP dockerfile]# docker build -f dockerfile-centos-test -t centostest .

# 想要追加一個命令 -l  ls -al
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.
ERRO[0000] error waiting for container: context canceled 

# cmd的情況下 替換了CMD["ls","-a"]命令,-不是命令追加

ENTRYPOINT是往命令之後追加

實戰:Tomcat映象

  1. 準備映象檔案. tomcat壓縮包, jdk壓縮包!
  2. 編寫Dockerfile檔案, 官方命名 Dockerfile, build會自動尋找這個檔案,就不需要 -f 指定了!
FROM centos
MAINTAINER czp<[email protected]>

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

ADD apache-tomcat-9.0.33.tar.gz /usr/local/

ADD jdk-8u221-linux-x64.rpm /usr/local/


RUN yum -y install vim
 
ENV MYPATH /usr/local
 
WORKDIR $MYPATH
 
ENV JAVA_HOME /usr/local/jdk1.8.0_11
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.33

ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.33

# 配置環境變數
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:/CATALINA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-9.0.33/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.33/bin/logs/catalina.out
  1. 構建映象
# docker build -t diytomcat .
  1. 本地測試

curl localhost:9090

釋出自己的映象

DockerHub

  1. 地址hub.docker.com 註冊自己的賬號!
  2. 確定這個賬號可以登入
  3. 在伺服器上提交自己的映象
[root@CZP ~]# 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
  1. 登入完畢就可以提交映象了,就是一步 docker push
#push自己的映象到伺服器上一定要帶上版本號
[root@CZP ~]# docker push czp/centos:1.0


docker tag [id] [tag] 為容器新增一個版本

提交到阿里雲映象倉庫

  1. 登入阿里雲
  2. 找到容器映象服務
  3. 建立名稱空間
  1. 建立容器映象
  1. 瀏覽阿里雲

小結

Docker網路

理解docker0

測試

三個網路

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

原理

  1. 我們每啟動一個docker容器,docker就會給docker容器分配一個ip,我們只要安裝了docker,就會有一個網絡卡docker0,橋接模式,使用的技術是evth-pair技術!

再次測試 ip addr

  1. 再啟動一個容器
# 我們發現這個容器帶來網絡卡, 都是一對對的
# evth-pair 就是一對虛擬機器裝置介面,他們都是成對出現的,一端連著協議,一端彼此相連
# 正因為有這個特性,veth-pair 充當橋樑,連線各種虛擬網路裝置的
# openStac,Docker容器之間的連線,OVS的連線,都是使用 evth-pair 技術
  1. 我們來測試一下

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

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

小結

Docker 使用的是Linux的橋接,宿主機中是一個Docker容器的網橋,docker0

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

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

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

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

# 如何可以解決呢?


# 通過 --link 就可以解決網路問題
[root@CZP ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.18.0.4) 56(84) bytes of data.
64 bytes from tomcat02 (172.18.0.4): icmp_seq=1 ttl=64 time=0.128 ms
64 bytes from tomcat02 (172.18.0.4): icmp_seq=2 ttl=64 time=0.097 ms
64 bytes from tomcat02 (172.18.0.4): icmp_seq=3 ttl=64 time=0.091 ms
64 bytes from tomcat02 (172.18.0.4): icmp_seq=4 ttl=64 time=0.109 ms
64 bytes from tomcat02 (172.18.0.4): icmp_seq=5 ttl=64 time=0.097 ms
64 bytes from tomcat02 (172.18.0.4): icmp_seq=6 ttl=64 time=0.096 ms
64 bytes from tomcat02 (172.18.0.4): icmp_seq=7 ttl=64 time=0.092 ms
64 bytes from tomcat02 (172.18.0.4): icmp_seq=8 ttl=64 time=0.094 ms
64 bytes from tomcat02 (172.18.0.4): icmp_seq=9 ttl=64 time=0.102 ms
^C
--- tomcat02 ping statistics ---
9 packets transmitted, 9 received, 0% packet loss, time 1007ms
rtt min/avg/max/mdev = 0.091/0.100/0.128/0.015 ms


# 反向是否可以ping通嗎
[root@CZP ~]# docker exec -it tomcat02 ping tomcat03
/etc/hosts  配置埠和域名的繫結

本地探究 – link 就是我們在host配置中增加了一個172.18.0.3 tomcat02 312857784cd4

我們現在玩Docker已經不建議使用–link了!

自定義網路,不使用docker0!

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

自定義網路

檢視所有的docker網路

網路模式

bridge : 橋接 docker 大橋

none: 不配置網路

host: 和宿主機共享網路

container: 容器內網路聯通!

測試

# 直接啟動的命令 --net brodge,預設docker0
docker run -d -P --name tomcat01 --net bridge tomcat

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

# 自定義

[root@CZP ~]# docker network create --help

Usage:	docker network create [OPTIONS] NETWORK

Create a network

Options:
      --attachable           Enable manual container attachment
      --aux-address map      Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
      --config-from string   The network from which copying the configuration
      --config-only          Create a configuration only network
  -d, --driver string        Driver to manage the Network (default "bridge")
      --gateway strings      IPv4 or IPv6 Gateway for the master subnet
      --ingress              Create swarm routing-mesh network
      --internal             Restrict external access to the network
      --ip-range strings     Allocate container ip from a sub-range
      --ipam-driver string   IP Address Management Driver (default "default")
      --ipam-opt map         Set IPAM driver specific options (default map[])
      --ipv6                 Enable IPv6 networking
      --label list           Set metadata on a network
  -o, --opt map              Set driver specific options (default map[])
      --scope string         Control the network's scope
      --subnet strings       Subnet in CIDR format that represents a network segment

[root@CZP ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
677fae13a48c634dc03c56641b9ba31354846d31a196fdcb92c9ef6ddff73150
[root@CZP ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
228826a97a0b        bridge              bridge              local
c3b4884cd4db        host                host                local
677fae13a48c        mynet               bridge              local
35885200f93d        none                null                local

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

[root@CZP ~]#  docker run -d -P --name tomcat-net-01 --net mynet tomcat:9.0
336dd072ca17ac1adf514c44c8dcbd3358146d6d60667f3a0f99dbbb3e305f09
[root@CZP ~]#  docker run -d -P --name tomcat-net-02 --net mynet tomcat:9.0
2cea3bb29350ae99ce26c1bf6f8d1f2dcfb25bf8042193263ce275308e9eb42d
[root@CZP ~]# docker network inspect mynet
[
   {
       "Name": "mynet",
       "Id": "677fae13a48c634dc03c56641b9ba31354846d31a196fdcb92c9ef6ddff73150",
       "Created": "2020-06-14T16:49:14.554786193+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": {
           "2cea3bb29350ae99ce26c1bf6f8d1f2dcfb25bf8042193263ce275308e9eb42d": {
               "Name": "tomcat-net-02",
               "EndpointID": "ebff8e9ef22bd3d66d0de4229d1f3a3c610785b23005294f60f96f3089d52c3d",
               "MacAddress": "02:42:c0:a8:00:03",
               "IPv4Address": "192.168.0.3/16",
               "IPv6Address": ""
           },
           "336dd072ca17ac1adf514c44c8dcbd3358146d6d60667f3a0f99dbbb3e305f09": {
               "Name": "tomcat-net-01",
               "EndpointID": "69451bb0c95ed27d207cd2bade9c57fd2625c245b8b8cb3e5d0dea530a368683",
               "MacAddress": "02:42:c0:a8:00:02",
               "IPv4Address": "192.168.0.2/16",
               "IPv6Address": ""
           }
       },
       "Options": {},
       "Labels": {}
   }
]

現在不使用–link也可以ping名字了,推薦使用這種網路

[root@CZP ~]# docker exec 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.080 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.096 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.086 ms
^C
[root@CZP ~]# 

好處:

不同的叢集使用不同的叢集,保證叢集之間是安全和健康的

網路聯通

# 測試打通 tomcat01到tomcat-net-01
# 連通之後就是將 tomcat01 放到了mynet網路下
# 一個容器兩個ip   阿里雲: 公網ip 私網ip

這樣容器之間就可以ping通了

實戰 redis叢集部署

# 建立網絡卡
docker network create --subnet 172.38.0.0/16 redis

# 通過指令碼建立六個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.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done



# 通過指令碼執行六個redis
for port in $(seq 1 6);\
do \
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf 
done

# 停止redis並刪除容器
for port in $(seq 1 6);\
do \
docker stop redis-${port}; \
docker rm redis-${port};
done

docker exec -it redis-1 /bin/sh #redis預設沒有bash
redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379  --cluster-replicas 1

叢集搭建成功

SpringBoot微服務打包Docker映象

  1. 構建springBoot專案
  2. 打包應用
  3. 編寫dockerfile
  4. 構建映象
  5. 釋出執行
願君前程似錦,歸來仍是少年