Docker的學習流程
- 概述
- 安裝
- 命令
- 鏡像
- 容器
- 操作
- …………
- Docker鏡像
- 容器數據卷
- DockerFile
- Docker網絡原理
- IDEA整合Docker
- Docker Compose
- Docker Swarm
- CI \ CD Jenkins
Docker概述
問題
環境不同,版本更新,導致服務不可用,對於運維來說,考驗十分大,環境配置麻煩,每個機器都要部署環境, 部署集群,費時費力,發布jar包或war包,需要redis、mysql、jdk、ES等環境,發布項目等時候能包含環境一起發過去,項目能帶上環境打包,環境配置麻煩,並且軟件可能不能跨平台。
解決

Docker的思想就來源於集裝箱 container ,現在的是隔離的思想,將所有的東西打包裝箱,每個container都是相互隔離的,為了讓完全不同的東西能放在同一個環境中運行,通過鏡像或稱為容器,Docker通過隔離機制,能將服務器利用到極致。
Docker基於Go語言開發的!開源項目!
Docker官網:https://www.docker.com/
文檔:https://docs.docker.com/ Docker的文檔是超級詳細的!
以前的虛擬技術
1、 資源占用十分多
2、 冗余步驟多
3、 啟動很慢!

容器化技術
容器化技術不是模擬一個完整的操作系統 ,比較Docker和虛擬機技術的不同:
- 傳統虛擬機,虛擬出一條硬件,運行一個完整的操作系統,然后在這個系統上安裝和運行軟件。
- 容器內的應用直接運行在宿主機的內容,容器是沒有自己的內核的,也沒有虛擬我們的硬件,所以就輕便了。
- 每個容器間是互相隔離,每個容器內都有一個屬於自己的文件系統,互不影響。

DevOps(開發、運維)
用更快速的交付和部署
傳統:一對幫助文檔,安裝程序。
Docker:打包鏡像發布測試一鍵運行。
更便捷的升級和擴縮容
使用了 Docker之后,我們部署應用就和搭積木一樣,項目打包為一個鏡像,擴展服務器A!服務器B
更簡單的系統運維
在容器化之后,我們的開發,測試環境都是高度一致的。
更高效的計算資源利用
Docker是內核級別的虛擬化,可以在一個物理機上可以運行很多的容器實例!服務器的性能可以被壓榨到極致。
Docker歷史
2010年,幾個的年輕人,就在美國成立了一家公司 DotCloud,做一些pass的雲計算服務!LXC(Linux Container容器)有關的容器技術!Linux Container容器是一種內核虛擬化技術,可以提供輕量級的虛擬化,以便隔離進程和資源。他們將自己的技術(容器化技術)命名就是 Docker,Docker剛剛延生的時候,沒有引起行業的注意!DotCloud,就活不下去!
開源
2013年,Docker開源!越來越多的人發現Docker的優點!火了。Docker每個月都會更新一個版本!
2014年4月9日,Docker1.0發布!Docker為什么這么火?十分的輕巧!在容器技術出來之前,我們都是使用虛擬機技術!
虛擬機:在window中裝一個VMware,通過這個軟件我們可以虛擬出來一台或者多台電腦!笨重!
虛擬機也屬於虛擬化技術,Docker容器技術,也是一種虛擬化技術!
Docker
Docker的基本組成

鏡像(image)
Docker鏡像就好比是一個目標,可以通過這個目標來創建容器服務,Tomcat鏡像=>run=>容器(提供服務器),通過這個鏡像可以創建多個容器(最終服務運行或者項目運行就是在容器中的)。
容器(container)
Docker利用容器技術,獨立運行一個或者一,通過鏡像來創建的。啟動,停止,刪除,基本命令
目前就可以把這個容器理解為就是一個簡易的 Linux系統。
倉庫(repository)
倉庫就是存放鏡像的地方,倉庫分為公有倉庫和私有倉庫。(很類似git)Docker Hub是國外的。阿里雲…都有容器服務器(配置鏡像加速!)
Docker安裝
環境准備
-
Linux要求內核3.0以上
-
CentOS 7
幫助文檔:https://docs.docker.com/engine/install/
- 如果有要先卸載就得版本: yum remove docker
安裝
-
需要的安裝包, yum install -y yum-utils
-
設置鏡像的倉庫
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相關的 Docker-ce 社區版 而ee是企業版, yum install docker-ce docker-ce-cli containerd.io ,這里我們使用社區版即可
-
啟動Docker, systemctl start docker
-
使用Docker version查看是否按照成功,docker version
-
test, docker run hello-world
-
查看已經下載的鏡像(從這里可以查看已有鏡像的id), docker images
卸載Docker
-
卸載依賴,yum remove docker-ce docker-ce-cli containerd.io
-
刪除資源,rm -rf /var/lib/docker,/var/lib/docker 是docker的默認工作路徑!
使用流程
docker run流程

底層原理
Docker是怎么工作的?
Docker是一個Client-Server結構的系統,Docker的守護進程運行在主機上。通過Socket從客戶端訪問!
Docker-Server接收到Docker-Client的指令,就會執行這個命令!

為什么Docker比Vm快?
- Docker有着比虛擬機更少的抽象層。由於Docker不需要Hypervisor實現硬件資源虛擬化,運行在Docker容器上的程序直接使用的都是實際物理機的硬件資源。因此在CPU、內存利用率上Docker將會在效率上有明顯優勢。
- Docker利用的是宿主機的內核,而不需要Guest OS( VM(虛擬機)里的的系統(OS) )。

Docker的常用命令
幫助文檔的地址:https://docs.docker.com/engine/reference/commandline/build/
幫助命令
docker version #顯示docker的版本信息。
docker info #顯示docker的系統信息,包括鏡像和容器的數量
docker 命令 --help #幫助命令
鏡像命令
docker images #查看所有本地主機上的鏡像 可以使用docker image ls代替
docker search #搜索鏡像
docker pull #下載鏡像 docker image pull
docker rmi #刪除鏡像 docker image rm
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 4 months ago 13.3kB
mysql 5.7 b84d68d0a7db 6 days ago 448MB
# 解釋
#REPOSITORY # 鏡像的倉庫源
#TAG # 鏡像的標簽(版本) ---lastest 表示最新版本
#IMAGE ID # 鏡像的id
#CREATED # 鏡像的創建時間
#SIZE # 鏡像的大小
容器命令
我們有了鏡像才可以創建容器
docker pull centos #docker中下載centos
docker run 鏡像id #新建容器並啟動
docker ps 列出所有運行的容器 docker container list
docker rm 容器id #刪除指定容器
docker start 容器id #啟動容器
docker restart 容器id #重啟容器
docker stop 容器id #停止當前正在運行的容器
docker kill 容器id #強制停止當前容器
退出容器
exit #容器直接退出
ctrl +P +Q #容器不停止退出 ---注意:這個很有用的操作
刪除容器
docker rm 容器id #刪除指定的容器,不能刪除正在運行的容器,如果要強制刪除 rm -rf
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 start 容器id #啟動容器
docker restart 容器id #重啟容器
docker stop 容器id #停止當前正在運行的容器
docker kill 容器id #強制停止當前容器
啟動和停止容器的操作
docker start 容器id #啟動容器
docker restart 容器id #重啟容器
docker stop 容器id #停止當前正在運行的容器
docker kill 容器id #強制停止當前容器
常用其他命令
后台啟動命令
docker run -d centos
查看日志
docker logs
查看容器中進程信息ps
命令 docker top 容器id
查看鏡像的元數據
docker inspect 容器id
宿主機端口 和 容器內部端口 以及端口暴露:

命令大全
attach Attach local standard input, output, and error streams to a running container
#當前shell下 attach連接指定運行的鏡像
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 #創建一個新的容器
diff Inspect changes to files or directories on a container's filesystem #查看docker容器的變化
events Get real time events from the server # 從服務獲取容器實時時間
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包中導入內容創建一個文件系統鏡像
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 #
logout Log out from a 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
push Push an image or a repository to a registry
rename Rename a container
restart Restart one or more containers
rm Remove one or more containers
rmi Remove one or more images
run Run a command in a new container
save Save one or more images to a tar archive (streamed to STDOUT by default)
search Search the Docker Hub for images
start Start one or more stopped containers
stats Display a live stream of container(s) resource usage statistics
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
wait Block until one or more containers stop, then print their exit codes
Portainer 可視化面板安裝
portainer 是 Docker圖形化界面管理工具!提供一個后台面板供我們操作!
docker run -d -p 8080:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
鏡像原理之聯合文件系統
鏡像是什么
鏡像是一種輕量級、可執行的獨立軟件包,用來打包軟件運行環境和基於運行環境開發的軟件,他包含運行某個軟件所需的所有內容,包括代碼、運行時庫、環境變量和配置文件。所有應用,直接打包Docker鏡像,就可以直接跑起來!
如何得到鏡像
- 從遠程倉庫下載
- 別人拷貝給你
- 自己制作一個鏡像 DockerFile
Docker鏡像加載原理
UnionFs (聯合文件系統)
UnionFs(聯合文件系統):Union文件系統(UnionFs)是一種分層、輕量級並且高性能的文件系統,他支持對文件系統的修改作為一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬文件系統下( unite several directories into a single virtual filesystem)。Union文件系統是 Docker鏡像的基礎。鏡像可以通過分層來進行繼承,基於基礎鏡像(沒有父鏡像),可以制作各種具體的應用鏡像。
特性:一次同時加載多個文件系統,但從外面看起來,只能看到一個文件系統,聯合加載會把各層文件系統疊加起來,這樣最終的文件系統會包含所有底層的文件和目錄。
Docker鏡像加載原理
==Docker的鏡像實際上由一層一層的文件系統組成,這種層級的文件系統UnionFS。
boots(boot file system)主要包含 bootloader和 Kernel, bootloader主要是引導加 kernel, Linux剛啟動時會加bootfs文件系統,在 Docker鏡像的最底層是 boots。這一層與我們典型的Linux/Unix系統是一樣的,包含boot加載器和內核。當boot加載完成之后整個內核就都在內存中了,此時內存的使用權已由 bootfs轉交給內核,此時系統也會卸載bootfs。
rootfs(root file system),在 bootfs之上。包含的就是典型 Linux系統中的/dev,/proc,/bin,/etc等標准目錄和文件。 rootfs就是各種不同的操作系統發行版,比如 Ubuntu, Centos等等。
分層理解
我們可以去下載一個鏡像,注意觀察下載的日志輸出,可以看到是一層層的在下載
思考:為什么Docker鏡像要采用這種分層的結構呢?
最大的好處,我覺得莫過於資源共享了!比如有多個鏡像都從相同的Base鏡像構建而來,那么宿主機只需在磁盤上保留一份Base鏡像,同時內存中也只需要加載一份Base鏡像,這樣就可以為所有的容器服務了,而且鏡像的每一層都可以被共享。
查看鏡像分層的方式可以通過docker image inspect 命令
理解
所有的 Docker鏡像都起始於一個基礎鏡像層,當進行修改或培加新的內容時,就會在當前鏡像層之上,創建新的鏡像層。
舉一個簡單的例子,假如基於 Ubuntu Linux16.04創建一個新的鏡像,這就是新鏡像的第一層;如果在該鏡像中添加 Python包,就會在基礎鏡像層之上創建第二個鏡像層;如果繼續添加一個安全補丁,就會創健第三個鏡像層該像當前已經包含3個鏡像層,如下圖所示(這只是一個用於演示的很簡單的例子)。

在添加額外的鏡像層的同時,鏡像始終保持是當前所有鏡像的組合,理解這一點。

上圖中的鏡像層跟之前圖中的略有區別,主要目的是便於展示文件。
下圖中展示了一個稍微復雜的三層鏡像,在外部看來整個鏡像只有6個文件,這是因為最上層中的文件7是文件5的一個更新版。

這種情況下,上層鏡像層中的文件覆蓋了底層鏡像層中的文件。這樣就使得文件的更新版本作為一個新鏡像層添加到鏡像當中。
Docker通過存儲引擎(新版本采用快照機制)的方式來實現鏡像層堆棧,並保證多鏡像層對外展示為統一的文件系統。
Linux上可用的存儲引撃有AUFS、 Overlay2、 Device Mapper、Btrfs以及ZFS。顧名思義,每種存儲引擎都基於 Linux中對應的文件系統或者塊設備技術,井且每種存儲引擎都有其獨有的性能特點。
Docker在 Windows上僅支持 windowsfilter 一種存儲引擎,該引擎基於NTFS文件系統之上實現了分層和CoW 。
下圖展示了與系統顯示相同的三層鏡像。所有鏡像層堆並合井,對外提供統一的視圖。
特點
Docker 鏡像都是只讀的,當容器啟動時,一個新的可寫層加載到鏡像的頂部!
這一層就是我們通常說的容器層,容器之下的都叫鏡像層!

容器數據卷
什么是容器數據卷?
將應用和環境打包成一個鏡像!數據?如果數據都在容器中,那么我們容器刪除,數據就會丟失!需求:數據可以持久化。MySQL,容器刪除了,刪庫跑路!需求:MySQL數據可以存儲在本地!容器之間可以有一個數據共享的技術!Docker容器中產生的數據,同步到本地!這就是卷技術!目錄的掛載,將我們容器內的目錄,掛載到Linux上面!
總結一句話:容器的持久化和同步操作!容器間也是可以數據共享的!
使用數據卷
方式一 :直接使用命令掛載 -v
-v, --volume list Bind mount a volume
具名和匿名掛載
# 三種掛載: 匿名掛載、具名掛載、指定路徑掛載
-v 容器內路徑 #匿名掛載
-v 卷名:容器內路徑 #具名掛載
-v /宿主機路徑:容器內路徑 #指定路徑掛載 docker volume ls 是查看不到的
# 通過 -v 容器內路徑: ro rw 改變讀寫權限
ro #readonly 只讀
rw #readwrite 可讀可寫
# ro 只要看到ro就說明這個路徑只能通過宿主機來操作,容器內部是無法操作!
數據卷容器
多個MySQL同步數據,命名的容器掛載數據卷。

# 測試 啟動3個容器,通過剛才自己寫的鏡像啟動
# 創建docker01:因為我本機是最新版,故這里用latest,狂神老師用的是1.0如下圖
$ docker run -it --name docker01 caoshipeng/centos:latest
# 查看容器docekr01內容
$ ls
bin home lost+found opt run sys var
dev lib media proc sbin tmp volume01
etc lib64 mnt root srv usr volume02
# 不關閉該容器退出
CTRL + Q + P
# 創建docker02: 並且讓docker02 繼承 docker01
$ docker run -it --name docker02 --volumes-from docker01 caoshipeng/centos:latest
# 查看容器docker02內容
$ ls
bin home lost+found opt run sys var
dev lib media proc sbin tmp volume01
etc lib64 mnt root srv usr volume02
# 再新建一個docker03同樣繼承docker01
$ docker run -it --name docker03 --volumes-from docker01 caoshipeng/centos:latest
$ cd volume01 #進入volume01 查看是否也同步docker01的數據
$ ls
docker01.txt
# 測試:可以刪除docker01,查看一下docker02和docker03是否可以訪問這個文件
# 測試發現:數據依舊保留在docker02和docker03中沒有被刪除
多個mysql實現數據共享
$ docker run -d -p 3306: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
$ docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
# 這個時候,可以實現兩個容器數據同步!
結論
容器之間的配置信息的傳遞,數據卷容器的生命周期一直持續到沒有容器使用為止。
但是一旦你持久化到了本地,這個時候,本地的數據是不會刪除的!
Dockerfile
Dockerfile 就是用來構建Docker鏡像的構建文件!
通過這個腳本可以生成鏡像,鏡像是一層一層的,腳本是一個個的命令,每個命令都是一層!
Dockerfile是用來構建Docker鏡像的文件,命令參數腳本。
構建步驟:
1、 編寫一個Dockerfile文件
2、 docker build 構建稱為一個鏡像
3、 docker run運行鏡像
4、 docker push發布鏡像(DockerHub 、阿里雲倉庫)
# 創建一個dockerfile文件,名字可以隨便 建議Dockerfile
# 文件中的內容: 指令(大寫) + 參數
$ vim dockerfile1
FROM centos # 當前這個鏡像是以centos為基礎的
VOLUME ["volume01","volume02"] # 掛載卷的卷目錄列表(多個目錄)
CMD echo "-----end-----" # 輸出一下用於測試
CMD /bin/bash # 默認走bash控制台
# 這里的每個命令,就是鏡像的一層!
# 構建出這個鏡像
-f dockerfile1 # f代表file,指這個當前文件的地址(這里是當前目錄下的dockerfile1)
-t caoshipeng/centos # t就代表target,指目標目錄(注意caoshipeng鏡像名前不能加斜杠‘/’)
. # 表示生成在當前目錄下
$ docker build -f dockerfile1 -t caoshipeng/centos .
docker run -it f4a6b0d4d948 /bin/bash # 運行自己寫的鏡像
#查看一下卷掛載
# docker inspect 容器id
$ docker inspect ca3b45913df5
DockerFile構建過程
基礎知識:
1、每個保留關鍵字(指令)都是必須是大寫字母
2、執行從上到下順序
3、表示注釋
4、每一個指令都會創建提交一個新的鏡像曾,並提交!

Dockerfile是面向開發的,我們以后要發布項目,做鏡像,就需要編寫Dockerfile文件,這個文件十分簡單!
Docker鏡像逐漸成企業交付的標准,必須要掌握!
DockerFile:構建文件,定義了一切的步驟,源代碼
DockerImages:通過DockerFile構建生成的鏡像,最終發布和運行產品。
Docker容器:容器就是鏡像運行起來提供服務。
DockerFile的指令
FROM # from:基礎鏡像,一切從這里開始構建
MAINTAINER # maintainer:鏡像是誰寫的, 姓名+郵箱
RUN # run:鏡像構建的時候需要運行的命令
ADD # add:步驟,tomcat鏡像,這個tomcat壓縮包!添加內容 添加同目錄
WORKDIR # workdir:鏡像的工作目錄
VOLUME # volume:掛載的目錄
EXPOSE # expose:保留端口配置
CMD # cmd:指定這個容器啟動的時候要運行的命令,只有最后一個會生效,可被替代
ENTRYPOINT # entrypoint:指定這個容器啟動的時候要運行的命令,可以追加命令
ONBUILD # onbuild:當構建一個被繼承DockerFile這個時候就會運行onbuild的指令,觸發指令
COPY # copy:類似ADD,將我們文件拷貝到鏡像中
ENV # env:構建的時候設置環境變量!
Docker網絡
理解Docker 0
原理:
我們每啟動一個Docker容器,docker就會給docker容器分配一 個ip,我們只要安裝了Docker,就會有一一個網卡docker0
橋接模式,使用的技術是evth-pair(就是一對虛擬的設備接口,都是成對出現,一個連着協議,一個彼此連接)技術。
就是說Docker使用的是Linux里面的橋接技術。

自定義網絡,不適用docker0,docker0問題:不支持容器名連接訪問。
自定義網絡
docker network
connect -- Connect a container to a network
create -- Creates a new network with a name specified by the
disconnect -- Disconnects a container from a network
inspect -- Displays detailed information on a network
ls -- Lists all the networks created by the user
prune -- Remove all unused networks
rm -- Deletes one or more networks
網絡模式
bridge :橋接 docker(默認,自己創建也是用bridge模式)
none :不配置網絡,一般不用
host :和所主機共享網絡
container :容器網絡連通(用得少!局限很大)
# 我們直接啟動的命令 --net bridge,而這個就是我們得docker0
# bridge就是docker0
$ docker run -d -P --name tomcat01 tomcat
等價於 => docker run -d -P --name tomcat01 --net bridge tomcat
# docker0,特點:默認,域名不能訪問。 --link可以打通連接,但是很麻煩!
# 我們可以 自定義一個網絡
$ docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
我們自定義的網絡Docker當我們維護好了對應的關系,推薦我們平時這樣使用網絡, 不同的集群使用不同的網絡,保證集群是安全和健康的。
網絡連通
假設要跨網絡操作別人,就需要使用docker network connect 連通。
實戰
部署Redis集群

SpringBoot微服務打包Docker鏡像
-
構建SpringBoot項目
-
打包運行
mvn package
-
編寫dockerfile
FROM java:8 COPY *.jar /app.jar CMD ["--server.port=8080"] EXPOSE 8080 ENTRYPOINT ["java","-jar","app.jar"]
-
構建鏡像
# 1.復制jar和DockerFIle到服務器 # 2.構建鏡像 $ docker build -t xxxxx:xx .
以后我們使用了Docker之后,給別人交付就是一個鏡像即可。