Docker快速入門

part 1: 目標與快速入門

歡迎!我們很高興你對學(xué)習Docker那么感興趣。這篇快速入門教程包括如下內(nèi)容:

  1. 配置Docker環(huán)境
  2. 創(chuàng)建一個Docker鏡像并在容器中運行
  3. 擴容你的應(yīng)用,在多個容器中運行
  4. 在集群中運行你的應(yīng)用
  5. 添加數(shù)據(jù)庫組成服務(wù)堆棧
  6. 生產(chǎn)環(huán)境部署你的應(yīng)用

Docker 中的概念

Docker是開發(fā)人員和系統(tǒng)管理員使用容器開發(fā),部署和運行應(yīng)用程序的平臺。 使用Linux容器部署應(yīng)用程序被稱為容器化。 容器的概念并不是新的,但是將容器用來輕松的部署應(yīng)用程序卻是一個新穎的想法

容器化變得如此受歡迎主要因為容器:

  • 靈活: 即使復(fù)雜度很高的應(yīng)用同樣可以容器化
  • 輕量級: 容器之間共享宿主機內(nèi)核
  • 快速升級: 動態(tài)部署更新和升級
  • 可移植: 可以本地build,部署到云上,并且可以在任何地方運行
  • 可擴展: 可以增加并自動分發(fā)容器副本
  • 服務(wù)堆棧: You can stack services vertically and on-the-fly.

鏡像和容器

通過運行一個鏡像可以啟動一個容器。鏡像是包含運行應(yīng)用程序所需環(huán)境的可執(zhí)行包,運行環(huán)境包括程序代碼,運行時,各種依賴庫,環(huán)境變量和配置文件

容器是一個鏡像的運行實例??梢酝ㄟ^docker ps查看運行中的容器

容器和虛擬機

容器在Linux上本機運行,并與其他容器共享主機的內(nèi)核。 它運行一個獨立的進程,不占用任何其他可執(zhí)行文件的內(nèi)存,使其輕量級

相比之下,虛擬機(VM)運行一個完整的“客戶”操作系統(tǒng),通過虛擬機管理程序?qū)χ鳈C資源進行虛擬訪問。 通常,VM提供的環(huán)境比大多數(shù)應(yīng)用程序需要的資源更多

Container stack example

Virtual machine stack example

準備Docker環(huán)境

安裝docker,這一步具體這篇文章

驗證docker版本
  1. 運行docker --version確認docker版本
$ docker --version
Docker version 19.03.1, build 74b1e89
  1. 運行docker infodocker version查看更多docker版本細節(jié)
$ docker info
Client:
 Debug Mode: false

Server:
 Containers: 1
  Running: 0
  Paused: 0
  Stopped: 1
 Images: 10
 Server Version: 19.03.1
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 894b81a4b802e4eb2a91d1ce216b8817763c29fb
 runc version: 425e105d5a03fabd737a126ad93d62a9eeede87f
 init version: fec3683
 Security Options:
  seccomp
   Profile: default
 Kernel Version: 4.9.184-linuxkit
 Operating System: Docker Desktop
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 1.952GiB
 Name: docker-desktop
 ID: XOGQ:6LZ4:DWI4:MH24:T7NA:MBOH:OHXR:2QYW:Q5CO:I5FR:TEVJ:Y5B7
 Docker Root Dir: /var/lib/docker
 Debug Mode: true
  File Descriptors: 32
  Goroutines: 49
  System Time: 2019-08-27T08:02:13.8093806Z
  EventsListeners: 2
 HTTP Proxy: gateway.docker.internal:3128
 HTTPS Proxy: gateway.docker.internal:3129
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Registry Mirrors:
  http://f1361db2.m.daocloud.io/
 Live Restore Enabled: false
 Product License: Community Engine

為了避免權(quán)限問題(使用sudo運行),需要將用戶添加到docker用戶組中。具體參考這篇文章

驗證doker安裝
  1. 通過運行簡單的hello-world鏡像測試docker安裝是否成功

    $ docker run hello-world
    
    Unable to find image 'hello-world:latest' locally
    latest: Pulling from library/hello-world
    [DEPRECATION NOTICE] registry v2 schema1 support will be removed in an upcoming release. Please contact admins of the docker.io registry NOW to avoid future disruption.
    1b930d010525: Pull complete
    Digest: sha256:fb158b7ad66f4d58aa66c4455858230cd2eab4cdf29b13e5c3628a6bfc2e9f05
    Status: Downloaded newer image for hello-world:latest
    
    Hello from Docker!
    This message shows that your installation appears to be working correctly.
    
    To generate this message, Docker took the following steps:
     1. The Docker client contacted the Docker daemon.
     2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
        (amd64)
     3. The Docker daemon created a new container from that image which runs the
        executable that produces the output you are currently reading.
     4. The Docker daemon streamed that output to the Docker client, which sent it
        to your terminal.
    
    To try something more ambitious, you can run an Ubuntu container with:
     $ docker run -it ubuntu bash
    
    Share images, automate workflows, and more with a free Docker ID:
     https://hub.docker.com/
    
    For more examples and ideas, visit:
     https://docs.docker.com/get-started/
    
  2. 列出機器上已經(jīng)下載的hello-world鏡像

    docker image ls或docker images
    
    REPOSITORY          TAG                            IMAGE ID            CREATED             SIZE
    choaya/into         latest                         d013706f5624        About an hour ago   123MB
    minio/minio         RELEASE.2019-08-21T19-40-07Z   7669a864ad18        5 days ago          51.6MB
    nginx               latest                         5a3221f0137b        11 days ago         126MB
    ubuntu              latest                         a2a15febcdf3        12 days ago         64.2MB
    minio/minio         latest                         77a8467ccda1        12 days ago         63.5MB
    python              3.6-alpine                     58496e6dcbca        2 weeks ago         95.1MB
    redis               alpine                         47af6bf42a1e        3 weeks ago         29.3MB
    openjdk             8-jdk-alpine                   a3562aa0b991        3 months ago        105MB
    hello-world         latest                         fce289e99eb9        7 months ago        1.84kB
    
  3. 列出機器上的容器,--all-a會列出所有的容器,包括已經(jīng)停止運行的容器

    $ docker container ls -a 或 $ docker container ls --all
    
    942b61d0b2ce        hello-world         "/hello"                 2 minutes ago       Exited (0) 2 minutes ago                             awesome_grothendieck
    78bc76fae770        d013706f5624        "java -Djava.securit…"   About an hour ago   Exited (143) About an hour ago                       into
    

總結(jié)和小抄

## List Docker CLI commands
docker
docker container --help

## Display Docker version and info
docker --version
docker version
docker info

## Execute Docker image
docker run hello-world

## List Docker images
docker image ls

## List Docker containers (running, all, all in quiet mode)
docker container ls
docker container ls --all
docker container ls -aq

part 1 結(jié)論

容器化使得持續(xù)集成/持續(xù)部署無縫銜接,比如:

  • 應(yīng)用沒有系統(tǒng)依賴
  • 可以將更新推送到分布式應(yīng)用程序的任何部分
  • 資源密度可以優(yōu)化

Part 2: 容器

前提條件

  • 安裝版本1.13以上的docker

  • 完成Part 1部分的學(xué)習

  • 下面命令能正常執(zhí)行

    $ docker run hello-world
    

簡介

現(xiàn)在開始就可以用Docker的方式來開發(fā)一個應(yīng)用程序。我們從一個應(yīng)用程序最底層,也就是container開始。在container之上是service,這部分將這part 3中介紹。最后最頂層是stack,這部分將這part 5中介紹。

  • Stack
  • Services
  • Container(現(xiàn)在在這)

新的開發(fā)環(huán)境

過去,如果您你要開始編寫Python應(yīng)用程序,那么你首先就是在你的計算機上安裝Python。 但是,你需要保證安裝的Python和你機器能兼容而且還要和你生產(chǎn)環(huán)境中的環(huán)境相匹配。

使用Docker,您可以使用一個可移植的Python環(huán)境作為鏡像,無需安裝。 然后,你可以將基礎(chǔ)鏡像,應(yīng)用程序代碼,依賴項,運行時一起打包構(gòu)建。

這些可移植鏡像由Dockerfile定義。

使用Dockerfile定義容器

Dockerfile定義容器內(nèi)環(huán)境中發(fā)生的事情。 對網(wǎng)絡(luò)接口和磁盤驅(qū)動器等資源的訪問在此環(huán)境中進行虛擬化,該環(huán)境與系統(tǒng)的其他部分隔離,因此您需要將端口映射到外部世界,并具體說明要“復(fù)制”到哪些文件到這個環(huán)境。此Dockerfile中定義的應(yīng)用程序的構(gòu)建在其運行時表現(xiàn)完全一致。

Dockerfile

在本地機器上創(chuàng)建一個空的目錄,并進入到這個目錄,在這個目錄中創(chuàng)建Dockerfile文件,拷貝下面的內(nèi)容到這個文件,然后保存。Dockerfile中的每個語句都有說明。

$ mkdir app
$ cd app
$ touch Dockerfile
# 使用官方的python運行時作為基礎(chǔ)鏡像
FROM python:2.7-slim

# 設(shè)置工作目錄為/app
WORKDIR /app

# 拷貝當前目錄中的內(nèi)容到容器中/app目錄下
COPY . /app

# 按章requirements.txt文件中定義的依賴
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# 暴露80端口
EXPOSE 80

# 定義環(huán)境變量
ENV NAME World

# 容器啟動時運行app.py
CMD ["python", "app.py"]

Dockerfile中使用了一些還沒有創(chuàng)建的文件app.pyrequirements.txt。下面我們來創(chuàng)建這些文件。

應(yīng)用本身

Dockerfile同目錄下創(chuàng)建app.pyrequirements.txt文件。

touch app.py requirements.txt

requirements.txt

Flask
Redis

app.py

from flask import Flask
from redis import Redis, RedisError
import os
import socket

# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)

app = Flask(__name__)

@app.route("/")
def hello():
    try:
        visits = redis.incr("counter")
    except RedisError:
        visits = "<i>cannot connect to Redis, counter disabled</i>"

    html = "<h3>Hello {name}!</h3>" \
           "<b>Hostname:</b> {hostname}<br/>" \
           "<b>Visits:</b> {visits}"
    return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)

目前我們通過pip install -r requirements.txt安裝了FlaskRedis的pthon庫,應(yīng)用程序打印了環(huán)境變量NAMEsocket.gethostname(),最后,由于Redis并沒有運行,這里應(yīng)該會打印錯誤信息。

在容器內(nèi)獲取hostname,其實是container ID,類似于 process ID

OK!你并不需要安裝Python或者requirements.txt中定義的庫文件在你的系統(tǒng),構(gòu)建或運行這個鏡像也不需要在系統(tǒng)上安裝它們。 你似乎并沒有真正設(shè)置Python和Flask的環(huán)境,但實際上你已經(jīng)有了。

構(gòu)建應(yīng)用

準備構(gòu)建這個應(yīng)用。在此之前,請先確保你在剛才建立的目錄下,ls列出這個目錄下的內(nèi)容:

$ ls
Dockerfile       app.py           requirements.txt

現(xiàn)在運行構(gòu)建命令。這條命令將會創(chuàng)建一個Docker鏡像,可以通過--tag-t選項來制定鏡像名稱

docker build --tag=friendlyhello .

構(gòu)建的鏡像在哪?已經(jīng)在你的本地機器上了

$ docker images
REPOSITORY          TAG                            IMAGE ID            CREATED             SIZE
friendlyhello       latest                         996ecb8e1951        30 seconds ago      148MB
choaya/into         latest                         d013706f5624        2 hours ago         123MB
python              2.7-slim                       6b34ff151910        9 hours ago         137MB
minio/minio         RELEASE.2019-08-21T19-40-07Z   7669a864ad18        5 days ago          51.6MB
nginx               latest                         5a3221f0137b        11 days ago         126MB
ubuntu              latest                         a2a15febcdf3        12 days ago         64.2MB
minio/minio         latest                         77a8467ccda1        12 days ago         63.5MB
python              3.6-alpine                     58496e6dcbca        2 weeks ago         95.1MB
redis               alpine                         47af6bf42a1e        3 weeks ago         29.3MB
openjdk             8-jdk-alpine                   a3562aa0b991        3 months ago        105MB
hello-world         latest                         fce289e99eb9        7 months ago        1.84kB

注意tag默認是latest。完整的tag語法應(yīng)該像這個樣子--tag=friendlyhello:v0.0.1

運行應(yīng)用程序

運行應(yīng)用程序,使用-p將機器的4000端口映射到容器的80端口

docker run -p 4000:80 friendlyhello

在運行的日志上,你可以看到你的服務(wù)運行在http://0.0.0.0:80/,但是這寫消息來自于容器內(nèi)部,容器并不知道你將容器的80端口映射到了4000端口,所以正確的URL應(yīng)該是http://localhost:4000

在瀏覽器中輸入URL,查看頁面內(nèi)容

應(yīng)用運行顯示內(nèi)容

同樣可以使用curl命令得到同樣的內(nèi)容

$ curl localhost:4000

<h3>Hello World!</h3><b>Hostname:</b> 14cf737a0cf5<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>

端口重映射4000:80演示了 DockerfileEXPOSEdocker run -p運行的區(qū)別。后者將宿主機4000端口映射到容器的80端口,在容器內(nèi)部可以使用http://localhost來訪問。

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                          NAMES
4f28a2e7c9e6        friendlyhello       "python app.py"     2 minutes ago       Up 2 minutes        80/tcp, 0.0.0.0:80->4000/tcp   pedantic_hermann

$ docker exec -it pedantic_hermann /bin/bash
$ root@4f28a2e7c9e6:/app# curl localhost
<h3>Hello World!</h3><b>Hostname:</b> 14cf737a0cf5<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>

注意這里使用docker exec -it pedantic_hermann /bin/bash 進入了容器,由于基礎(chǔ)鏡像中并沒有安裝curl,所以需要先通過apt安裝curl才能使用。

$ apt update

$ apt-get install curl

這里只是為了驗證內(nèi)部容器可以通過80端口進行訪問,盡量不要在容器內(nèi)安裝多余的內(nèi)容,這會增加容器的大小

ctrl+c停止運行。

在后臺運行應(yīng)用程序,使用detached模式

docker run -d -p 4000:80 friendlyhello

執(zhí)行完后你會得到一個長長的 container ID,然后馬上退出返回到命令行。這樣容器就會一直在后臺運行??梢酝ㄟ^docker container ls命令查看到簡短的container ID。

$ docker container ls

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                  NAMES
cf8a2c2a348b        friendlyhello       "python app.py"     4 minutes ago       Up 4 minutes        0.0.0.0:4000->80/tcp   mystifying_brown

注意CONTAINER IDhttp://localhost:4000頁面上的hostname是匹配的

現(xiàn)在使用docker container stop結(jié)束容器運行,將CONTAINER ID作為參數(shù)

docker container stop cf8a2c2a348b

共享鏡像

為了演示剛才關(guān)鍵鏡像的便攜性,我們需要上傳我們剛才的鏡像,然后嘗試在任何地方運行它。畢竟當你在線上部署容器時,你需要知道怎么push鏡像到registries。

registries時一些倉庫的集合,倉庫時鏡像的集合。這個有點像Github倉庫。

使用Docker ID登陸

如果沒有Docker賬戶,請在hub.docker.com上注冊一個。注意你的用戶名。

在你機器上登陸公共的registry

docker login
給鏡像打標簽

通過 username/repository:tag可以將本地鏡像和registry的一個倉庫關(guān)聯(lián)。tag是可選的,但是推薦填上。比如get-started:part2,這就是將鏡像放在get-started倉庫,tagpart2

現(xiàn)在運行docker tag image傳入username,repository和tag

docker tag image username/repository:tag

比如

docker tag friendlyhello choaya/get-started:part2

運行docker images查看這個新的鏡像

$ docker images
REPOSITORY           TAG                            IMAGE ID            CREATED             SIZE
choaya/get-started   part2                          996ecb8e1951        About an hour ago   148MB
friendlyhello        latest                         996ecb8e1951        About an hour ago   148MB
choaya/into          latest                         d013706f5624        3 hours ago         123MB
python               2.7-slim                       6b34ff151910        10 hours ago        137MB
minio/minio          RELEASE.2019-08-21T19-40-07Z   7669a864ad18        5 days ago          51.6MB
nginx                latest                         5a3221f0137b        11 days ago         126MB
ubuntu               latest                         a2a15febcdf3        12 days ago         64.2MB
minio/minio          latest                         77a8467ccda1        12 days ago         63.5MB
python               3.6-alpine                     58496e6dcbca        2 weeks ago         95.1MB
redis                alpine                         47af6bf42a1e        3 weeks ago         29.3MB
openjdk              8-jdk-alpine                   a3562aa0b991        3 months ago        105MB
hello-world          latest                         fce289e99eb9        7 months ago        1.84kB
發(fā)布鏡像

上傳剛才的鏡像到倉庫

docker push choaya/get-started:part2

完成之后,你可以登陸到Docker Hub,可以看到這個鏡像。

pull同時運行遠程倉庫的鏡像

從現(xiàn)在開始,你可以用docker run直接在你的機器上運行你的應(yīng)用程序。

docker run -p 4000:80 choaya/get-started:part2

如果本地沒有這個鏡像,docker自動會從遠程倉庫中下載這個鏡像到本地機器

由于我們本地已經(jīng)有這個鏡像,為了演示便攜性,我先把本地的鏡像刪除

$ docker images
REPOSITORY           TAG                            IMAGE ID            CREATED             SIZE
choaya/get-started   part2                          996ecb8e1951        About an hour ago   148MB
friendlyhello        latest                         996ecb8e1951        About an hour ago   148MB
choaya/into          latest                         d013706f5624        3 hours ago         123MB
python               2.7-slim                       6b34ff151910        11 hours ago        137MB
minio/minio          RELEASE.2019-08-21T19-40-07Z   7669a864ad18        5 days ago          51.6MB
nginx                latest                         5a3221f0137b        11 days ago         126MB
ubuntu               latest                         a2a15febcdf3        12 days ago         64.2MB
minio/minio          latest                         77a8467ccda1        12 days ago         63.5MB
python               3.6-alpine                     58496e6dcbca        2 weeks ago         95.1MB
redis                alpine                         47af6bf42a1e        3 weeks ago         29.3MB
openjdk              8-jdk-alpine                   a3562aa0b991        3 months ago        105MB
hello-world          latest                         fce289e99eb9        7 months ago        1.84kB

$ docker container prune

$ docker image rm -f 996ecb8e1951

$ docker images
REPOSITORY          TAG                            IMAGE ID            CREATED             SIZE
choaya/into         latest                         d013706f5624        3 hours ago         123MB
python              2.7-slim                       6b34ff151910        11 hours ago        137MB
minio/minio         RELEASE.2019-08-21T19-40-07Z   7669a864ad18        5 days ago          51.6MB
nginx               latest                         5a3221f0137b        11 days ago         126MB
ubuntu              latest                         a2a15febcdf3        12 days ago         64.2MB
minio/minio         latest                         77a8467ccda1        12 days ago         63.5MB
python              3.6-alpine                     58496e6dcbca        2 weeks ago         95.1MB
redis               alpine                         47af6bf42a1e        3 weeks ago         29.3MB
openjdk             8-jdk-alpine                   a3562aa0b991        3 months ago        105MB
hello-world         latest                         fce289e99eb9        7 months ago        1.84kB

可以看到現(xiàn)在我本地機器上已經(jīng)沒有了剛才創(chuàng)建的鏡像,現(xiàn)在直接從遠程倉庫運行應(yīng)用程序試試。

$ docker run -p 4000:80 choaya/get-started:part2

Unable to find image 'choaya/get-started:part2' locally
part2: Pulling from choaya/get-started
[DEPRECATION NOTICE] registry v2 schema1 support will be removed in an upcoming release. Please contact admins of the docker.io registry NOW to avoid future disruption.
1ab2bdfe9778: Already exists
f9047cc61c29: Already exists
7f58e6c9f6f0: Already exists
7058c90ade99: Already exists
32c0ef8226c3: Pull complete
c67c640dc154: Pull complete
13606c24f595: Pull complete
Digest: sha256:02e4a83a136002050374b2b5d3b15683ff2134ed752bb8435f1f770ecbcd57d1
Status: Downloaded newer image for choaya/get-started:part2
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:80/ (Press CTRL+C to quit)

可以看到從遠程倉庫拉取了鏡像,并運行了一個容器,在本地通過http://localhost:4000可以正常訪問

如論在什么地方執(zhí)行docker run,它都會pull你的鏡像,同時Python和requirements.txt定義的依賴和你的應(yīng)用程序代碼都會一并打包。你不需要在你機器上安裝各種環(huán)境。

Part 2結(jié)論

這部分內(nèi)容到這就結(jié)束了,下一節(jié)我們將學(xué)習擴容我們應(yīng)用,我們將以service來運行這個container

這里是這一節(jié)所用到的命令

docker build -t friendlyhello .  # Create image using this directory's Dockerfile
docker run -p 4000:80 friendlyhello  # Run "friendlyhello" mapping port 4000 to 80
docker run -d -p 4000:80 friendlyhello         # Same thing, but in detached mode
docker container ls                                # List all running containers
docker container ls -a             # List all containers, even those not running
docker container stop <hash>           # Gracefully stop the specified container
docker container kill <hash>         # Force shutdown of the specified container
docker container rm <hash>        # Remove specified container from this machine
docker container rm $(docker container ls -a -q)         # Remove all containers
docker image ls -a                             # List all images on this machine
docker image rm <image id>            # Remove specified image from this machine
docker image rm $(docker image ls -a -q)   # Remove all images from this machine
docker login             # Log in this CLI session using your Docker credentials
docker tag <image> username/repository:tag  # Tag <image> for upload to registry
docker push username/repository:tag            # Upload tagged image to registry
docker run username/repository:tag                   # Run image from a registry

Part 3: Services

前提條件

  • 安裝版本1.13以上的docker
  • 安裝Docker Compose。Mac OS版和Windows版的Docker已經(jīng)預(yù)裝了。在Linux上,你需要安裝
  • 學(xué)習完P(guān)art 1
  • 學(xué)習完P(guān)art 2
  • 確保Part 2中推向遠程倉庫的鏡像能正常運行,這一節(jié)我們將會使用這個鏡像

簡介

在part 3中我們會擴容我們的應(yīng)用同時啟用負載均衡。為了實現(xiàn)這個目標,我們將進入分布式應(yīng)用的container層級升級到service層

  • Stack
  • Services(現(xiàn)在在這)
  • Container(在part 2中介紹)

關(guān)于services

在分布式應(yīng)用中,應(yīng)用的不同部分稱為"services"。比如,一個視頻分享網(wǎng)站可能包括一個存儲應(yīng)用數(shù)據(jù)到數(shù)據(jù)庫的服務(wù),一個視頻轉(zhuǎn)碼服務(wù),一個為前端提供數(shù)據(jù)的服務(wù)等等

services實際上只是“生產(chǎn)中的容器”。服務(wù)只運行一個鏡像,但它規(guī)定了鏡像的運行方式,它應(yīng)該使用哪些端口,應(yīng)該運行多少個容器副本,以便service具有所需的容量等等。 擴容服務(wù)會更改運行該應(yīng)用的容器實例的數(shù)量,從而為應(yīng)用中的服務(wù)分配更多計算資源。

第一個docker-compose.yml文件

docker-compose.yml文件是一個YAML文件,它定義了Docker容器應(yīng)該怎么運行。

docker-compose.yml

將下面的內(nèi)容保存到docker-compose.yml文件。確保你已經(jīng)將Part 2中的鏡像推到了遠程倉庫,然后將文件中的username/repo:tag換成你自己遠程倉庫鏡像

version: "3"
services:
  web:
    # replace username/repo:tag with your name and image details
    image: username/repo:tag
    deploy:
      replicas: 5
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
    ports:
      - "4000:80"
    networks:
      - webnet
networks:
  webnet:

這個docker-compose.yml告訴Docker做了下面這些事:

  • 從遠程倉庫pull part 2中我們上傳的鏡像
  • 運行5個鏡像的實例作為webservice,限制每個實例最多只能使用單個CPU核心的10%(1.5表示每個實例最多1.5個核心),最多50M的內(nèi)存
  • 如果運行失敗立即重啟
  • 映射本地4000端口到web的80端口
  • Instruct web’s containers to share port 80 via a load-balanced network called webnet. (Internally, the containers themselves publish to web’s port 80 at an ephemeral port.)
  • 使用默認設(shè)置定義一個名為webnet的網(wǎng)絡(luò)(默認配置是一個負載均衡的overlay網(wǎng)絡(luò))

運行新的負載均衡的應(yīng)用

在使用docker stack deploy命令之前,需要先運行

docker swarm init

注意:這條命令的含義在part 4中介紹。如果不運行dicker swarm init會報this node is not a swarm manager錯誤

現(xiàn)在就可以運行了,你需要給你的應(yīng)用一個名字,這里命名為getstartedlab

$ docker stack deploy -c docker-compose.yml getstartedlab

我們在一個宿主機上運行了5個容器實例,每個容器中是我們部署的鏡像。下面我們來探索探索

查看我們應(yīng)用程序webservice的service ID

$ docker service ls

查看上面這條命令的輸出,以應(yīng)用名字為前綴。如果你把應(yīng)用命名同上面一樣,那么這里顯示的名字就是getstartedlab_web。同樣輸出中列出了service ID,副本數(shù)量,鏡像名稱和暴露的端口

同樣,你能運行docker stack services,以stack的名字作為參數(shù)。以下示例命令允許您查看與getstartedlabstack關(guān)聯(lián)的所有服務(wù):

$ docker stack services getstartedlab

ID                  NAME                MODE                REPLICAS            IMAGE                      PORTS
k0eqbpwwjbn7        getstartedlab_web   replicated          5/5                 choaya/get-started:part2   *:4000->80/tcp

service中運行的單個容器稱為task。每個task都有一個唯一ID,最多是docker-compose.yml中定義的replicas數(shù)量。列出你的serviceTasks

$ docker service ps getstartedlab_web

ID                  NAME                  IMAGE                      NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
t9f3n9ehci40        getstartedlab_web.1   choaya/get-started:part2   lazzyq-HP           Running             Running 29 minutes ago
ugf8z6qymwcl        getstartedlab_web.2   choaya/get-started:part2   lazzyq-HP           Running             Running 29 minutes ago
m65zkmcnh9uk        getstartedlab_web.3   choaya/get-started:part2   lazzyq-HP           Running             Running 29 minutes ago
a6kl9zalaxc1        getstartedlab_web.4   choaya/get-started:part2   lazzyq-HP           Running             Running 29 minutes ago
cpb6ynlm7680        getstartedlab_web.5   choaya/get-started:part2   lazzyq-HP           Running             Running 29 minutes ago

你可以運行在瀏覽器中輸入http://localhost:4000,刷新幾次觀察每次的hostname和容器ID的關(guān)系

可以發(fā)現(xiàn),每次刷新,容器ID都會改變一次,這演示了負載均衡的功能。每次請求都會選一個task來響應(yīng)。使用round-robin的方式進行響應(yīng)。容器ID和docker container ls -q中的容器ID對應(yīng)

擴容你的應(yīng)用

你可以通過改變docker-compose.yml文件中replicas來實現(xiàn)擴容。保存修改之后,重新運行docker stack deploy命令

docker stack deploy -c docker-compose.yml getstartedlab

Docker就地運行,不需要先停止stack和停止任何容器就能實現(xiàn)擴容

現(xiàn)在重新運行docker container ls -q查看重新部署的實例。如何擴大副本,則會啟動更多的tasks,運行更多的容器

停止應(yīng)用和swarm

  • 使用docker stack rm命令停止應(yīng)用

    docker stack rm getstartedlab
    
  • 停止swarm

    docker swarm leave --force
    

使用Docker啟動應(yīng)用和擴容就像這么簡單。你已經(jīng)向生產(chǎn)環(huán)境運行容器邁了一大步。接下來,你將會學(xué)習如何在Docker machines集群上運行真正的swarm應(yīng)用。

總結(jié)和小抄

回顧一下,當運行docker run很簡單,在生產(chǎn)環(huán)境中真正的實現(xiàn)是將容器當作service來運行。在Compose文件中,Services定義了容器的行為,這個文件能用來擴容,限制資源和重新部署應(yīng)用。service的改變能就地運行,使用docker stack deploy命令來部署service

這一節(jié)使用到的命令

docker stack ls                                            # List stacks or apps
docker stack deploy -c <composefile> <appname>  # Run the specified Compose file
docker service ls                 # List running services associated with an app
docker service ps <service>                  # List tasks associated with an app
docker inspect <task or container>                   # Inspect task or container
docker container ls -q                                      # List container IDs
docker stack rm <appname>                             # Tear down an application
docker swarm leave --force      # Take down a single node swarm from the manager

Part 4: Swarms

前提條件

  • 安裝版本1.13以上的docker
  • 安裝Docker Compose
  • 安裝Docker Machine,Mac OS版和Windows版的Docker已經(jīng)預(yù)裝了。在Linux上需要安裝
  • 學(xué)習完成part 1
  • 學(xué)習完成part 2
  • 確保Part 2中推向遠程倉庫的鏡像能正常運行,這一節(jié)我們將會使用這個鏡像
  • 一份part 3中的docker-compose.yml文件的備份

簡介

在part 3中,我們使用part 2中構(gòu)建的鏡像,將其以service的方式,擴容到5個實例

在part 4中,我們將部署應(yīng)用到集群中,并且在多臺機器上運行。多容器,多機應(yīng)用實現(xiàn)基于被稱為swarm的``Docker化`的集群

理解Swarm集群

Swarm是一組運行Docker的機器集群。在Swarm集群中像原來那樣執(zhí)行Docker命令,現(xiàn)在這些命令被稱為swarm manager執(zhí)行。swarm集群中的機器可以是物理機或者虛擬機。這些機器加入swarm后,這些機器被稱為nodes

Swarm managers可以使用使用多種策略來運行容器,例如emptiest node--它使用容器填充利用率最低的機器?;蛘?code>global--它確保每臺機器只獲得指定容器的一個實例。你可以在Compose文件中指定swarm manager使用那種策略

到現(xiàn)在為止,我們一直在本地機器上使用單主機模式的Docker。但是Docker也能切換到swarm mode,這就是使用swarm的原因。啟用swarm mode使當前計算機成為swarm manager。 啟用后Docker就會運行你在管理的swarm上執(zhí)行的命令,而不僅僅是在當前機器上

啟動swarm

swarm集群由多個節(jié)點組成,這些節(jié)點可以是物理機也可以是虛擬機?;靖拍詈芎唵危哼\行docker swarm init啟用swarm模式同時使當前機器作為swarm manager,然后在其他機器上運行docker swarm join加入swarm作為worker節(jié)點。接下來我們使用VM快速創(chuàng)建2臺機器的swarm集群

創(chuàng)建集群

你需要一個創(chuàng)建VM的hypervisor,所以在機器上需要安裝Oracle VirtualBox

現(xiàn)在使用docker-machineVirtualBox創(chuàng)建幾個VM

docker-machine create --driver virtualbox myvm1
docker-machine create --driver virtualbox myvm2

列出VM獲取它們的IP

現(xiàn)在創(chuàng)建了2個VM,分別為myvm1myvm2

使用下面的命令列出VM獲取它們的IP

$ docker-machine ls

NAME    ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER     ERRORS
myvm1   -        virtualbox   Running   tcp://192.168.99.100:2376           v19.03.1
myvm2   -        virtualbox   Running   tcp://192.168.99.101:2376           v19.03.1

初始化Swarm和添加Nodes

第一臺機器充當manager,執(zhí)行管理命令和對wokers加入到swarm進行授權(quán),第二臺機器充當worker

你可以使用docker-machine ssh向VM發(fā)送命令。使用docker swarm init命令指定myvm1作為swarm manager。

$ docker-machine ssh myvm1 "docker swarm init --advertise-addr <myvm1 ip>:<port>"
Swarm initialized: current node <node ID> is now a manager.

To add a worker to this swarm, run the following command:

  docker swarm join \
  --token <token> \
  <myvm ip>:<port>

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

端口 2377和2376

docker warm initdocker swarm join盡量使用2377這個端口(swarm 管理端口),或者不指定端口將默認端口2377

docker-machine ls命令返回的機器IP中包含2376端口,這個端口是docker的后臺端口。不要使用這個端口,不然會有 報錯

docker swarm init命令執(zhí)行后的結(jié)果中可以看到添加node的docker swarm join命令格式。使用docker-machine ssh命令將docker swarm join命令發(fā)送給myvm2,讓myvm2作為worker加入到swarm

$ docker-machine ssh myvm2 "docker swarm join \
--token <token> \
<ip>:2377"

This node joined a swarm as a worker.

恭喜你,你已經(jīng)創(chuàng)建了你的第一個swarm集群

在manager上運行docker node ls查看swarm集群中的節(jié)點

$ docker-machine ssh myvm1 "docker node ls"

ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
brtu9urxwfd5j0zrmkubhpkbd     myvm2               Ready               Active
rihwohkh3ph38fhillhhb84sk *   myvm1               Ready               Active              Leader

離開swarm

如果你想重新開始,在每個節(jié)點上運行docker swarm leave

在swarm集群上部署應(yīng)用

最難的部分已經(jīng)完了?,F(xiàn)在你可以重復(fù)part 3的過程部署應(yīng)用到新的swarm集群上。注意只有swarm manager比如myvm1執(zhí)行docker命令。workers僅僅作為機器資源

配置swarm manager的docker-machine shell命令

目前為止,執(zhí)行命令都是以docker-machine ssh命令將命令發(fā)送到機器上執(zhí)行??梢允褂?code>docker-machine env <machine>命令配置你當前的shell命令和VM的Docker daemon通信。這個方法可以讓你使用本地的docker-compose.yml文件部署應(yīng)用程序到''遠程''機器,不用將這個文件拷來拷去

運行docker-machine env myvm1,然后命令結(jié)果運行的最后一行拷貝出來并運行,配置你當前的shell命令和swarm manager myvm1通信

Mac或Linux上配置docker-machine shell環(huán)境

運行docker-machine env myvm1得到配置與myvm1通信的命令

$ docker-machine env myvm1

export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.100:2376"
export DOCKER_CERT_PATH="/Users/sam/.docker/machine/machines/myvm1"
export DOCKER_MACHINE_NAME="myvm1"
# Run this command to configure your shell:
# eval $(docker-machine env myvm1)

運行這個命令

eval $(docker-machine env myvm1)

運行docker-machine ls驗證myvm1現(xiàn)在是激活的機器,myvm1被*標識

$ docker-machine ls

NAME    ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER     ERRORS
myvm1   *        virtualbox   Running   tcp://192.168.99.100:2376           v19.03.1
myvm2   -        virtualbox   Running   tcp://192.168.99.101:2376           v19.03.1

在swarm manager上部署應(yīng)用

現(xiàn)在你可以使用在part 3中使用的docker stack deploy命令和docker-compose.yml文件的備份來部署你的應(yīng)用。這個命令會花一些時間完成部署,并且需要一段時間才會可用。使用在swarm manager運行docker service ps <service_name>驗證所有服務(wù)重新部署

通過配置docker-machine shell環(huán)境與myvm1連接,你仍然可以訪問本地機器的文件。確保你在之前目錄下,目錄下有part 3中的docker-compose.yml文件

像之前那樣,在myvm1上運行下面的命令

docker stack deploy -c docker-compose.yml getstartedlab

就這樣,應(yīng)用已經(jīng)部署到了swarm集群

注意:如果你的鏡像不是在Docker Hub上,而是在私有倉庫,你需要使用docker login <your-registry>登陸,然后添加--with-registry-auth到上面的命令,比如:

docker login registry.example.com

docker stack deploy --with-registry-auth -c docker-compose.yml getstartedlab

上面的命令可以使swarm節(jié)點可以從你的私有倉庫中pull鏡像

現(xiàn)在你可以使用part 3中的命令。只不過這次服務(wù)分別部署到myvm1myvm2

  • 使用docker-machine envdocker-machain ssh連接到VM。如果想將將shell連接到myvm2,在當前shell或者新的shell中再次運行docker-machine env,然后再執(zhí)行docker-machine env命令后返回的命令。這條命令只是配置了當前shell。如果你重新開了一個shell窗口,需要重新運行命令進行配置。使用docker-machine ls列出機器,看看這些機器處于什么狀態(tài),ip地址,確認當前連接到的是哪臺機器

  • 另外,你可以用docker-machine ssh <machine> "<command>"命令來達到同樣的目的。這條命令運行的log日志直接打印到VM,不會在本地機器上訪問文件

  • 在MacOS和Linux上,你可以使用docker-machine scp <file> <machine>:~拷貝文件到機器上

訪問集群

你可以使用myvm1myvm2的IP地址來訪問你的應(yīng)用

創(chuàng)建網(wǎng)絡(luò)是共享的,同時實現(xiàn)了負載均衡。運行docker-machine ls獲取VM的IP地址,可以通過瀏覽器或curl訪問4000端口

訪問隨機得到的結(jié)果有5個不同的容器ID,體現(xiàn)了負載均衡

2個機器的IP都訪問,是因為在swarm節(jié)點加入到路由網(wǎng)格(routing mesh)中。這樣確保了在swarm中部署的service無論使用什么端口都得以保留,無論在哪個node上運行的容器都這樣。下面這個圖展示了一個名為my-web服務(wù)部署在擁有3個node的swarm中并對外暴露8080端口的結(jié)構(gòu)

routing mesh diagram

迭代和擴容應(yīng)用

從現(xiàn)在開始,你可以運行你在part 2和part 3中學(xué)到的命令

可以更改docker-compose.yml進行擴容

修改代碼,重新構(gòu)建鏡像,將鏡像推送到倉庫進行迭代

無論是擴容還是迭代,僅僅再次運行docker stack deploy就可以應(yīng)用這些改變

你可以使用docker swarm join命令將任何機器(物理機或虛擬機)加入到swarm中,集群就相當于擴容了。運行docker stack deploy,應(yīng)用就能使用這些資源重新部署

清理和重啟

stack和swarm

你可以使用docker stack rm命令停止stack,例如

docker stack rm getstartedlab

保留swarm還是移除它?

可以使用docker-machine ssh myvm2 "docker swarm leave"讓worker從swarm中移除,使用docker-machine ssh myvm1 "docker swarm leave --force"讓manager從swarm中移除,但是在part 5中還會使用到這個swarm,現(xiàn)在還是留著

取消docker-machine shell命令

你可以使用下面的命令來取消上面配置的docker-machine shell環(huán)境

Mac或Linux上使用

eval $(docker-machine env -u)

Windows上使用

& "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env -u | Invoke-Expression

重啟Docker machine

如果你把宿主機關(guān)機了,Docker machine將停止運行。可以使用docker-machine ls查看機器的運行狀態(tài)

$ docker-machine ls
NAME    ACTIVE   DRIVER       STATE     URL   SWARM   DOCKER    ERRORS
myvm1   -        virtualbox   Stopped                 Unknown
myvm2   -        virtualbox   Stopped                 Unknown

重啟可以使用

docker-machine start <machine-name>

比如

$ docker-machine start myvm1
Starting "myvm1"...
(myvm1) Check network to re-create if needed...
(myvm1) Waiting for an IP...
Machine "myvm1" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.

$ docker-machine start myvm2
Starting "myvm2"...
(myvm2) Check network to re-create if needed...
(myvm2) Waiting for an IP...
Machine "myvm2" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.

總結(jié)和小抄

在part 4中,你了解了swarm,在swarm中節(jié)點怎么成為manager或worker,怎么常見swarm并部署應(yīng)用到swarm。你可以看到,在part 3中的命令并沒有改變,這些命令只是在swarm的manager節(jié)點上運行。你也看到了docker中網(wǎng)絡(luò)的功能,能夠在容器之間進行負載均衡,即使容器運行在不同機器上。最后你知道了怎么在集群上迭代和擴容你的應(yīng)用。

這一節(jié)使用到的命令

docker-machine create --driver virtualbox myvm1 # Create a VM (Mac, Win7, Linux)
docker-machine create -d hyperv --hyperv-virtual-switch "myswitch" myvm1 # Win10
docker-machine env myvm1                # View basic information about your node
docker-machine ssh myvm1 "docker node ls"         # List the nodes in your swarm
docker-machine ssh myvm1 "docker node inspect <node ID>"        # Inspect a node
docker-machine ssh myvm1 "docker swarm join-token -q worker"   # View join token
docker-machine ssh myvm1   # Open an SSH session with the VM; type "exit" to end
docker node ls                # View nodes in swarm (while logged on to manager)
docker-machine ssh myvm2 "docker swarm leave"  # Make the worker leave the swarm
docker-machine ssh myvm1 "docker swarm leave -f" # Make master leave, kill swarm
docker-machine ls # list VMs, asterisk shows which VM this shell is talking to
docker-machine start myvm1            # Start a VM that is currently not running
docker-machine env myvm1      # show environment variables and command for myvm1
eval $(docker-machine env myvm1)         # Mac command to connect shell to myvm1
& "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env myvm1 | Invoke-Expression   # Windows command to connect shell to myvm1
docker stack deploy -c <file> <app>  # Deploy an app; command shell must be set to talk to manager (myvm1), uses local Compose file
docker-machine scp docker-compose.yml myvm1:~ # Copy file to node's home dir (only required if you use ssh to connect to manager and deploy the app)
docker-machine ssh myvm1 "docker stack deploy -c <file> <app>"   # Deploy an app using ssh (you must have first copied the Compose file to myvm1)
eval $(docker-machine env -u)     # Disconnect shell from VMs, use native docker
docker-machine stop $(docker-machine ls -q)               # Stop all running VMs
docker-machine rm $(docker-machine ls -q) # Delete all VMs and their disk images

Part 5: Stack

前提條件

  • 安裝版本1.13以上的docker
  • 安裝Docker Compose
  • 安裝Docker Machine,Mac OS版和Windows版的Docker已經(jīng)預(yù)裝了。在Linux上需要安裝
  • 學(xué)習完成part 1
  • 學(xué)習完成part 2
  • 確保Part 2中推向遠程倉庫的鏡像能正常運行,這一節(jié)我們將會使用這個鏡像
  • 一份part 3中的docker-compose.yml文件的備份
  • 確保part 4中國創(chuàng)建的機器正常運行。運行docker-machine ls驗證。如果機器停止了,運行docker-machine start myvm1啟用manager,docker-machine start myvm2啟動worker
  • 確保part 4中swarm正常運行。運行docker-machine ssh myvm1 "docker node ls"命令驗證。如果swarm正常運行,節(jié)點應(yīng)該是ready狀態(tài),如果不是,重新初始化swarm

簡介

在part 4中,你已經(jīng)學(xué)會了啟用swarm集群并且部署應(yīng)用在上面

在part 5這部分,你將接觸到分布式應(yīng)用的最高層:stack。stack就是一組相關(guān)聯(lián)、共享依賴,能同時擴容的services,一個stack就能實現(xiàn)整個應(yīng)用(盡管復(fù)雜的應(yīng)用需要使用多個stack)

好消息是,當你在part 3中創(chuàng)建compose文件并且使用docker stack deploy時,就已經(jīng)使用過stack了。但是這只是單個service的的stack運行在單個host上,但生產(chǎn)環(huán)境并不會這么使用。那么現(xiàn)在你將學(xué)習多個相關(guān)聯(lián)的services部署在多臺機器上

添加一個新service并重新部署

docker-compose.yml中添加服務(wù)很簡單。首先我們先添加一個免費的可視化服務(wù),這個可視化服務(wù)可以幫組我們看到swarm怎么調(diào)度容器

  1. 使用下面的內(nèi)容替換原來的docker-compose.yml文件,注意將username/repo:tag替換成你自己的鏡像

    version: "3"
    services:
      web:
        # replace username/repo:tag with your name and image details
        image: username/repo:tag
        deploy:
          replicas: 5
          restart_policy:
            condition: on-failure
          resources:
            limits:
              cpus: "0.1"
              memory: 50M
        ports:
          - "80:80"
        networks:
          - webnet
      visualizer:
        image: dockersamples/visualizer:stable
        ports:
          - "8080:8080"
        volumes:
          - "/var/run/docker.sock:/var/run/docker.sock"
        deploy:
          placement:
            constraints: [node.role == manager]
        networks:
          - webnet
    networks:
      webnet:
    

    唯一的改變就是添加了一個名為visualizer的service。注意這里添加了2個新的概念,volumns允許visualizer能夠訪問宿主機docker的socket文件;placement確保visualizer只運行在swarm manager,而不是在worker。

  2. 確保你的shell配置成連接到myvm1

    • 運行docker-machine ls列出機器確保shell已經(jīng)配置連接到myvm1,如果配置成功,可以在myvm1看到*標識

    • 如果可能的話,重新運行docker-machine env myvm1,然后運行下列命令配置

      在MacOS或Linux上

      eval $(docker-machine env myvm1)
      

      在Windows上

      & "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env myvm1 | Invoke-Expression
      
  3. 在manager上重新運行docker stack deploy命令

    $ docker stack deploy -c docker-compose.yml getstartedlab
    Updating service getstartedlab_web (id: angi1bf5e4to03qu9f93trnxm)
    Creating service getstartedlab_visualizer (id: l9mnwkeq2jiononb5ihz9u7a4)
    
  4. 看一眼visualizer

    你可以看到,在compose文件中visualizer運行在8080端口。通過docker-machine ls命令得到的IP地址來訪問

Visualizer screenshot

可以看到單個visualizer運行在manager上,5個web實例分別在swarm各個機器上運行。你能通過docker stack ps <stack>來確認:

docker stack ps getstartedlab

持久化數(shù)據(jù)

接下來我們添加一個redis數(shù)據(jù)出來存儲應(yīng)用數(shù)據(jù)

  1. 保存新的docker-machine.yml文件。只是在前面的基礎(chǔ)上添加了Redis service

    version: "3"
    services:
      web:
        # replace username/repo:tag with your name and image details
        image: username/repo:tag
        deploy:
          replicas: 5
          restart_policy:
            condition: on-failure
          resources:
            limits:
              cpus: "0.1"
              memory: 50M
        ports:
          - "80:80"
        networks:
          - webnet
      visualizer:
        image: dockersamples/visualizer:stable
        ports:
          - "8080:8080"
        volumes:
          - "/var/run/docker.sock:/var/run/docker.sock"
        deploy:
          placement:
            constraints: [node.role == manager]
        networks:
          - webnet
      redis:
        image: redis
        ports:
          - "6379:6379"
        volumes:
          - "/home/docker/data:/data"
        deploy:
          placement:
            constraints: [node.role == manager]
        command: redis-server --appendonly yes
        networks:
          - webnet
    networks:
      webnet:
    

    Redis配置使用6379端口,在compose文件中,將6379端口從宿主機暴露,所以你可以通過訪問Redis。

    最重要的是,在部署之前,有幾件事關(guān)于redis持久化的事需要說明

    • redis運行在manager
    • redis存儲數(shù)據(jù)的目錄映射到了宿主機的/data目錄

    這樣,redis數(shù)據(jù)就存儲在了宿主機上,而不是存儲在容器內(nèi)的/data目錄,容器中的目錄在容器重新部署時數(shù)據(jù)會被清除掉

    要做到數(shù)據(jù)持久化,必須做到:

    • 限制redis service必須運行在相同的宿主機上
    • 容器內(nèi)的數(shù)據(jù)目錄映射到了宿主機的文件系統(tǒng)上

    現(xiàn)在可以將添加了redis service的stack重新部署

  2. 在manager上創(chuàng)建./data目錄

    docker-machine ssh myvm1 "mkdir ./data"
    
  3. 確保shell配置成連接到myvm1

  4. 再次運行docker stack deploy重新部署

    $ docker stack deploy -c docker-compose.yml getstartedlab
    
  5. 運行docker service ls驗證3個服務(wù)是否如期運行

    $ docker service ls
    ID                  NAME                       MODE                REPLICAS            IMAGE                             PORTS
    x7uij6xb4foj        getstartedlab_redis        replicated          1/1                 redis:latest                      *:6379->6379/tcp
    n5rvhm52ykq7        getstartedlab_visualizer   replicated          1/1                 dockersamples/visualizer:stable   *:8080->8080/tcp
    mifd433bti1d        getstartedlab_web          replicated          5/5                 gordon/getstarted:latest    *:80->80/tcp
    
  6. 在web頁面上訪問應(yīng)用,你看到存儲在redis中的數(shù)據(jù)

Hello World in browser with Redis

同樣,檢查visualizer是否在8080端口正常運行,同時redis、webvisualizer3個服務(wù)正常運行

Visualizer with redis screenshot

歡迎關(guān)注我的公眾號

我的公眾號
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容