按部就班學Docker

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怎麼製做的
  1. Dockerfile > https://github.com/docker-library 每個image都是根據Dockerfile配置生成的

驗證html

> 將官網上的mogodb的Dockerfile放入到咱們的物理主機上,
並執行。
#mogodb-my 起個別名
docker build -t mogodb-my .
  1. 根據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@if8veth61cf0b5@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
  1. bridge
  • 默認使用的方式 2.host
  • 訪問容器不須要進行映射直接能夠訪問
  1. 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
相關文章
相關標籤/搜索