docker基本用法
- 卸載
sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine
- 安裝
sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 - 設置穩定的倉庫 sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo #安裝docker sudo yum install docker-ce docker-ce-cli containerd.io
- 鏡像加速器
sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://vxdxcg5s.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker
- 查看鏡像
docker images
- 拉取
## 默認會拉取最新的,不過能夠指定tags的方式拉取對應的鏡像 dokcer pull hello-world(鏡像名)
- 運行
docker run --name hellodocker(別名) hello-world
- 查看運行狀態
docker ps -a
- 刪除
docker rmi -f imageId docker rmi -f $(docker images) ## 刪除容器 docker rmi -f $(docker ps -aq)
- tomcat
# -d 後臺運行 # --name 指定一個名稱 # -p 將默認的8080端口映射爲一個新的端口 docker run -d --name mytomcat -p 8888:8080 tomcat # 進入到鏡像中 # 能夠是containerId或者是names docker exec -it 7940b96bcca6 /bin/bash
- mysql
docker run -d --name mysql01 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123 --privileged mysql ### 鏈接不上的問題排查 docker exec -it mysql /bin/bash mysql -uroot -p Enter password: mysql> select host,user,plugin,authentication_string from mysql.user; #host爲 % 表示不限制ip localhost表示本機使用 plugin非mysql_native_password 則須要修改密碼 mysql> use mysql; mysql> alter user 'root'@'%' identified with mysql_native_password by '123'; mysql> flush privileges; mysql> select host,user,plugin,authentication_string from mysql.user;
- image怎麼製做的
- Dockerfile > https://github.com/docker-library 每個image都是根據Dockerfile配置生成的
驗證html
> 將官網上的mogodb的Dockerfile放入到咱們的物理主機上, 並執行。 #mogodb-my 起個別名
docker build -t mogodb-my .
- 根據container生成image
docker commit mycentos vim-centos
經過Dockerfile能夠追蹤image生成的過程便於排查問題,而container的方式看不到生成的細節,因此不推薦使用,能夠適當使用。java
- 查看docker佔用的系統資源
docker top mytomcat docker stats mytomcat #限制系統資源的使用(否者會無限制消耗系統的資源) #--memory 100M 限制內存 #--cpu-shares 10 限制CPU資源佔比,例如兩個container一個配置10,一個配置20那麼他們兩個的CPU佔比應該後者是前者的兩倍 即1:2 docker run -d --name mytomcat02 --memory 100M --cpu-shares 10 -p 8000:8080 tomcat
Spring Boot 項目作成image
FROM openjdk:8 MAINTAINER Bellamy.XIAO LABEL name="demo" version="1.0" author="Bellamy.XIAO" COPY demo-0.0.1-SNAPSHOT.jar demo-image.jar CMD ["java","-jar","demo-image.jar"]
## build docker build -t spring-boot-demo . ## query docker images ## run docker run -d --name demo -p 9000:8080 spring-boot-demo ## log docker logs containerId
推送到遠端倉庫
# 生成tag: docker tag spring-boot-demo 7634xxx/spring-boot:v1.0 # 官方倉庫: https://hub.docker.com 登陸: docker login tag: docker tag ImageId 7634xxx/spring-boot :v1.0 push: docker push 7634xxx/spring-boot:v1.0 # 阿里雲倉庫 登陸: sudo docker login --username=xxxx registry.cn-hangzhou.aliyuncs.com tag: sudo docker tag ImageId registry.cn-hangzhou.aliyuncs.com/docker-namesapce/docker-repository:version push : sudo docker push registry.cn-hangzhou.aliyuncs.com/docker-namesapce/docker-repository:version # 私服[harbor]: https://github.com/goharbor/harbor
系統資源監控平臺[weaveworks/scope]
#下載 sudo curl -L git.io/scope -o /usr/local/bin/scope #受權 sudo chmod a+x /usr/local/bin/scope #啓動(能夠有多個ip) scope launch 192.0.0.1 #中止 scope stop
Docker核心部分->從網絡提及網絡
-
Linux中的網絡node
namespace
之間的連通性
namespace
是 Linux 2.6.x 內核版本以後支持的特性,主要用於資源的隔離。有了 namespace,一個 Linux 系統就能夠抽象出多個網絡子系統,各子系統間都有本身的網絡設備,協議棧等,彼此之間互不影響。python-
namespace
間通訊mysql- 基礎部分
####### 網卡基本操做 ####### # 查看網卡信息 ip link show #或者 ip a # 網卡配置目錄 cd /etc/sysconfig/network-scripts/ #給網卡添加臨時ip ip addr add 192.168.xxx.xxx/24 dev eth0 #刪除ip ip addr delete 192.168.xxx.xxx/24 dev eth0 ------------------------------------------- ####### 將網卡進行隔離 ###### # 建立 network namespace ip netns add ns1 #查看 ip netns list # 查看當前namespace的網卡信息 ip netns exec ns1 ip a # 啓動網卡 ip netns exec ns1 ifup lo ---------------------------------------------
不得不說的veth pair技術(virtual Ethernet Pair)
eth-pair 就是一對的虛擬設備接口,和 tap/tun 設備不一樣的是,它都是成對出現的。一端連着協議棧,一端彼此相連着。正由於有這個特性,它經常充當着一個橋樑,鏈接着各類虛擬網絡設備,典型的例子像「兩個 namespace 之間的鏈接」,「Bridge、OVS 之間的鏈接」,「Docker 容器之間的鏈接」 等等,以此構建出很是複雜的虛擬網絡結構。linux
# 經過如下方式發現隔離的兩個namespace間能夠通訊了 ip link add veth-ns1 type veth peer name veth-ns2 #綁定network namespace ip link set veth-ns1 netns ns1 # 給網卡添加ip ip netns exec ns1 ip addr add 192.xxx.xxx.10/24 dev veth-ns1 # 啓動網卡 ip netns exec ns1 ip link set veth-ns1 up # ns2同理可得,略 # ns1 ping ns2 ip netns exec ns1 ping 192.168.xxx.xxx ----------------------------------------------------
經過如上結論來看docker是否相似
-
啓動2個docker容器(驗證容器與容器之間爲何能夠相互通訊)git
docker run -d tomcat01 -p 8001:8080 tomcat docker run -d tomcat02 -p 8002:8080 tomcat # 經過上述方式查看物理主機信息 #內容以下 8: veth131fbae@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default inet6 aaaa::aaaa:aaaa:aaaa:aaaa/64 scope link valid_lft forever preferred_lft forever 10: veth61cf0b5@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default inet6 aaaa::aaaa:aaaa:aaa:aaa/64 scope link valid_lft forever preferred_lft forever
經過上述信息咱們能夠發現,(veth131fbae@if7和veth61cf0b5@if9),@if7和@f9,經過數字發現7和9,中間像是跳過了一個8github
-
進入到容器一探究竟web
# 分別進入到docker 容器中,獲得以下內容 7: eth0@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default inet 172.xxx.xxx.2/16 brd 172.xxx.255.255 scope global eth0 valid_lft forever preferred_lft forever 9: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.xxx.xxx.3/16 brd 172.xxx.255.255 scope global eth0 valid_lft forever preferred_lft forever
eth0@if8 和eth0@if10,由此咱們發現了一些端倪, 能夠看的出
docker
中的container
和物理主機中確實是成對出現了這樣的網卡信息。veth131fbae@if7
<-->eth0@if8
、veth61cf0b5@if9
<--->eth0@if10
,那麼也意味着docker中的網絡是按照namespace相似的思想作到資源隔離的redis
Docker 中的網絡模式
#經過以下命令查看 docker network ls NETWORK ID NAME DRIVER SCOPE 15ea9d89d616 bridge bridge local 1c62b0fd4212 host host local 375f1ab17a8b none null local
- bridge
- 默認使用的方式 2.host
- 訪問容器不須要進行映射直接能夠訪問
- none
- 只有一個本地網卡信息
#建立,默認爲bridge docker network create net01 #經過以下命令能夠獲得具體信息 docker network inspect net01 信息以下: [ { "Name": "net01", "Id": "b9fee626fdee", "Created": "2019-12-19T10:50:59.641869093Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "x.0.0.0/16", "Gateway": "x.x.x.x" #網關信息 } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { # 容器信息 "c0f8db51792b9b394b": { "Name": "tomcat03", "EndpointID": "9a966183a87", "MacAddress": "", "IPv4Address": "x.x.x.x/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ]
這是否意味着咱們能夠經過上述三種方式自定義網絡
# 從新啓動一個容器,命令以下 docker run -d --name tomcat03 --network net01 -p 8082:8080 tomcat #能夠對比容器使用network參數與未使用的ip變化
神奇的是在tomcat03中此刻卻沒法ping通使用了docker默認的network建立的tomcat01容器。 緣由在於自定義的網絡跟docker0不在同一個網段因此沒法ping通(tomcat03使用的是自定義網絡,而tomcat01使用的則是默認的網絡),那麼tomcat03和tomcat01固然沒法ping通。
# 查看當前docker默認的bridge docker inspect bridge [ { "Name": "bridge", "Id": "15ea9d89d6165304b561b", "Created": "2019-12-19T10:43:46.750789678Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "x.x.0.0/16", "Gateway": "x.x.x.x" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { #能夠看到默認網絡的容器信息 "44371744ca1a": { "Name": "tomcat01", "EndpointID": "7005e8d9f9aab442", "MacAddress": "", "IPv4Address": "x.x.x.x/16", "IPv6Address": "" } }, "Options": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" }, "Labels": {} } ] # 將tomcat01也加入到自定義網絡中 docker network connect net01 tomcat01 #再次查看net01發現tomcat01也在當中了 # 經過以下命令查看tomcat01的網絡信息發現tomcat01中的網絡此時多了一個ip地址 docker inspect tomcat01 #此時tomcat01和tomcat03由於有同網段的ip地址,因此又能夠互通
結論: 爲何容器之間可以相互連通,是由於docker會建立這種橋接模式,而橋接模式其實是使用了veth-pair技術,因此容器之間能夠進行通訊。
container之間是否能夠經過名稱互通
若是真的能夠那麼就不須要擔憂ip地址的變化了,就像微服務同樣,服務與服務之間的調用經過註冊咋註冊中心上的服務名字便可調用。遺憾的是咱們在使用默認的docker網絡是沒法用名字的方式ping通
#增長link的方式進行指定 docker run -d --name tomcat05 --link tomcat01 -p 8085:8080 tomcat # 自定義網絡的方式是能夠互通的
多機通訊overlay網絡
- Swarm中實現
# 建立一個overlay網絡 docker network create -d overlay o-net #建立mysql docker service create --name mysql -v v1:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123 -e MYSQL_DATABASE=db_wordpress --network o-net mysql:5.6 #建立wordpress docker service create --name wordpress -e WORDPRESS_DB_USER=root -e WORDPRESS_DB_PASSWORD=123 -e WORDPRESS_DB_HOST=mysql:3306 -e WORDPRESS_DB_NAME=db_wordpress -p 8080:80 --network o-net wordpress #查看網絡信息 docker network inspect o-net [ { "Name": "o-net", "Id": "45x28fm6", "Scope": "swarm", "Driver": "overlay", "IPAM": { "Driver": "default", "Config": [ { "Subnet": "Gateway": } ] }, "Containers": { "64cf17fd1f0": { "Name": "mysql.1.s1hfbsju", "EndpointID": "MacAddress": "IPv4Address": }, "lb-overlay-net": { "Name": "overlay-net-endpoint", "EndpointID": , "MacAddress":, "IPv4Address": , "IPv6Address": "" } }, "Options": { "com.docker.network.driver.overlay.vxlanid_list": "4097" }, "Labels": {}, "Peers": [ { "Name": "IP": }, { "Name": "IP": } ] } ]
docker持久化
- volume
# 查看,建立容器的時候會自動生成一個默認的volume docker volume ls DRIVER VOLUME NAME local 1deb0814c8723496c03aacecbe0535e47f39e1131286f3c0d1090eb8717617e8 local 3a7e9642878f96afe5b307b39dc184aad6f0ea379e53592b989e2d513a44c6b9 local 6f4e05e55601c866a614dd60b05386763e8081b93465472adbdceef5a1a2c60a 如上所示 VOLUME NAME太長不容易記憶 在建立容器的時候能夠指定 -v docker run -d --name mysql -v mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123 mysql DRIVER VOLUME NAME local mysql # 查看詳情 docker volume inspect mysql [ { "CreatedAt": "2019-12-23T06:40:53Z", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/mysql/_data", "Name": "mysql", "Options": null, "Scope": "local" } ] # 測試是否可以持久化 1.建立一個數據庫tester 2. 退出容器並刪除容器 3.查看volume發現,volume並不會隨着容器的刪除而刪除 4.執行命令:docker run -d --name mysql -v mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123 mysql(volume屬性指向以前建立的volume->mysql) docker run -d --name mysql -p 3306:3306 -v mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123 --net net-cluster mysql:latest --log-bin=mysql-bin --binlog-format=ROW --server_id=101(甚至能夠直接修改my.cnf) 5.進入mysql並show databases;發現以前建立的數據庫還在。
- Bind Mounts
# 1. 建立一個文件 /usr/local/web/1.html 內容: <h1>hello</h1> #2. 掛載並運行:docker run -d --name tomcat -p 8888:8080 -v /usr/local/web/:/usr/local/tomcat/webapps/web/ tomcat 或者 docker run -d --name tomcat02 -p 9000:8080 --mount type=bind,source=/usr/local/web/,target=/usr/local/tomcat/webapps/web/ tomcat #3.訪問http://ip:8888/web/1.html查看內容 #4.進入到Tomcat中查看,會發現有個同樣的目錄和文件。 #5.再次修改物理機中的1.html 加入內容<h2>Docker</h2> #6.從新訪問瀏覽器會發現內容的變化
Docker容器管理
若是使用命令行的方式,須要每次先建立自定義網路、掛載等再一個個的啓動運行容器相對來講比較麻煩,下面來看看Docker容器管理。
- 單機版多容器管理
- docker-compose
安裝
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose docker-compose --version
版本
https://github.com/docker/compose/releases
命令
https://docs.docker.com/compose/reference/envvars/
示例
#打印訪問次數 # application.py import time import redis from flask import Flask app = Flask(__name__) cache = redis.Redis(host='redis', port=6379) def get_hit_count(): retries = 5 while True: try: return cache.incr('hits') except redis.exceptions.ConnectionError as exc: if retries == 0: raise exc retries -= 1 time.sleep(0.5) @app.route('/') def hello(): count = get_hit_count() return 'Hello World! I have been seen {} times.\n'.format(count) ---------------------- requirements.txt: flask redis ------------------------------- Dockerfile: FROM python:3.7-alpine WORKDIR /code ENV FLASK_APP application.py ENV FLASK_RUN_HOST 0.0.0.0 RUN apk add --no-cache gcc musl-dev linux-headers COPY requirements.txt requirements.txt RUN pip install -r requirements.txt COPY . . CMD ["flask", "run"] --------------------------------------------- docker-compose.yml: version: '3' services: web: build: . ports: - "5000:5000" volumes: - /web networks: - compose-net redis: image: "redis:alpine" volumes: - /redis networks: - compose-net volumes: web: redis: networks: compose-net
注意:若是不指定網絡,docker-compose會生成一個默認的網絡
- 集羣版多容器管理
- docker swarm
示例(1個manager,2個work)
manager:docker swarm init --advertise-addr= ip # 日誌輸出: Swarm initialized: current node (k2bfj4ipf63u) is now a manager.
work(2個):$ docker swarm join --token SWMTKN-1-k2bfj4ipf63u192.0.0.1:2377 日誌輸出: This node joined a swarm as a worker.
查看集羣信息
docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION k2bfj4ipf63u * node1 Ready Active Leader 19.03.4 lf9i7sj17u5b node2 Ready Active 19.03.4 69tfr9cq6j61 node3 Ready Active 19.03.4
節點升/降級
#示例命令: docker node promote node2 docker node demote node2
建立一個Tomcat
docker service create --name tomcat -p 8080:8080 tomcat
查看swarm的services
#命令: docker service ls ID NAME MODE REPLICAS IMAGE PORTS qy870rkl tomcat replicated 1/1 tomcat:latest *:8080->8080/tcp
查看service的啓動日誌
docker service logs tomcat
查看在哪一個node中運行
docker service ps tomcat
擴展service
docker service scale tomcat=3
自動恢復
# 刪除其中一個容器 docker rm -f bfaxc6smw #查看 $ docker service ps tomcat ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 50000saiypxh tomcat.1 tomcat:latest node2 Running Running 30 minutes ago 3x4bfaxc6smw tomcat.2 tomcat:latest node3 Running Running 19 minutes ago vicrsu2aebud \_ tomcat.2 tomcat:latest node3 Shutdown Failed 19 minutes ago "task: non-zero exit (137)" ot50dhj0b1at tomcat.3 tomcat:latest node1 Running Running 23 minutes ago
刪除service
docker service rm tomcat # 再次查看 docker service ls