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://docs.docker.com/ Docker的文件是超級詳細的!
Docker能幹嘛
之前的虛擬機器技術!
虛擬機器技術缺點:
-
資源佔用十分多
-
冗餘步驟多
-
啟動很慢!
容器化技術
容器化技術不是模擬的一個完整的作業系統
比較Docker 和 虛擬機器技術的不同:
- 傳統虛擬機器,虛擬出一套硬體,執行一個完整的作業系統,然後在這個系統上安裝和執行軟體
- 容器內的應用直接執行在宿主機的核心,容器是沒有自己的核心的,也沒有虛擬我們的硬體,所以就輕便了
- 每個容器間是互相隔離的,每個容器內都有一個屬於自己的檔案系統,互不影響。
DevOps(開發、運維)
應用更快速的交付和部署
傳統:一堆幫助文件,安裝程式
Docker:打包映象,釋出測試,一鍵執行
更便捷的升級和擴縮容
使用了Docker之後,我們部署應用就和搭積木一樣!
專案打包為一個映象,擴充套件 伺服器A!伺服器B
更簡單的系統運維
在容器化之後,我們的開發、測試環境都是高度一致的。
更高效的計算資源利用
Docker 是核心級別的虛擬化,可以在物理機上可以執行很多的容器例項!伺服器的效能可以被壓榨到極致。
Docker 安裝
Docker的基本組成
映象(image):
docker映象就像一個模板,可以通過這個模板來建立服務,tomcat映象 ==> run ==> tomcat01容器(提供服務),通過這個映象可以建立多個容器(最終服務執行或者專案執行就是在容器中的)。
容器(container):
Docker利用容器技術,獨立執行一個或者一組應用,通過映象來建立。
啟動,停止,刪除,基本命令!
目前可以把這個容器理解為就是一個簡易的linux系統
倉庫(repository):
倉庫就是存放映象的地方!
倉庫分為公有倉庫和私有倉庫!
Docker Hub(預設是國外的)
阿里雲...都有容器伺服器(配置映象加速!)
安裝Docker
環境準備
- 需要會一點點的Linux基礎
- CentOS 7
- 我們使用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的預設工作路徑!
阿里雲映象加速
-
登入阿里雲找到容器服務
-
找到映象加速的地址
-
配置使用
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 快?
-
Docker有著比虛擬機器更少的抽象層
-
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
測試檔案的同步
再來測試:
- 停止容器
- 宿主機上修改檔案
- 啟動容器
- 容器內的資料依舊是同步的
好處:我們以後修改只需要在本地修改即可,容器內會自動同步!
實戰:安裝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映象的檔案!命令引數指令碼!
構建步驟:
- 編寫一個dockerfile檔案
- docker build 構建成為一個映象
- docker run 執行映象
- docker push 釋出映象(DockerHub、阿里雲映象倉庫!)
檢視一下官方是怎麼做的?
發現官方的映象都是基礎包,很多功能沒有,我們通常會自己搭建自己的映象!
官方既然可以製作映象,那麼我們也可以!
DockerFile構建過程
基礎知識:
- 每個保留關鍵字(指令)都是必須是大寫字母
- 執行從上到下順序執行
#
表示註釋- 每一個指令都會建立提交一個新的映象層,並提交!
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映象
-
準備映象檔案 tomcat 壓縮包,jdk的壓縮包!
-
編寫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
-
構建映象
# docker build -t diytomcat .
-
啟動映象
-
訪問測試
-
釋出專案(由於做了卷掛載,我們直接在本地編寫專案就可以釋出了!)
<?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
-
地址 https://hub.docker.com/ 註冊自己的賬號!
-
確定這個賬號可以登入
-
在我們的伺服器上提交自己的映象
[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
-
登入完畢後就可以提交映象了,就是一步 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
提交的時候也是按照映象的層級來進行提交的。
釋出到阿里雲映象服務上
-
登入阿里雲
-
找到容器映象服務
-
建立名稱空間
-
建立容器映象
-
瀏覽阿里雲
阿里雲容器映象就參考官方地址!
小結
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通容器內部
原理
-
我們每啟動一個docker容器,docker就會給docker容器分配一個IP,我們只要安裝了docker,就會有一個網路卡 docker0
橋接模式,使用的技術是 evth-pair 技術!
再次測試ip addr
-
再啟動一個容器測試,發現又多了一對網路卡!
# 我們發現這個容器帶來網路卡,都是一對一對的 # evth-pair 就是一堆的虛擬裝置介面,他們都是成對出現的,一端連著協議,一端彼此相連 # 正因為有這個特性,evth-pair充當一個橋樑,連線各種虛擬網路裝置 # OpenStac,Docker容器之間的連線,OVS的連線,都是使用evth-pair技術
-
我們來測試下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中的所有網路介面都是虛擬的。虛擬的轉發效率高!
只要容器刪除,對應的一對網橋就沒了!
--link
思考一個場景,我們編寫了一個微服務,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映象
-
構建springboot專案
@RestController public class HelloController { @RequestMapping("/hello") public String hello(){ return "hello,wydilearn"; } }
-
打包應用
-
編寫dockerfile
FROM java:8 COPY *.jar /app.jar CMD ["--server.port=8080"] EXPOSE 8080 ENTRYPOINT ["java","-jar","/app.jar"]
-
構建映象
[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 .
-
釋出執行!
[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!
未完待續。。。