Docker各類知識點進行整理分享,其他內容請參考目錄。
docker build 可以建立一個自定義映象;docker run 可以啟動一個容器;而實際專案中,特別是微服務化之後,運維需要面對的不單單是一個映象一個容器,而是幾十乃至上千。如果通過手工敲命令去建立一個個容器,不科學也太慢。如果遇到機器更新換代或者重啟,又得重新敲一遍,這樣下去我想遲早腦袋頭髮都要掉光。還好docker提前想到了這點,為我們準備了相應的工具:
容器編排:docker compose叢集編排:swarm mode還有一個很時尚的工具Kubernetes ,它是Google根據自身十幾年經驗打造的。
容器編排:docker composeCompose 是由Python 編寫,定義和執行多個 Docker 容器的工具。通過一個 docker-compose.yml 模板檔案(YAML 格式)來定義應用服務,簡單的命令批量建立和啟動定義的所有服務。
重要概念:
服務 (service):一個應用容器,實際上可以執行多個相同映象的例項。專案 (project):由一組關聯的應用容器組成的一個完整業務單元。一個專案可以由多個服務(容器)關聯而成,Compose 面向專案進行管理。
特性:
使用不同的專案名稱可以在一個主機構建不同的應用環境。比如開發主機上的不同專案。預設專案名稱為yml檔案所在目錄名稱,通過使用-p projectname 可以自定義專案名稱。建立的映象和容器名稱字首會帶上專案名稱。儲存已經建立容器裡頭掛載的資料。執行 docker-compose up 的時候,如果監測到有執行的容器,它會自動把舊容器掛載的資料複製到新的容器。Compose會快取建立容器的配置,重啟service時只會重建有更改的容器。yml模板檔案支援可變引數,使用引數可以建立不同的應用。db: image: "postgres:${POSTGRES_VERSION}"yml模板檔案常用配置:
version:compose檔案格式版本號,最新版為3。services:服務父節點。通過映象建立容器的docker-compose.yml檔案version: "3"services: #容器唯一標識 webapp: #映象名稱 image: examples/web ports: - "80:80" volumes: - "/data"通過DockerFile編譯建立容器的docker-compose.yml檔案version: '3'services: #容器唯一標識 webapp: build: #DockerFile檔案地址 context: ./dir #DockerFile檔名稱 dockerfile: Dockerfile-alternate安裝:
Mac/Windows安裝:Docker Desktop for Mac/Windows 自帶 docker-compose 二進位制檔案,安裝 Docker 之後可以直接使用。Linux安裝:$ sudo curl -L https://github.com/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose$ sudo chmod +x /usr/local/bin/docker-compose常見命令:
up: 建立並啟動配置的所有容器down: 停止並刪除容器、映象、網路、儲存盤ps:列出服務(service)所有的容器images:列出服務(service)所有的映象rm:刪除停止的容器build:編譯或者再編譯服務create: 建立服務start:開啟服務stop:停止服務restart:重啟服務例項
下面用 Python 來建立一個能夠記錄頁面訪問次數的 web 網站。
新建composetest資料夾,在該目錄中編寫 app.py檔案。
import timeimport redisfrom flask import Flaskapp = 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! 該頁面已被訪問 {} 次。\\n'.format(count)在資料夾中,新增 Dockerfile 檔案
FROM python:3.7-alpineWORKDIR /codeENV FLASK_APP app.pyENV FLASK_RUN_HOST 0.0.0.0RUN apk add --no-cache gcc musl-dev linux-headersRUN pip install redis flaskCOPY . .CMD ["flask", "run"]通過Python 3.7 基礎映象建立.設定工作目錄為 /code.設定FLask命令的環境變數.安裝gcc 加速編譯MarkupSafe與SQLAlchemy.安裝python依賴的包.複製當前目錄內容到映象目錄.設定容器預設啟動命令flask run.在資料夾外部建立 docker-compose.yml 檔案
version: '3'services: webtest: build: ./composetest ports: - 5000:5000 redis: image: redis:alpine 建立一個web容器,開放5000埠.從Docker Hub拉取一個Redis映象建立容器.執行Compose專案。(專案名稱為plana)
D:\\docker\\03-compose>docker-compose -p plana upCreating network "plana_default" with the default driverBuilding webtestStep 1/8 : FROM python:3.7-alpine---> 16f919b9ecd5Step 2/8 : WORKDIR /code---> Using cache---> 3cd944ab4513Step 3/8 : ENV FLASK_APP app.py---> Using cache---> 2aa9917f4c9fStep 4/8 : ENV FLASK_RUN_HOST 0.0.0.0---> Using cache---> db1028a91223Step 5/8 : RUN apk add --no-cache gcc musl-dev linux-headers---> Using cache---> 13a0ed97a7ddStep 6/8 : RUN pip install redis flask---> Using cache---> 1807263196e2Step 7/8 : COPY . .---> Using cache---> 553b6c68eaceStep 8/8 : CMD ["flask", "run"]---> Using cache---> ad92e1924ad5Successfully built ad92e1924ad5Successfully tagged plana_webtest:latestWARNING: Image for service webtest was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.Creating plana_redis_1 ... done Creating plana_webtest_1 ... done Attaching to plana_webtest_1, plana_redis_1redis_1 | 1:C 29 Apr 2020 12:59:36.795 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Ooredis_1 | 1:C 29 Apr 2020 12:59:36.795 # Redis version=5.0.9, bits=64, commit=00000000, modified=0, pid=1, just startedredis_1 | 1:C 29 Apr 2020 12:59:36.795 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.confredis_1 | 1:M 29 Apr 2020 12:59:36.800 * Running mode=standalone, port=6379.redis_1 | 1:M 29 Apr 2020 12:59:36.800 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.redis_1 | 1:M 29 Apr 2020 12:59:36.800 # Server initializedredis_1 | 1:M 29 Apr 2020 12:59:36.801 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.redis_1 | 1:M 29 Apr 2020 12:59:36.802 * Ready to accept connectionswebtest_1 | * Serving Flask app "app.py"webtest_1 | * Environment: productionwebtest_1 | WARNING: This is a development server. Do not use it in a production deployment.webtest_1 | Use a production WSGI server instead.webtest_1 | * Debug mode: offwebtest_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)執行結果。(需要指定專案名稱)
D:\\docker\\03-compose>docker-compose psName Command State Ports------------------------------D:\\docker\\03-compose>docker-compose imagesContainer Repository Tag Image Id Size----------------------------------------------D:\\docker\\03-compose>docker-compose -p plana images Container Repository Tag Image Id Size------------------------------------------------------------------plana_redis_1 redis alpine 3661c84ee9d0 29.8 MBplana_webtest_1 plana_webtest latest ad92e1924ad5 219.7 MBD:\\docker\\03-compose>docker-compose -p plana ps Name Command State Ports---------------------------------------------------------------------------------plana_redis_1 docker-entrypoint.sh redis ... Up 6379/tcpplana_webtest_1 flask run Up 0.0.0.0:5000->5000/tcp叢集編排:swarm modeSwarm 是使用 SwarmKit 構建的 Docker 引擎內建(原生)的叢集管理和編排工具。Docker 1.12開始 Swarm mode 已經內嵌入 Docker 引擎,成為了 docker 子命令 docker swarm。Swarm mode 內建 kv 儲存功能,提供了眾多的新特性,使得 Docker 原生的 Swarm 叢集具備與 Mesos、Kubernetes 競爭的實力。比如:
具有容錯能力的去中心化設計內建服務發現負載均衡路由網格動態伸縮滾動更新安全傳輸等常見概念
節點節點為作用在Swarm叢集中的一個例項化Docker引擎。雖然可以在一臺物理主機上部署多個節點,但是生產環境中都是跨物理主機進行。 節點可以加入已經存在的swarm叢集或者將自己初始化為一個swarm叢集。
分為:管理(manager)節點,工作(worker)節點。
管理節點:執行docker swarm 命令管理 swarm 叢集的節點。一個 Swarm 叢集可以有多個管理節點,但只有一個管理節點可以成為 leader,leader 通過 raft 協議實現。管理節點下發任務(Task) 給工作節點,通過工作節點通知給它的任務(Task)執行狀態來管理每個工作節點。工作節點:接收和執行來自管理節點的任務(task)。管理節點預設也作為工作節點。你也可以通過配置讓服務只執行在管理節點。服務(Service)與任務(Task)服務關係
任務(Task):Swarm 中的最小的排程單位,目前來說就是一個單一的容器。一個任務分配給一個節點之後,哪怕執行失敗都無法轉移到其他節點。服務(Service):運行於管理或者工作節點上的一組任務屬性定義。它是Swarm的中心結構,也是與Swarm互動的主要角色。與Docker-compose中的服務類似,包含映象與命令等。服務有兩種模式:replicated services:按照一定規則在各個工作節點上執行指定個數的任務。global services:每個工作節點上執行一個任務使用例項
使用https://www.docker.com/play-with-docker實驗。
初始化管理節點$ docker swarm initError response from daemon: could not choose an IP address to advertise since this system has multiple addresses on different interfaces (192.168.0.48 on eth0 and 172.18.0.53 on eth1) - specify one with --advertise-addr因為有多個網路地址需要指定
$ docker swarm init --advertise-addr 192.168.0.48Swarm initialized: current node (uas5ayulwp28ldrcr3bscmitr) is now a manager.To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-17khjeqkfmjswynhda1i0dfqw4hy5io2006xktyvav272ccfie-6xomx3u1mvm7pacj0ymheyu6e 192.168.0.48:2377To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.檢視節點列表
$ docker node lsID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSIONuas5ayulwp28ldrcr3bscmitr * node1 Ready Active Leader 19.03.4加入工作節點$ docker swarm join --token SWMTKN-1-17khjeqkfmjswynhda1i0dfqw4hy5io2006xktyvav272ccfie-6xomx3u1mvm7pacj0ymheyu6e 192.168.0.48:2377This node joined a swarm as a worker.在兩個主機執行以上命令之後,去管理節點檢視節點列表
$ docker node lsID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSIONuas5ayulwp28ldrcr3bscmitr * node1 Ready Active Leader 19.03.42rum5pm81t76tjv91rld1n8vu node3 Ready Active 19.03.4u4tbyt95nhy7l6vj3z013r8wz node5 Ready Active 19.03.4服務部署(命令都是在管理節點執行。)1.新建服務
在叢集中建立nginx服務。
$ docker service create --replicas 3 -p 80:80 --name nginx nginx:lateststieixvmvfipi4w6qh49t9es0overall progress: 3 out of 3 tasks 1/3: running 2/3: running 3/3: running verify: Service converged2.檢視服務
檢視服務列表:
$ docker service lsID NAME MODE REPLICAS IMAGE PORTSstieixvmvfip nginx replicated 3/3 nginx:latest *:80->80/tcp檢視服務詳細:
$ docker service ps nginxID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTSxgc5u5m5gl9p nginx.1 nginx:latest node3 Running Running 2 minutes ago y76pttbz9pkh nginx.2 nginx:latest node5 Running Running 2 minutes ago oti754af3izt nginx.3 nginx:latest node1 Running Running 2 minutes ago瀏覽器中輸入管理節點或者工作節點IP地址都可以檢視nginx介面。
管理節點
工作節點
工作節點
3.服務伸縮
業務訪問量少時,可以減少服務執行容器數。
$ docker service scale nginx=2nginx scaled to 2overall progress: 2 out of 2 tasks 1/2: running 2/2: running verify: Service converged
檢視服務詳情:
$ docker service lsID NAME MODE REPLICAS IMAGE PORTSstieixvmvfip nginx replicated 2/2 nginx:latest *:80->80/tcp
業務訪問量多時,可以增加服務執行容器數。
$ docker service scale nginx=3nginx scaled to 3overall progress: 3 out of 3 tasks 1/3: running 2/3: running 3/3: running verify: Service converged
4.刪除服務
$ docker service rm nginxnginx
檢視服務:
$ docker service lsID NAME MODE REPLICAS IMAGE PORTS
通過compose檔案部署服務
docker service create 一次只能部署一個服務,使用 docker-compose.yml 可以一次啟動多個關聯的服務
1.建立docker-compose.yml檔案
version: "3"services: nginx: image: nginx:latest ports: - 80:80 deploy: mode: replicated replicas: 3
2.部署服務
yml檔案通過使用docker stack部署。
$ docker stack deploy -c docker-compose.yml nginxCreating network nginx_defaultCreating service nginx_nginx
3.檢視服務
$ docker stack lsNAME SERVICES ORCHESTRATORnginx 1 Swarm$ docker service lsID NAME MODE REPLICAS IMAGE PORTS92n4xd254vu1 nginx_nginx replicated 3/3 nginx:latest *:80->80/tcp$ docker service ps nginx_nginxID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTSp6d3xibx9swx nginx_nginx.1 nginx:latest node1 Running Running 2 minutes ago v0taw0rnr9v3 nginx_nginx.2 nginx:latest node3 Running Running 2 minutes ago 2z3sbkdo16oi nginx_nginx.3 nginx:latest node5 Running Running 2 minutes ago
4.移除服務
$ docker stack down nginxRemoving service nginx_nginxRemoving network nginx_default