Docker


1. Docker安裝

1.1 Docker的基本組成

鏡像(image):

docker鏡像就好比是一個模板,可以通過這個模板來創建容器服務,tomcat鏡像------>run------->tomcat01容器(提供服務器),通過這個鏡像可以創建多個容器(最終服務運行或者項目運行就是在容器中的)

容器(container):

Docker利用容器技術,獨立運行一個或者一組應用,通過鏡像來創建的

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

目前可以把容器理解為一個簡易的Linux系統

倉庫(repository):

倉庫就是存放鏡像的地方

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

Docker Hub

阿里雲等等都有容器服務器(默認在國外,配置鏡像加速)

1.2 安裝Dokcer

環境准備

  1. 需要linux基礎
  2. Centos7
  3. 使用軟件進行遠程連接

環境查看

# 系統內核是3.10以上的
unmae -r
# 系統版本
cat /etc/os-release

安裝

幫助文檔

# 1.卸載舊的版本
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
                  
# 2.需要的安裝包
yum install -y yum-utils

# 3.設置鏡像的倉庫
yum-config-manager \
    --add-repo \
    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

# 4. 安裝docker相關的   docker-ce 社區版 ee企業版
yum install docker-ce docker-ce-cli containerd.io

# 5.啟動docker
systemctl start docker

# 6.使用docker version測試是否安裝成功
docker version

# 7.hello-word
docker run hello-word

# 8.查看下載的這個hello-word鏡像
docker images

1.3 卸載docker

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

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

# /var/lib/docker docker的默認工作路徑

1.4 阿里雲鏡像加速

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

  2. 找到鏡像加速的地址

  3. 配置應用

    mkdir -p /etc/docker
    # 編輯daemon.json
    tee /etc/docker/daemon.json <<-'EOF'
    # 設置加速器地址
    {
      "registry-mirrors": ["https://xxxxxxxx.mirror.aliyuncs.com"]
    }
    EOF
    # 最后重新加載和重啟docker:
    systemctl daemon-reload
    
    systemctl restart docker
    
    mkdir -p /etc/docker
    tee /etc/docker/daemon.json <<-'EOF'
    {
      "registry-mirrors": ["https://me0kxh75.mirror.aliyuncs.com"]
    }
    EOF
    systemctl daemon-reload
    systemctl restart docker
    

1.5 run流程

1.6 底層原理

docker是怎么工作的?

Docker 是一個client-server 結構的系統,Docker的守護進程運行在主機上,通告Socker從客戶端訪問

Dokcer server 接收到Docker-client 的指令,就會執行這個命令

Docker為什么比虛擬機快

  • Docker有着比虛擬機更少的抽象層
  • Docker 利用的是宿主機的內核,VM需要Guest OS
  • 所以,新建一個容器的時候,Docker不需要虛擬機一樣重新加載一個操作系統的內核,避免引導。虛擬機是加載Guest OS,分鍾級別的,而docker是利用宿主機的操作系統,省略了這個復雜的過程,秒級

2. Docker常用命令

2.1 幫助命令

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

2.2 鏡像命令

2.2.1 docker images查看所有本地的主機上的鏡像

docker images

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

# 可選項
-a  # 列出所有的鏡像
-q  # 只顯示鏡像的ID

2.2.2 docker search 搜索鏡像

docker search mysql

# 可選項
--filter=STARS=3000   #搜索出來的鏡像是STARS大於3000的

2.2.3 docker pull 下載鏡像

# 下載鏡像
docker pull 鏡像名[:tag]

如果不寫tag,默認就是latest
分層下載,docker image的核心,聯合文件系統
Digest #簽名
docker.io/library/mysql:latest  #真實地址

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

# 指定版本下載
docker pull mysql:5.7

2.2.4 docker rmi 刪除鏡像

docket rmi -f 鏡像id  #刪除指定鏡像
docket rmi -f 鏡像id 鏡像id  #刪除多個鏡像
docket rmi -f $(docker images -aq)  #遞歸刪除所有鏡像

2.3 容器命令

說明:我們有了鏡像才可以創建容器,Linux,下載一個centos 鏡像來測試學習

docker pull centos

2.3.1 新建容器並啟動 run

docker run [可選參數] image

# 參數說明
--name="Name"   # 容器名字  tomcat01 tomcat02,用來區分容器
-d				# 后台方式運行
-it 				# 使用交互方式運行,進入容器查看內容
-p				# 指定容器的端口 -p 8080:8080
	-p ip:主機端口:容器端口
	-p 主機端口:容器端口(常用)
	-p 容器端口
	容器端口
-p				# 隨機指定端口

# 測試
docker run -it centos /bin/bash  # 啟動並進入容器
	exit # 從容器中退回到主機

2.3.2 docker ps 列出所有運行的容器

docker ps  # 列出當前正在運行的容器

-a  # 列出當前正在運行的容器+歷史運行過的容器
-n=?  # 顯示最近創建的容器,例如-n=1,顯示最近創建的一個容器
-q  # 只顯示容器的編號

2.3.3 退出容器

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

2.3.4 刪除容器 rm

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

2.3.5 啟動和停止容器的操作

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

2.4 常用其他命令

2.4.1 后台啟動容器

# 命令 docker run -d 鏡像名
docker run -d centos

# 問題 docker ps 發現centos停止了

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

2.4.2 查看日志

docker logs 
# 顯示日志
-tf   #顯示全部日志
--tail number #顯示指定數量的日志

docker logs -f -t --tail 容器id   # 沒有日志

#自己編寫一段shell腳本
docker run -d centos /bin/bash -c "while true;do echo zjc;sleep 1;done"

docker logs -tf --tail 10 容器id   

2.4.3 查看容器中進程信息 ps

# 命令 docker top容器id

2.4.4 查看鏡像的元數據 inspect

docker inspect 容器id

2.4.5 進入當前正在運行的容器 exec attach

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

#命令
# 方式一
docker exec -it 容器id /bin/bash

# 方式二xi
docker attach 容器id

#區別
docker exec #進入容器之后開啟一個新的終端,可以在里面操作(常用)
docker attach # 進入容器正在執行的終端,不會啟動新的進程

2.4.6 從容器內拷貝文件到主機上

docker cp 容器id:容器內路徑 目的地主機路徑
#拷貝是一個手動過程,可以使用-v卷的技術,可以實現

2.5 常用命令小結

attach					# 當前shell下attach連接指定運行鏡像
build					# 通過dockerfile定制鏡像
commit					# 提交當前容器為新的鏡像
cp					# 從容器中拷貝指定文件或者目錄到宿主機中
create					# 創建一個新的容器,同run 但不啟動容器
diff					# 查看docker 容器變化
events					# 從docker 服務獲取容器實時事件
exec					# 在已存在的容器上運行命令
export					# 導出容器的內容作為一個 tar 歸檔文件[對應import]
history					# 展示一個鏡像形成歷史
images					# 列出系統當前鏡像
import        			        # 從tar包中的內容創建一個新的文件系統映像[對應export]
info					# 顯示系統相關信息
inspect					# 查看容器詳細信息
kill					# kill 指定容器
load					# 從一個tar 包中加載一個鏡像[對應save]
login 					# 注冊或者登陸一個docker源服務器
logout					# 從當前docker registry退出
logs					# 輸出當前容器日志信息
port					# 查看映射端口對應的容器內部源端口
pause     				# 暫停容器
ps					# 列出容器列表
pull					# 從docker鏡像源服務器拉取指定鏡像或者庫鏡像
push					# 推送指定鏡像或者庫鏡像至docker源服務器
restart					# 重啟運行的容器
rm					# 移除一個或者多個容器
rmi					# 移除一個或多個鏡像[無容器使用該鏡像才可刪除,否則需要刪除相關容器才可繼續或 -f 強制刪除]
run 					# 創建一個新的容器並運行一個命令
save					# 保存一個鏡像為一個tar包[對應load]
search					# 在docker hub 中搜索鏡像
start 					# 啟動容器
stop					# 停止容器
tag					# 給源中鏡像打標簽
top					# 查看容器中運行的進程信息
unpause					# 取消暫停容器
version					# 查看docker版本號
wait					# 截取容器停止時的退出狀態值

3. 作業練習

3.1 部署Nginx

# 1.搜索鏡像 search,可以去docker 搜索,可以看到幫助文檔
# 2.下載鏡像 pull
# 3.運行測試
docker images 

# -d 后台運行
# --name 給容器命名
# -p 宿主機端口,容器內部端口
docker run -d --name nginx01 -p 3344:80 nginx
docker ps
curl localhost:3344

# 進入容器
docker exec -it nginx01 /bin/bash

docker stop 容器id


# 思考問題:我們每次改動nginx配置文件,都需要進入容器內部,十分麻煩,我們可以在容器外部提供一個映射路徑,到達在容器外部修改文件,容器內部就可以自動修改   -v 數據卷技術

端口暴露的概念

3.2 docker來裝一個tomcat

# 官方的使用
docker run -it --rm tomcat:9.0   # 用完就刪除

# 我們之前的啟動都是后台,停止容器之后,容器還是可以查看到,docker run -it --rm tomcat:9.0

# 下載再啟動
docker pull tomcat

# 啟動運行
docker run -d -p 3355:8080 --name tomcat101 tomcat

# 測試訪問沒有問題

# 進入容器
docker exec -it tomcat101 /bin/bash

# 發現問題:1. linux命令少了  2. 沒有webapps
# 阿里雲鏡像的原因,默認是最小的鏡像,所有不必要的都刪除掉,保證最小可運行的環境
  
思考:在容器外部提供給一個映射路徑,webapps,我們在外部防止項目,就自動同步到內部就好了

3.3 部署es+kibana

# es 暴漏的端口很多
# es 十分的耗內存
# es 的數據一般需要放置到安全目錄
# --net somenetwork? 網絡配置

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

# 啟動了linux 就卡住了,docker stats 查看CPU的狀態
# es 十分消耗內存

# 修改配置文件 -e環境配置修改
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="Xms64m -Xmx512m" elasticsearch:7.6.2

curl localhost:9200

使用kibana連接es,思考網絡如何才能連接過去

4.Portainer可視化面板

  • 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

訪問測試:http://ip:8080

5. Docker鏡像講解

5.1 鏡像是什么

鏡像是一種輕量級、可執行的獨立軟件保,用來打包軟件運行環境和基於運行環境開發的軟件,他包含運行某個軟

件所需的所有內容,包括代碼、運行時庫、環境變量和配置文件

所有的應用,直接打包docker鏡像,就可以直接跑起來

5.1.1如何得到鏡像:

  • 遠程倉庫下載
  • 其他人拷貝給你
  • 自己制作一個鏡像dockerfile

5.2 docker鏡像加載原理

5.2.1 UnionFS(聯合文件系統)

UnionFs(聯合文件系統):Union文件系統(UnionFs)是一種分層、輕量級並且高性能的文件系統,他支持對

文件系統的修改作為一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬文件系統下( unite

several directories into a single virtual filesystem)。Union文件系統是 Docker鏡像的基礎。鏡像可以通過分層

來進行繼承,基於基礎鏡像(沒有父鏡像),可以制作各種具體的應用鏡像

特性:一次同時加載多個文件系統,但從外面看起來,只能看到一個文件系統,聯合加載會把各層文件系統疊加起

來,這樣最終的文件系統會包含所有底層的文件和目錄

5.2.2 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等等。

對於個精簡的OS,rootfs可以很小,只需要包合最基本的命令,工具和程序庫就可以了,因為底層直接用Host的kernel,自己只需要提供rootfs就可以了

由此可見對於不同的Linux發行版, boots基本是一致的, rootfs會有差別,因此不同的發行版可以公用bootfs.

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

5.2.3 分層理解

為什么要采用分層結構?

最大的好處,我覺得莫過於資源共享了!比如有多個鏡像都從相同的Base鏡像構建而來,那么宿主機只需在磁盤上保留一份base鏡像,同時內存中也只需要加載一份base鏡像,這樣就可以為所有的容器服務了,而且鏡像的每一層都可以被共享。

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

查看鏡像分層的方式

docker image inspect

特點

5.2.4 commit鏡像

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

# 命令
docker commit -m="提交的描述信息" -a="作者" 容器id 目標鏡像名:[TAG]

實戰測試

# 啟動一個默認的tomcat

# 發現這個默認的tomcat是沒有webapps應用,鏡像的原因,官方的鏡像默認 webapps下面是沒有文件的

# 手動拷貝進去了基本的文件

# 將修改后的容器通過commit提交為一個新的鏡像,我們以后就可以使用修改過的鏡像,這就是自己修改過的一個鏡像

如果想要保存當前容器的狀態,我們可以通過commit來提交,獲得一個鏡像,類似於虛擬機的快照

6. 容器數據卷

6.1 什么是容器數據卷

docker的理念回顧

將應用和環境打包成一個鏡像

如果數據都在容器中,那么刪除容器,數據就會丟失! 需求:數據可以持久化

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

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

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

6.1.1 總結:

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

6.1.2 使用數據卷

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

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

# 測試
docker run -it -v /home/ceshi:/home centos /bin/bash 

# 啟動起來之后,我們可以通過 docker inspect 容器id 來查看元數據

# 再次測試
1. 停止容器
2. 在宿主機上修改文件
3. 再次啟動容器
4. 容器內的數據依舊是同步的

好處:

我們以后修改只需要在本地修改即可,容器內自動同步!

6.2 實戰:安裝MySQL

6.2.1 思考:MySQL 數據持久化問題

# 獲取鏡像
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 容器名字

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

# 啟動成功之后,我們在本地使用sql yog測試連接
# sqlyog 連接到服務器的3310 --- 3310和容器內的3306映射,這個時候就可以連接上了

# 在本地測試創建一個數據庫,查看一下我們映射的路徑是否OK

6.2.2 假設我們將容器刪除

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

6.3 具名和匿名掛載

# 匿名掛載
-v 容器內路徑
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看所有的volume的情況
➜  ~ docker volume ls    
DRIVER              VOLUME NAME
local               33ae588fae6d34f511a769948f0d3d123c9d45c442ac7728cb85599c2657e50d        
# 這里發現,這種就是匿名掛載,我們在 -v只寫了容器內的路徑,沒有寫容器外的路徑!

# 具名掛載
➜  ~ docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
➜  ~ docker volume ls                  
DRIVER              VOLUME NAME
local               juming-nginx

# 通過 -v 卷名:容器內路徑

# 查看一下這個卷
docker volume inspect juming-nginx

# 所有的docker容器內的卷,沒有指定目錄的情況下都是在/var/lib/docker/volumes/xxxx/_data,如果指定了目錄,docker volume ls 是查看不到的

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

# 三種掛載: 匿名掛載、具名掛載、指定路徑掛載
-v 容器內路徑			#匿名掛載
-v 卷名:容器內路徑		#具名掛載
-v /宿主機路徑:容器內路徑 #指定路徑掛載 docker volume ls 是查看不到的

6.3.1拓展

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

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

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

6.4初始Dockerfile

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

通過這個腳本可以生成鏡像,鏡像是一層一層的,腳本一個個的命令,每個命令都是一層

# 創建一個dockerfile文件,名字可以隨便 建議Dockerfile
# 文件中的內容 指令(大寫) 參數
FROM centos

VOLUME ["volume01","volume02"]

CMD echo "----end----"
CMD /bin/bash
#這里的每個命令,就是鏡像的一層!

docker build -f /dockerfile -t kuangshen/centos:v1.0 .
# 啟動容器

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

查看一下掛載的路徑

測試一下剛才的文件是否同步

這種方式之后使用的很多,因為 通常我們會構建自己的鏡像

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

6.5 數據卷容器

多個mysql同步數據

# 啟動三個容器,通過我們自己寫的容器
docker run -it --name docker01 kuangshen/centos:1.0

# 此時刪除容器docker01,docker02和docker03依舊可以訪問這個文件
拷貝的概念

多個mysql實現數據共享

docker run -d -p 3306:3306 -v /etc/mysql/conf.d  -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01  mysql:5.7
# 這個時候,可以實現兩個容器數據同步!

結論

  • 容器之間配置信息的傳遞,數據卷容器的生命周期一直持續到沒有容器使用為止

  • 但是一旦持久化到了本地,這個時候本地的數據是不會刪除的

7. DockerFile

dockerfile是用來構建docker鏡像的文件,命令參數腳本

7.1 構建步驟

  1. 編寫一個dockerfile文件
  2. docker build構建成為一個鏡像
  3. docker run 運行鏡像
  4. docker push 發布鏡像(docker hub,阿里雲鏡像倉庫)

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

7.2 Dockerfile構建過程

7.2.1 基礎知識:

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

Dockerfile是面向開發的,以后發布項目,做鏡像,就需要編寫dockerfile文件

Docker鏡像逐漸成為企業交付的標准

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

Dockerimages:通告Dockerfile構建生成的鏡像,最終發布運行的產品

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

7.3 Dockerfile指令

FROM              # 基礎鏡像,一切從這開始構建
MAINTAINER 		  # 鏡像是誰寫的,姓名+郵箱
RUN				  # 鏡像構建的時候需要運行的命令
ADD				  # 添加內容
WORKDIR			  # 鏡像的工作命令
VOLUME     		  # 掛載的目錄
EXPOSE			  # 指定暴露端口		  
CMD				  # 指定容器啟動的時候運行的命令,只有最后一個會生效,可被替代
ENTRYPOINT        # 指定這個容器啟動的時候要運行的命令可以追加命令
ONBUILD			  # 當構建一個被繼承的 dockerfile ,這個時候就會運行ONBUILD的指令,觸發指令
COPY              # 類似ADD,將我們的文件拷貝到鏡像中
ENV				  # 構建的時候設置環境變量

7.4 實戰測試

Docker Hub中99%鏡像都是從這個基礎鏡像過來的 FROM scratch,然后配置需要的軟件和配置來進行構建

7.4.1 創建一個自己的centos

# 1.編寫Dcokerfile文件
vim mydockerfile-centos

FROM centos
MAINTAINER z<419@qq.com>

ENV MYPATH /usr/loacl
WORKDIR $MYPATH

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

EXPOSE 80

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

# 2.通過這個文件構建鏡像
# 命令:docker build -f dockerfile文件路徑 -t 鏡像名:[tag] .
docker build -f mydockerfile-centos -t mycentos:0.1 .

# 3.測試運行

我們可以通過 docker history+鏡像id 列出本地鏡像的變更歷史

我們平時拿到一個鏡像,可以研究一下他是怎么做到的

7.4.2 CMD和ENTRYPOINT的區別

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

測試CMD

# 編寫dockerfile文件
vi dockerfile-cmd-test
FROM centos
CMD ["ls","-a"]

# 構建鏡像
docker build -f dockerfile-cmd-test -t cmdtest .

# RUN運行,發現我們的ls -a命令生效
docker run dd8e4401d72f

# 想追加一個命令 -l,成為ls -al
docker run dd8e4401d72f -l

docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\":
 executable file not found in $PATH": unknown.
ERRO[0000] error waiting for container: context canceled 
# cmd的情況下 -l 替換了CMD["ls","-l"]。 -l  不是命令所有報錯

測試ENTRYPOINT

# 編寫dockerfile文件
$ vim dockerfile-cmd-entrypoint
FROM centos
ENTRYPOINT ["ls","-a"]

$ docker build -f dockerfile-cmd-entrypoint -t entrypoint-test .

$ docker run 3c4c9621ed91   
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found ...

# 我們的命令,是直接拼接在我們得ENTRYPOINT命令后面的
$ docker run entrypoint-test:0.1 -l
total 56
drwxr-xr-x   1 root root 4096 May 16 06:32 .
drwxr-xr-x   1 root root 4096 May 16 06:32 ..
-rwxr-xr-x   1 root root    0 May 16 06:32 .dockerenv
lrwxrwxrwx   1 root root    7 May 11  2019 bin -> usr/bin
drwxr-xr-x   5 root root  340 May 16 06:32 dev
drwxr-xr-x   1 root root 4096 May 16 06:32 etc
drwxr-xr-x   2 root root 4096 May 11  2019 home
lrwxrwxrwx   1 root root    7 May 11  2019 lib -> usr/lib
lrwxrwxrwx   1 root root    9 May 11  2019 lib64 -> usr/lib64 ....

7.5 實戰測試:Tomcat鏡像

1. 准備鏡像文件 tomcat 壓縮包,jdk的壓縮包
2. 編寫dockerfile文件,官方命名Dockerfile,build會自動尋找這個文件,不需要再-f指定

FROM centos 
MAINTAINER chao      # 名字

COPY readme.txt /usr/local/readme.txt #復制文件

ADD jdk-8u231-linux-x64.tar.gz /usr/local/ #復制解壓
ADD apache-tomcat-9.0.35.tar.gz /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/bin/dt.jar:$JAVA_HOME/lib/tools.jar #設置環境變量 分隔符是:
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.35 #設置環境變量
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.35 #設置環境變量
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080 #設置暴露的端口
CMD /usr/local/apache-tomcat-9.0.35/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.35/bin/logs/catalina.out # 設置默認命令

3. 構建鏡像
docker build -t diytomcat .

4. 運行
$ docker run -d -p 9090:8080 --name kuangshentomcat -v /home/kuangshen/build/tomcat/test:/usr/local/apache-tomcat-9.0.35/webapps/test -v /home/kuangshen/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.35/logs diytomcat

5、訪問測試

6、發布項目(由於做了卷掛載,我們直接在本地編寫項目就可以發布了!)
  1. 發布項目
vi web.xml 

  <?xml version="1.0" encoding="UTF-8"?>
  <web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                               http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
           version="2.5">

  </web-app>
vi index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JC</title>
</head>
<body>
Hello World!<br/>
<%
sysem.out.println("---my test web logs---")
%>
</body>
</html>

7.6 發布鏡像

提交的時候也是按照鏡像的層級來進行提交的

7.6.1 DcokerHub

  1. https://hub.docker.com 注冊自己的賬號
  2. 確定這個賬號可以登錄
  3. 在我們服務器上提交自己的鏡像
  4. 登錄完畢之后就可以提交鏡像了,docker push
$ 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

# 登錄
dokcer login -u 用戶名

# 上傳鏡像
docker push 鏡像名

# push鏡像的問題
 會發現push不上去,因為如果沒有前綴的話默認是push到 官方的library
# 解決方法
1. 第一種 build的時候添加你的dockerhub用戶名,然后在push就可以放到自己的倉庫了
$ docker build -t chengcoder/mytomcat:0.1 .

2. 第二種 使用docker tag 然后再次push
$ docker tag 鏡像id chengcoder/mytomcat:1.0 #然后再次push

7.6.2 阿里雲

  1. 登錄阿里雲
  2. 找到容器鏡像服務
  3. 創建命名空間

  1. 創建容器鏡像

  1. 瀏覽阿里雲

阿里雲容器鏡像的就參考官方地址

7.7 docker流程小結

8. Docker網絡

8.1 理解Docker0

三個網絡

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

# 測試  運行一個tomcat
docker run -d -P --name tomcat01 tomcat

# 查看容器的內部的網絡地址   ip addr                               

       
docker exec -it 容器id ip addr

# 查看容器內部網絡地址 發現容器啟動的時候會得到一個 eth0@if551 ip地址,docker分配!
550: eth0@if551: <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通容器內部! 可以 容器內部可以ping通外界嗎? 可以!
$ 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.069 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.074 ms

8.1.1 原理

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

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

# 我們發現這個容器帶來的網卡,都是一對一對出現的
# evth-pair 就是一對的虛擬設備接口,都是成對出現的,一段連着協議,一段彼此相連
# 正因為有這個特性,evth-pair 充當一個橋梁,連接各種虛擬網絡設備的
# Openstack,Docker容器之間的連接,OVS的連接,都是使用evth-pair技術
  1. 我們測試 tomcat01 和 tomcat02 可以ping通
docker exec -it tomcat02 ping 172.18.0.2

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

結論: tomcat01 和 tomcat02 是共用的一個 docker0

所有的容器不指定網絡的情況下,都是通過docker0通信的,docker會給我們的容器分配一個默認的可用IP

8.1.2 小結

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

  • Dcoker中的所有的網絡接口都是虛擬的,虛擬的轉發效率高

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

場景:編寫了一個微服務,項目不重啟,數據庫 IP 換掉了,如何用名字來進行訪問容器

$ docker exec -it tomcat02 ping tomca01   # ping不通
ping: tomca01: Name or service not known
# 如何解決?
通過 --link 解決了網絡連通問題


# 運行一個tomcat03 --link tomcat02 
$ docker run -d -P --name tomcat03 --link tomcat02 tomcat
5f9331566980a9e92bc54681caaac14e9fc993f14ad13d98534026c08c0a9aef

# 用tomcat03 ping tomcat02 可以ping通
$ docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.115 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.080 ms

# 用tomcat02 ping tomcat03 ping不通


探究:inspect

# 查看hosts 配置

  • --link 就是在我們hosts配置中增加了一個 172.18.0.3 tomcat02 312857784cd4

  • 現在已經不建議使用 --link 了

docker0的問題:不支持容器名連接網絡

8.3 自定義網絡

查看所有的docker 網絡

網絡模式:

  1. bridge:橋接(默認)

      	2.	none:不配置網絡
                	3.	host:和宿主機共享網絡
                          	4.	container:容器網絡互通(用的少,局限大)
    

測試:

# 我們直接啟動的命令默認有--net bridge,而這個就是我們的docker0
docker run -d -P --name tomcat01 tomcat
等價於---> docker run -d -P --name tomcat01 --net bridge tomcat

# docker0 特點:默認bridge,域名不能訪問,  --link可以打通連接,但不推薦使用

# 我們可以自定義一個網絡

自定義一個網絡

# --driver  bridge
# --subnet 192.168.0.0/16
# --gateway 192.168.0.1
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet

docker network ls

# 我們的網絡就創建好了
docker network inspect mynet

# 測試
docker run -d -P --name tomcat-net-01 --network mynet tomcat
docker run -d -P --name tomcat-net-02 --network mynet tomcat


# 自定義的網絡可以直接ping 通, 不需要使用 --link

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

好處:

redis:不同的集群使用不同 的網絡,保證集群是安全和健康的

mysql:不同的集群使用不同的網絡,保證集群是安全和健康的

8.4 網絡連通

# 測試打通 tomcat01 - mynet
docker network connect mynet tomcat01

# 連通之后就是將 tomcat01 放到了 mynet 網絡下

# 一個容器兩個ip地址

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

8.5 實戰:部署Redis集群

# 創建網卡
docker network create redis --subnet 172.38.0.0/16
# 通過腳本創建六個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);\
docker run -p 637${port}:6379 -p 1667${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


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM