Docker快速入門

part 1: 目標與快速入門

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

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

Docker 中的概念

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

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

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

鏡像和容器

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

容器是一個鏡像的運行實例∫剩可以通過docker ps查看運行中的容器

容器和虛擬機

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

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

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ù)部署無縫銜接,比如:

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

Part 2: 容器

前提條件

  • 安裝版本1.13以上的docker

  • 完成Part 1部分的學習

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

    $ docker run hello-world
    

簡介

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

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

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

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

使用Docker吉捶,您可以使用一個可移植的Python環(huán)境作為鏡像夺鲜,無需安裝。 然后呐舔,你可以將基礎(chǔ)鏡像币励,應用程序代碼,依賴項珊拼,運行時一起打包構(gòu)建食呻。

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

使用Dockerfile定義容器

Dockerfile定義容器內(nèi)環(huán)境中發(fā)生的事情澎现。 對網(wǎng)絡(luò)接口和磁盤驅(qū)動器等資源的訪問在此環(huán)境中進行虛擬化仅胞,該環(huán)境與系統(tǒng)的其他部分隔離,因此您需要將端口映射到外部世界剑辫,并具體說明要“復制”到哪些文件到這個環(huán)境干旧。此Dockerfile中定義的應用程序的構(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)建這些文件闹击。

應用本身

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庫成艘,應用程序打印了環(huán)境變量NAMEsocket.gethostname()赏半,最后,由于Redis并沒有運行淆两,這里應該會打印錯誤信息断箫。

在容器內(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)建應用

準備構(gòu)建這個應用。在此之前暂刘,請先確保你在剛才建立的目錄下饺谬,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語法應該像這個樣子--tag=friendlyhello:v0.0.1

運行應用程序

運行應用程序森缠,使用-p將機器的4000端口映射到容器的80端口

docker run -p 4000:80 friendlyhello

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

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

應用運行顯示內(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停止運行。

在后臺運行應用程序爱谁,使用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直接在你的機器上運行你的應用程序钱烟。

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)在直接從遠程倉庫運行應用程序試試曙博。

$ 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定義的依賴和你的應用程序代碼都會一并打包。你不需要在你機器上安裝各種環(huán)境惠窄。

Part 2結(jié)論

這部分內(nèi)容到這就結(jié)束了蒸眠,下一節(jié)我們將學習擴容我們應用,我們將以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)預裝了楞卡。在Linux上,你需要安裝
  • 學習完P(guān)art 1
  • 學習完P(guān)art 2
  • 確保Part 2中推向遠程倉庫的鏡像能正常運行脾歇,這一節(jié)我們將會使用這個鏡像

簡介

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

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

關(guān)于services

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

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

第一個docker-compose.yml文件

docker-compose.yml文件是一個YAML文件呐芥,它定義了Docker容器應該怎么運行逻杖。

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ò))

運行新的負載均衡的應用

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

docker swarm init

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

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

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

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

查看我們應用程序webservice的service ID

$ docker service ls

查看上面這條命令的輸出诞帐,以應用名字為前綴欣尼。如果你把應用命名同上面一樣,那么這里顯示的名字就是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來響應。使用round-robin的方式進行響應鞭执。容器ID和docker container ls -q中的容器ID對應

擴容你的應用

你可以通過改變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,運行更多的容器

停止應用和swarm

  • 使用docker stack rm命令停止應用

    docker stack rm getstartedlab
    
  • 停止swarm

    docker swarm leave --force
    

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

總結(jié)和小抄

回顧一下朦拖,當運行docker run很簡單,在生產(chǎn)環(huán)境中真正的實現(xiàn)是將容器當作service來運行厌衔。在Compose文件中璧帝,Services定義了容器的行為,這個文件能用來擴容葵诈,限制資源和重新部署應用裸弦。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)預裝了。在Linux上需要安裝
  • 學習完成part 1
  • 學習完成part 2
  • 確保Part 2中推向遠程倉庫的鏡像能正常運行晕城,這一節(jié)我們將會使用這個鏡像
  • 一份part 3中的docker-compose.yml文件的備份

簡介

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

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

理解Swarm集群

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

Swarm managers可以使用使用多種策略來運行容器,例如emptiest node--它使用容器填充利用率最低的機器压鉴⊙伦桑或者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集群上部署應用

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

配置swarm manager的docker-machine shell命令

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

運行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上部署應用

現(xiàn)在你可以使用在part 3中使用的docker stack deploy命令和docker-compose.yml文件的備份來部署你的應用缕探。這個命令會花一些時間完成部署魂莫,并且需要一段時間才會可用。使用在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

就這樣倦始,應用已經(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地址來訪問你的應用

創(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

迭代和擴容應用

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

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

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

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

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

清理和重啟

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并部署應用到swarm考润。你可以看到,在part 3中的命令并沒有改變读处,這些命令只是在swarm的manager節(jié)點上運行糊治。你也看到了docker中網(wǎng)絡(luò)的功能,能夠在容器之間進行負載均衡罚舱,即使容器運行在不同機器上井辜。最后你知道了怎么在集群上迭代和擴容你的應用。

這一節(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)預裝了粥脚。在Linux上需要安裝
  • 學習完成part 1
  • 學習完成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é)點應該是ready狀態(tài)天通,如果不是,重新初始化swarm

簡介

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

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

好消息是祭芦,當你在part 3中創(chuàng)建compose文件并且使用docker stack deploy時筷笨,就已經(jīng)使用過stack了。但是這只是單個service的的stack運行在單個host上,但生產(chǎn)環(huán)境并不會這么使用奥秆。那么現(xiàn)在你將學習多個相關(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ù)出來存儲應用數(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頁面上訪問應用或杠,你看到存儲在redis中的數(shù)據(jù)

Hello World in browser with Redis

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

Visualizer with redis screenshot

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

我的公眾號
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末认境,一起剝皮案震驚了整個濱河市胚委,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌叉信,老刑警劉巖亩冬,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡硅急,警方通過查閱死者的電腦和手機覆享,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來营袜,“玉大人撒顿,你說我怎么就攤上這事〖园澹” “怎么了凤壁?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長跪另。 經(jīng)常有香客問我拧抖,道長,這世上最難降的妖魔是什么免绿? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任唧席,我火速辦了婚禮,結(jié)果婚禮上嘲驾,老公的妹妹穿的比我還像新娘袱吆。我一直安慰自己,他們只是感情好距淫,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布绞绒。 她就那樣靜靜地躺著,像睡著了一般榕暇。 火紅的嫁衣襯著肌膚如雪蓬衡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天彤枢,我揣著相機與錄音狰晚,去河邊找鬼。 笑死缴啡,一個胖子當著我的面吹牛壁晒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播业栅,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼秒咐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了碘裕?” 一聲冷哼從身側(cè)響起携取,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎帮孔,沒想到半個月后雷滋,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年晤斩,在試婚紗的時候發(fā)現(xiàn)自己被綠了焕檬。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡澳泵,死狀恐怖实愚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情烹俗,我是刑警寧澤爆侣,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站幢妄,受9級特大地震影響兔仰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蕉鸳,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一乎赴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧潮尝,春花似錦榕吼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至乱凿,卻和暖如春顽素,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背徒蟆。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工胁出, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人段审。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓全蝶,卻偏偏與公主長得像,于是被迫代替她去往敵國和親寺枉。 傳聞我的和親對象是個殘疾皇子抑淫,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容