docker從入門到熟練
一、為什麼要用docker
1.jar+環境一起打包,直接執行映象即可
2.每個容器間相互隔離,每個容器都有一個屬於自己的檔案系統,互不影響
3.通過隔離機制,可以將伺服器記憶體利用到極致
4.容器內的應用直接執行在宿主機的內容,容器是沒有自己的核心的,也沒有虛擬硬體(docker和虛擬機器都是虛擬化技術,docker非常輕巧(最核心的環境+jdk+mysql...),虛擬機器技術缺點:1、資源佔用多 2、冗餘步驟多 3、啟動很慢)
二、docker優點
1、應用更快速的交付和部署:打包映象釋出測試,一鍵執行。
2、更快捷的升級和擴容。
3、更簡單的系統運維:容器化之後,開發、測試環境都是高度一致的
4、更高效的計算機資源利用:docker是核心級別的虛擬化,伺服器的效能可以被壓榨到機制
三、安裝docker
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 http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
4.安裝docker
先更新軟體包索引:yum makecache fast
安裝:yum install docker-ce docker-ce-cli containerd.io
5.啟動docker
systemctl start docker
6.檢視是否安裝成功
docker version
7.測試hell-world
docker run hello-world
8.檢視映象
docker images
9.解除安裝docker
-yum remove docker-ce docker-ce-cli containerd.io
-
rm -rf /var/lib/docker
- rm -rf /var/lib/containerd
10.配置阿里雲映象加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{ "registry-mirrors": ["https://"] } EOF
sudo systemctl daemon-reload
sudosystemctl restart docker
四、docker工作原理
docker是一個client-server結構的系統,docker的守護程序執行在主機上,通過socket從客戶端訪問,dockerserver接收到docker-client的指令,就會去執行
docker為什麼比vm快?
-docker的抽象層比vm更少
-docker利用的是宿主機的核心(秒級),vm需要載入Guest OS(分鐘級別)。
五、docker常用命令
幫助命令
docker version 顯示docker的版本資訊
docker info 顯示docker的系統資訊,包括容器和映象
docker [] --help 幫助命令
映象命令
docker images[] 檢視所有本地主機上的映象
-a 顯示所有的映象
-q 只顯示映象id
-aq 顯示所有映象的id
docker search 搜尋映象
--filter=STARS=3000 搜尋條件為STARTS3000以上的
docker pull 映象名:版本號 指定tag下載,不使用latest(分層下載)
docker rmi -f 映象id
docker rmi -f $(docker images -aq) 刪除所有docker映象
容器命令
docker run [] image
--name="name" 指定容器名字啟動
-d 後臺方式執行
-it 使用互動方式執行,進入容器檢視內容 (互動執行要指定控制檯 /bin/bash)
-p
-p ip:主機埠:容器埠
-p 主機埠:容器埠
-p 容器埠
容器埠
-P 隨機指定埠
docker ps 檢視正在執行的容器
docker ps -a 檢視所有的容器(包含歷史執行過的容器)
docker ps -a -n=1顯示出最近建立的1個容器
docker ps -aq顯示所有容器的id
exit:直接退出容器
ctrl+p+q:容器不停止退出
docker rm 容器id,不能刪除正在執行的容器,要加-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常用的其他命令
docker run -d centos:容器停止了,docker容器使用後臺執行,就必須要有一個前臺程序,docker發現沒有應用,就會自動停止
#nginx容器啟動後發現自己沒有提供服務,就會立刻停止
docker run -d centos /bin/sh -c "while true;do echo mj666;sleep 1;done"指令碼執行
檢視日誌:docker logs -tf --tail (最近條數) 容器id
-t顯示日誌
-f顯示時間戳
檢視容器中的程序資訊:docker top 容器id
檢視容器的元資料:docker inspect 容器id
進入當前正在執行的容器:docker exec -it 容器id/(容器name) /bin/bash (進入容器後開啟一個新的終端,可以在裡面操作)
docker attach 容器id(進入容器正在執行的終端,不會啟動新的程序)
從容器內拷貝檔案到主機上:docker cp 容器id:容器內路徑 目的主機路徑(只要容器還在資料就在,不管是否是啟動狀態)
六、常用軟體安裝
Nginx安裝:1.docker pull nginx
2.docker run -d --name nginx01 -p 9092:80 nginx
3.curl localhost:9092 檢視
4.docker exec -it 容器id/(容器name) /bin/bash 進入容器之後whereis nginx 檢視檔案目錄
Tomcat安裝:1.docker pull nginx:9.0(docker run -it --rm tomcat:9.0(run命令會幫我們自動下載),一般用來測試用完就刪除)
2.docker run -d --name tomcat01 -p 9093:8080 tomcat
3.docker exec -it tomcat01 /bin/bash 進入容器之後發現命令缺少,沒有webapps,原因阿里雲預設是下載最小的映象,所有不必要的都剔除掉了。
4.cp -r(遞迴) webapps.dist/* webapps 遞迴拷貝webapps.dist下的內容到webapps目錄下,發現可以訪問到了
部署es+kibana:
es安裝:
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
啟動之後直接卡死,docker stats 檢視cpu的狀態,原因是es十分耗記憶體
**docker run -d --name elasticsearch007 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64M -Xms512M" elasticsearch:7.6.2
kibana安裝:連線es,後面再操作??????
七、視覺化管理工具:
portainer:docker圖形化管理工具
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
Rancher(CI/CD再使用):???
八、docker映象
映象是一種輕量級、可執行的獨立軟體包,用來打包軟體執行環境和基於執行環境開發的軟體,包含某個軟體所需的所有內容,包括程式碼、執行時庫、環境變數和配置檔案,所有的應用,直接打包docker映象就可以直接執行
映象獲得方式:遠端倉庫下載或者通過dockerfile製作
UnionFS是docker映象的基礎,docker映象實際上由一層一層的檔案系統組成。
docker映象載入原理:
bootfs包含bootloader和kernel,linux剛啟動之後會載入bootfs,bootfs是docker映象的最底層,當boot載入完之後整個核心就在記憶體中了,此時記憶體的使用權就由bootfs轉給核心,此時系統解除安裝掉bootfs
rootfs(基礎映象)就是各種作業系統的發行版,比如Ubuntu,Centos等。
docker的rootfs可以很小,只需要包含基本的命令,工具和程式,因為底層用的是Host的kernel。
分層理解:
tomcat為例,tomcat分層下載是6層,映象是隻讀的,這時啟動容器,一個新的可寫層(容器層)被載入到映象的頂部(commit把映象層和修改過後的容器層打包為一個新的映象層)。
commit映象:
docker commit 提交容器成為一個新的副本
docker commit -m ="提交的描述資訊" -a="作者" 容器id 目標映象名:[版本號]
1.啟動一個預設的tomcat
2.發現這個預設的tomcat沒有webapps應用,這個是官方映象的原因
3.這個時候我們進入容器拷貝webapps.dist下內容到webapps目錄
4.將我們操作過的容器通過commit提交為一個新的映象
九、docker容器資料卷
資料卷技術將容器內的目錄,掛載到Linux上,實現資料的共享,資料相互同步。
作用:容器資料的持久化和同步操作,容器之間也可以共享資料
使用資料卷:
方式一:docker run -it -v /home/ceshi(宿主機目錄):/home(容器目錄) centos /bin/bash (cat檢視檔案資訊)
-停止容器後
-宿主機上修改檔案
-啟動容器
-容器內的資料依舊是同步的
好處:只需要修改本地,容器內會自動同步
安裝mysql:
docker run -d -p 9095:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=panghu --name mysql01 mysql:5.7
刪除容器後,掛載到本地的資料卷沒有丟失,即實現了容器資料持久化功能
**具名掛載和匿名掛載:
匿名掛載:docker run -d -P --name nginx01 -v /etc/nginx nginx
檢視所有的volume的情況:docker volume ls
-v後面不指定宿主機目錄,只指明容器內路徑
具名掛載:docker run -d -P --name nginx02 -v juming-nginx(卷名):/etc/nginx nginx
docker volume ls
檢視容器資訊:docker inspect 容器name ,發現掛載的位置在/var/lib/docker/volumes/xxx(卷名)/_data(存放資料的目錄)
通過具名掛載可以很方便的找到volume,大多數情況都採用具名掛載
-v 容器內路徑 #匿名掛載
-v 卷名:容器內路徑 #具名掛載
-v 宿主機路徑:容器內路徑 #指定路徑掛載
ro:只讀,容器內部無法操作,只能通過宿主機來操作
rw:可讀可寫
一旦設定了容器許可權,容器對我們掛載出來的內容就有限定了
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
(pwd 指令可立刻得知您目前所在的工作目錄的絕對路徑名稱)
十、dockerfile入門
dockerfile就是用來構建docker映象的命令指令碼檔案
通過這個指令碼可以生成映象,映象是一層一層的,指令碼是一個一個的命令,一個命令構建一層
vim 構建並寫好dockerfile檔案後
通過docker build -f dockerfile1 -t /mj999/centos .
執行容器檢視檔案目錄,發現volume01和volume02(匿名掛載),這個卷一定有一個同步的宿主機目錄,在volume01下建立一個檔案container.txt檔案
通過檢視容器資訊docker inspect,發現了匿名掛載的目錄位置跟剛才一樣/var/lib/docker/volumes/xxx/_data
進入目錄發現建立成功,資料掛載同步成功
建立自己的映象時經常使用這種掛載資料卷方式,假設構建映象時沒有掛載卷,要手動掛載 -v 卷名:容器內路徑名
十一、資料卷容器(用於容器之間的資料相互共享)(類似於拷貝檔案)
建立第一個資料卷容器(父容器)
docker run -it --name docker01 mj999/centos
在volume01下建立一個檔案docker01
(建立檔案touch建立目錄mkdir刪除一行命令ctrl+u)
建立第二個容器docker run -it --name docker02 --volumes-from docker01 mj999/centos(02掛載01資料卷容器)
進入volume01目錄後發現docker01建立的內容docker02上面也有
刪除docker01資料卷容器
發現docker02和docker03還是有資料
*多個mysql實現資料共享:
#docker run -d -p 9095:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=panghu --name mysql01 mysql:5.7
#
docker run -d -p 9095:3306 -e MYSQL_ROOT_PASSWORD=panghu --name mysql02 --volumes-from mysql01 mysql:5.7
結論:容器之間配置資訊的傳遞,資料卷容器的生命週期一直持續到沒有容器使用為止。一旦資料持久化到本地,本地的資料是不會被刪除的。
十二、dockerfile
1)dockerfile是用來構建docker映象檔案的命令引數指令碼,一行命令構建一層映象
構建步驟:1.編寫一個docker file 檔案
2.docker build 構建成一個映象
3.docker run 執行映象
4.docker push 釋出映象(DockerHub、阿里雲映象倉庫)
去dockerhub官網上檢視dockerfile的編寫
官方的很多映象都是基礎包,很多功能都沒有,通常要搭建自己的映象
*2)dockerfile構建過程
基礎知識:1、每個保留關鍵字(指令)都必須是大寫字母
2、執行從上到下順序執行
3、#表示註釋
4、每一個指令都會建立提交一個新的映象層
dockerfile指令:
FROM #基礎映象,一切從這裡開始構建
MAINTAINER #映象的作者,姓名+郵箱
RUN #映象構建的時候需要執行的命令
ADD #新增內容,例如製作tomcat映象,新增tomcat壓縮包
WORKDIR #映象的工作目錄
VOLUME #掛載的目錄
EXPOSE #保留埠配置
CMD #指定這個容器啟動的時候要執行的命令,一個cmd指令執行一個命令,只有最後一個cmd指令會生效,可以被替代
ENTRYPOINT #指定這個容器啟動的時候要執行的命令,可以追加命令
ONBUILD #當構建一個被繼承dockerfile,這個時候就會執行ONBUILD的指令,觸發指令
COPY #類似ADD,將我們的檔案拷貝到映象中
ENV #構建的時候設定環境變數
3)建立一個檔案目錄,構建一個dockerfile製作映象:
FROM centos
MAINTAINER mj666<[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--"
CMD /bin/bash
然後通過docker build -f mydockerfile -t mycentos:0.1 .
可以列出docker映象的變更歷史 docker history 映象id(也可以用來檢視官方的映象製作歷史)
4)cmd和entrypoint的區別:cmd追加命令會覆蓋
entrypoint是直接追加
建立二個dockerfile製作映象測試
cmd測試:
FROM centos
CMD ["ls","-a"]
entrypoint測試:
FROM centos
ENTRYPOINT ["ls","-a"]
製作完映象之後分別使用run命令啟動,沒有什麼區別,追加l命令後cmd的會報錯,而entrypoint的正確執行了ll命令
5)實現tomcat映象
1.準備映象檔案,tomcat的壓縮包,jdk的壓縮包
2.編寫Dockerfile檔案,官方命名,不需要再-f指定,build時自動尋找該檔案
FROM centos
MAINTAINER mj999<[email protected]>
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u11-linux-x64.tar.gz /usr/local/
ADDapache-tomcat-9.0.1.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/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.1
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.1
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.1/startup.sh && tail -F /usr/local/apache-tomcat-9.0.1/bin/logs/catalina.out
3.docker build -t 構建映象 .
4.掛載資料卷啟動
docker run -d -p 9096:8080 --name mjtomcat -v /home/mj999/build/tomcat/test:/usr/local/apache-tomcat-9.0.1/webapps/test -v /home/mj999/build/tomcat/logs:/usr/local/apache-tomcat-9.0.1/logs diytomcat
*啟動失敗通過docker logs 容器id檢視原因
5.訪問外網測試121.43.37.22:9096成功或者curl localhost:9096
6.釋出專案,由於做了資料卷掛載,我們直接在本地編寫專案就可以釋出了。
-在/home/mj999/build/tomcat/test目錄下建立一個WEB-INF,去編輯一個web.xml檔案
-在/home/mj999/build/tomcat/test目錄下建立一個jsp頁面
#訪問成功
#再看日誌,列印成功
十三、釋出映象
**釋出映象到dockerhub
1.https://hub.docker.com/註冊賬號
2.登入賬號
3.提交映象docker push 到伺服器上
4.docker tag 映象id 作者/映象名:版本號 (增加一個tag,又多了一個映象,再重新push)
push成功
**push到阿里雲倉庫
1.登入阿里雲開啟映象容器服務
2.建立個人例項
建立名稱空間(最多建立3個)
建立映象倉庫
3.按照官網的操作指南操作
push成功
十四、docker網路
docker0
使用ip addr命令檢視ip地址
lo:本機迴環地址
eth0:阿里雲內網地址
docker0:docker地址
啟動一個tomcat:
docker run -d --name tomcat01 -P tomcat
檢視容器ip
(容器中使用ip addr 報錯:原因是tomcat版本問題
進入容器 aptupdate&& apt install-y iproute2)
docker exec -it tomcat01 ip addr ,得到一個eth0@if131的ip地址,這是docker分配的。
直接在linux上ping容器內部,可以ping通。
**(1)linux可以ping通docker容器內部
原理:每啟動一個docker容器,docker就會給容器分配一個ip,只要安裝了docker就會有一個網絡卡docker0(橋接模式),使用的技術是veth-pair技術
在linux下執行ip addr,發現多了一個131,130
發現容器帶的網絡卡,都是一對一對的。
veth-pair 就是一對的虛擬裝置介面,我們都是成對出現的,一端連著協議,一端彼此相連
因為有這個特性,veth-pair可以充當橋樑,連線各種虛擬網路裝置
OpenStac,docker容器之間的連線,ovs的連線,都是使用的veth-pair技術
(2)測試是否tomcat01和tomcat02之間是否能ping通,發現可以ping通
**容器和容器之間是可以進行通訊的
結論:容器之間能通訊是因為docker0作為共用路由器。(在容器和docker0分別建立一個虛擬網絡卡,通過vethpair進行連線,再通過docker0路由,容器之間就能通訊了)
所有的容器不指定網路的情況下,都是docker0路由,docker0會給容器分配一個預設的可用ip。
docker使用的是linux的橋接,宿主機中是一個docker容器的網橋docker0(docker0和物理網絡卡是直連NAT)
docker中的所有網路介面都是虛擬的,虛擬的轉發效率高。
只要容器刪除,對應網橋一對就刪除掉了。
(3)直接通過容器名ping,不能ping通
(容器缺少ping命令解決辦法:apt-get update
apt install iputils-ping
apt install net-tools )
建立tomcat03用--link和tomcat02繫結:docker run -d -P --name tomcat03 --link tomcat02 tomcat
docker exec -it tomcat03 ping tomcat02
用3ping2發現能ping通
用2ping3發現不能ping通
結論:通過--link解決了網路連通問題,不使用ip,使用名字即可
(4)檢視docker網路
發現了link連線
(5)通過檢視host配置,--link操作就是增加了一個172.17.0.3 tomcat02 4533e117ae50,所以能夠通過名字ping通
--link已經不建議使用了。
*****自定義網路,不使用docker0,因為docker0不支援容器名連線訪問。
檢視docker的所有網路
網路模式:
bridge:橋接(預設,自己建立的網路也基本使用橋接)
none: 不配置網路
host: 和宿主機共享網路
container:容器網路連通(不常用)
測試:#docker run -d -P --name --net bridge tomcat(docker run -d -P --name tomcat 這是預設新增的,bridge就是docker0)
docker0:是預設的網路,域名不能訪問,--link可以打通連線
自定義網路測試:docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
--driver 模式
--subnet 子網 192.168.0.2-192.168.255.254
--gateway 閘道器
檢視剛才建立的網路
建立兩個tomcat指定網路為mynet,再次檢視mynet網路下多了2個容器
直接ping地址:能夠ping通
直接ping名字:能夠ping通
結論:自定義的網路docker已經幫我們維護好了對應關係
使用的好處:不同的叢集使用不同的網路,保證叢集是安全和健康的。
******網路連通(網絡卡之間不能打通,只能容器和網絡卡之間打通)
在docker0網路下建立2個tomcat容器,在mynet網路下建立2個容器,這個時候直接2個網路下的容器直接ping是ping不通的
這個時候就需要docker0網路下的容器連線到mynet網路
connect命令
測試打通tomcat03-mynet網路
連線之後發現容器直接加入進了mynet網路下,這就是一個容器兩個ip地址
1和3之間直接可以ping通,4由於還沒和mynet打通,所以不能ping通
結論:如果要跨網路操作他人,就需要使用docker network connect連通
十五、部署redis叢集-3主3從
1.建立redis網絡卡
#docker network create redisnet --subnet 172.38.0.0/16(沒有指定網路模式和閘道器)
2.通過指令碼建立6個redis配置
for port in $(seq 1 6); \
do \
mkdir -p /redisdata/redis/node-${port}/conf
touch/redisdata/redis/node-${port}/conf/redis.conf
cat <<EOF>/redisdata/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
3.
指令碼批量啟動redis
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port}\
-v /redisdata/redis/node-${port}/data:/data \
-v /redisdata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redisnet --ip 172.38.0.1${port}redis:latest redis-server /etc/redis/redis.conf
一個一個啟動redis
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /redisdata/redis/node-1/data:/data \
-v /redisdata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redisnet --ip 172.38.0.11 redis:latest redis-server /etc/redis/redis.conf
docker run -p 6372:6379 -p 16372:16379 --name redis-1 \
-v /redisdata/redis/node-2/data:/data \
-v /redisdata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net redisnet --ip 172.38.0.13 redis:latest redis-server /etc/redis/redis.conf
6個節點全部啟動完成
進入容器命令列
建立叢集
#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
連線叢集
redis-cli -c
產看叢集資訊、節點資訊
測試redis叢集高可用:
往redis叢集裡面存一個a,值為b
關掉儲存資料的redis節點
通過get命令取資料,發現從他的從機redis-4上拿到了資料,實現了redis叢集的高可用
通過cluster nodes發現3號故障,master變成了4
docker搭建redis叢集完成
十六、Springboot專案打包Docker映象
1.構建springboot專案
2.打包應用-先clean再package
執行能訪問
再命令黑窗執行測試一下,啟動成功,這個時候這個打包就沒有問題了
3.編寫dockerfile
FROM java:8
COPY *.jar /app.jar
CMD["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT["java","-jar","/app.jar"]
4.構建映象
docker build -t mj999 . 構建成功
5.釋出執行
檢視映象
啟動執行
docker run -d -P --name mjspringboot mj999
訪問成功
curl localhost:49168/hello