上一篇 / 目录 / 下一篇
英文原文在这里:https://docs.docker.com/get-started/
Part 1: Docker环境设置
参考Docker安装指南或快速入门手册来安装Docker Desktop。
安装成功后,使用下面的命令来验证Docker的运行状态:
docker --version
docker info 或 docker version 可以查看更加详细的信息:
docker info
docker version
通过下面的命令可以测试一下你的docker安装正确与否:
docker run hello-world
它会下载一个简单的docker镜像,并启动一个容器运行这个镜像。
使用docker image来查看本地的镜像:
docker image ls
使用docker container命令查看本地的容器。例如下面的命令会返回所有正在运行和已经停止的容器:
docker container ls --all
小结
通过Docker,你可以很轻量级的扩展你的程序。而且通过docker镜像发布程序意味着程序的安装将不再需要任何依赖组件(除了Docker Engine)。下面列出了本章节使用到的所有命令,供大家参考。
## 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 2: 容器
当你按照上述步骤确认了Docker的运行环境正常之后,你可以着手创建自己的容器镜像了。首先创建一个新的目录:
mkdir my-first-container
cd my-first-container
Dockerfile
在此目录中新建一个文本文件,命名为Dockerfile
。文件内容如下:
# Use an official Python runtime as a parent image
FROM python:2.7-slim
# Set the working directory to /app
WORKDIR /app
# Copy the current directory contents into the container at /app
COPY . /app
# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt
# Make port 80 available to the world outside this container
EXPOSE 80
# Define environment variable
ENV NAME World
# Run app.py when the container launches
CMD ["python", "app.py"]
Dockerfile 的作用是告诉Docker,按照一定的步骤来构建打包一个镜像。在上述例子中,Docker会依次执行以下步骤来生成新的镜像:首先下载一个名为python:2.7-slim的镜像作为模板,拷贝当前目录下的文件到镜像的/app目录,运行一个pip install命令,对外开放80端口,设置环境变量NAME=World,最后运行一个python程序。
The Python application
Dockerfile 引用了2个文件: requirements.txt 和 app.py. 它们是pip指令和python程序所需的源代码。我们在同一目录下创建这两个文件。
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 = "cannot connect to Redis, counter disabled"
html = "Hello {name}!
" \
"Hostname: {hostname}
" \
"Visits: {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)
这段代码的逻辑很简单,程序会启动一个web service,监听端口80。返回的html中包含环境变量"NAME"的值(默认为world),以及socket.gethostname()的值(为当前容器的ID)。另外,由于容器中并没有运行Redis,因此程序会打印出错误消息:cannot connect to Redis, counter disabled
编译打包
创建容器镜像的所有文件都准备好了,下面就来编译打包。此时在当前目录中你应该有三个文件:Dockerfile, app.py, requirements.txt。
运行下面的命令来打包生成镜像:
docker build --tag=friendlyhello .
提示:不要忘记命令最末尾的小数点,它表示当前目录。
生成的镜像会保存在本地的Docker镜像注册表中(docker image registry)。运行下面的命令查看所有的本地镜像。
docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
friendlyhello latest 17334977b537 13 seconds ago 131MB
在上面的例子中,--tag参数没有指明具体的版本号,因此打包的镜像TAG列默认为latest。如果要指定具体的版本号,可以使用 --tag=friendlyhello:v0.0.1
。
运行容器
使用命令 docker run来运行一个容器:
docker run -p 4000:80 friendlyhello
参数 -p 4000:80
表明将你的实体机端口4000映射到容器的端口80,因此你可以使用http://localhost:4000
来访问容器中的web service。这个命令会在当前命令行窗口中运行容器,且命令不会返回,直到容器退出。如果要在后台运行容器,请使用参数 -d
开启 detached模式:
docker run -d -p 4000:80 friendlyhello
下面的截图演示了foreground运行和background运行的区别:
使用curl或浏览器来测试这个程序:
curl http://localhost:4000
Hello World!
Hostname: 6be4e1853e71
Visits: cannot connect to Redis, counter disabled
停止容器
在容器正在运行的命令行窗口中,点击CTRL+C会退出这个python 程序,但是Windows系统比较特殊,该操作不会停止容器。正确的做法是使用命令docker container stop来停止一个运行的容器。方法是,先执行 docker container ls 找到正在运行的容器ID。
docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6be4e1853e71 friendlyhello "python app.py" 7 minutes ago Up 7 minutes 0.0.0.0:4000->80/tcp infallible_morse
然后执行 docker container stop
:
docker container stop 6be4e1853e71
发布你的docker镜像
镜像可以发布到Docker公开的镜像仓库(docker hub registry)中,这样任何人都可以在任何机器上下载并运行你的镜像。当然,你也可以把镜像发布到其他第三方维护的Docker注册表,甚至于你可以创建公司内部的私有注册表,不过这不在本指南的讨论范围内。
首先需要登录Docker ID。执行命令 docker login
,并按提示输入用户名和密码。
然后给你的镜像设置一个标签。标签是对镜像的唯一标识。完整的标签格式是:
其中,
docker tag friendlyhello feiandytan/get-started:part2
上述命令为镜像friendlyhello创建了一个新的标签,表明此镜像将上传到我的id feiandytan
下的仓库 get-started
中,并且将其version记为part2
。
最后一步就是发布:
docker push
一旦发布成功,你就可以在任意一台安装了Docker的电脑上运行该容器。方法是执行下面的命令:
docker run -p 4000:80
小结
下面列出本章用到的命令,供大家参考:
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 # Gracefully stop the specified container
docker container kill # Force shutdown of the specified container
docker container rm # 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 # 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 username/repository:tag # Tag 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)
先来看几个概念。
Service:当我们搭建分布式系统时,我们常常希望某一个程序可以同时运行多个副本,它们全部处在一个负载均衡器的后面。在Docker中,这种将一个镜像启动并运行在多个容器副本中的集群,就称为一个服务。描述一个Docker 服务需要指明以下内容:这个服务运行的是哪一个镜像?需要同时运行多少个容器副本?每个容器最大占用多少CPU和内存?是否需要负载均衡等等。这些描述信息都记录在docker-compose.yml文件中。
Task: 每一个服务都会运行若干个docker 容器。一个容器就称为这个服务的一个任务。例如,如果一个服务同时运行了5个容器,我们就说这个服务包含5个任务。
docker-compose.yml
我们在任意一个目录中新建文本文件 docker-compose.yml。内容如下:
version: "3"
services:
web:
image: /get-started:part2
deploy:
replicas: 5
resources:
limits:
cpus: "0.1"
memory: 50M
restart_policy:
condition: on-failure
ports:
- "4000:80"
networks:
- webnet
networks:
webnet:
提示:
上述配置表明:
- 服务加载的镜像是
/get-started:part2 - 启动5个容器实例来组成一个服务。服务的名称为"web"。
- 每个容器最多使用一个CPU内核的10%,以及50MB内存。
- 容器在失败状态下自动重启。
- 映射实体机端口4000到容器的端口80。
- 服务使用的网络名为"webnet",并且定义了"webnet"网络为默认配置。
部署运行服务
接下来执行命令(关于swarm会在后面介绍):
docker swarm init
使用docker stack deploy来运行这个stack:
docker stack deploy -c docker-compose.yml getstartedlab
上面的命令将读取服务描述文件docker-compose.yml
来部署一个stack,并命名该stack为getstartedlab。
可以访问http://localhost:4000 来观察返回的hostname。每次的结果都不同,说明负载均衡器已经生效。
提示:默认的负载均衡策略是依次循环访问各个容器。
查看服务的状态
使用下面的命令可以查看当前电脑上运行的所有服务:
docker service ls
例如:
C:\Users\i062893\OneDrive\code\docker-workspace\my-first-container>docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
ypyx4ed2uzur getstartedlab_web replicated 0/10 feiandytan/get-started:part2 *:4000->80/tcp
执行命令docker stack services
查看某个stack的所有服务。例如:
C:\Users\i062893\OneDrive\code\docker-workspace\my-first-container>docker stack services getstartedlab
ID NAME MODE REPLICAS IMAGE PORTS
ypyx4ed2uzur getstartedlab_web replicated 10/10 feiandytan/get-started:part2 *:4000->80/tcp
注意上面服务的命名规则:服务的全称"getstartedlab_web"是由
使用下面的命令可以查看某个服务包含哪些任务:
docker service ps getstartedlab_web
使用下面的命令查看某个stack包含哪些任务:
docker stack ps getstartedlab
增加任务数
通过修改文件docker-compose.yml 中的replicas参数,可以很容易的扩展你的服务任务数量。只需要重新运行下面的命令即可:
docker stack deploy -c docker-compose.yml getstartedlab
删除stack和swarm
使用下面的命令删除stack和swarm:
docker stack rm getstartedlab
docker swarm leave --force
小结
下面列出本章使用到的docker命令,供大家参考:
docker swarm init # Init this machine as a swarm manager
docker stack ls # List stacks or apps
docker stack deploy -c # Run the specified Compose file
docker service ls # List running services associated with an app
docker service ps # List tasks associated with an app
docker inspect # Inspect task or container
docker container ls -q # List container IDs
docker stack rm # Tear down an application
docker swarm leave --force # Take down a single node swarm from the manager
Part 4: 蜂窝 (Swarms)
在之前的指南中,已经接触过swarm命令了。Docker可以将多台电脑组合成一个蜂窝集群网络,每一个节点的计算机都可以部署和运行容器,共同来完成分布式计算的任务。Part 3演示了一个仅包含单个节点的蜂窝集群,在其中部署了一个名称为getstartedlab的服务。接下来就演示一下如何将两台电脑连接成一个蜂窝集群。
为了便于理解,首先需要解释一下几个概念,以及蜂窝集群的工作原理。
蜂窝的概念和原理
Swarm: 一个蜂窝是一组计算机,它们都运行了Docker Engine并且相互连接组成一个集群。显然,一个蜂窝可以包含多台计算机,而一台计算机只能加入一个蜂窝集群。
Swarm manager: 蜂窝经理是Swarm集群中一类特殊的计算机,它们负责执行Docker命令行的命令以及按照一定的策略在各个节点上管理容器。
Swarm workers: 蜂窝工人是Swarm集群中的另一类计算机,它们受经理的管理,只负责运行容器,而不能执行Docker命令行的命令。
node: 蜂窝集群中的每一个计算机 (经理或工人)都称为一个节点。
-
Ingress routing mesh: 蜂窝利用一种称为Ingress routing mesh的机制来实现负载均衡,其原理如下图所示:
在每一个节点上都运行了一个负载均衡器(swarm load balancer),它负责把网络请求分发到各个节点运行的容器中。由上图可以看出,蜂窝集群是一个很复杂的网状结构,每个节点的负载均衡器都与所有节点中的容器相连接。
创建集群
下面以Win10操作系统为例,创建2个虚拟机并将它们组合成一个蜂窝集群。
打开 Hyper-V Manager, 点击右侧的菜单"Virtual Switch Manager…":
新建一个External类型的virtual switch,取名为"myswitch",勾选"Allow management operating system to share this network adapter"。
当创建了myswitch虚拟网络交换配置后,虚拟机就可以访问外部网络了。
下面的docker-machine命令可以创建两个虚拟机。
提示:从现在开始,所有的docker-machine命令请在CMD管理员模式下运行。
docker-machine create -d hyperv --hyperv-virtual-switch "myswitch" myvm1
docker-machine create -d hyperv --hyperv-virtual-switch "myswitch" myvm2
使用docker-machine ls
命令查看虚拟机列表。你可以从列表中看到虚拟机的IP地址和状态,例如:
C:\Users\i062893\OneDrive\code\docker-workspace\my-first-container>docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
myvm1 - hyperv Running tcp://10.58.181.134:2376 v18.09.7
myvm2 - hyperv Running tcp://10.58.180.164:2376 v18.09.7
我们打算让myvm1作为蜂窝集群的经理,因此在myvm1中执行docker swarm init
命令。方法如下:
C:\Users\i062893\OneDrive\code\docker-workspace\my-first-container>docker-machine ssh myvm1 "docker swarm init --advertise-addr 10.58.181.134"
Swarm initialized: current node (64ve59yqsdgvcpsphbn59et5v) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-2zpjxx9ie1a8g8kadizxhy0pygx5sb1lrpjp5wqlu7qxqg2lo6-5h5zw6h0dvq6gf51tly19y9uj 10.58.181.134:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
上述命令将引号中的指令通过ssh连接发送到myvm1虚拟机上并执行。从响应消息中可以看到一个docker swarm join
指令,将它拷贝出来,在myvm2上执行,就可以把第二个虚拟机加入同一个蜂窝集群。也可以使用docker swarm join-token worker
再次查看具体的docker swarm join 指令,例如:
C:\Users\i062893\OneDrive\code\docker-workspace\my-first-container>docker-machine ssh myvm1 "docker swarm join-token worker"
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-3ych7gmhb6uwven0nn4fo0ft8oe5857vitnlzztofvwia307pn-2vlvn2dng0lr5m87mozo4d5vt 10.59.173.123:2377
我们接着把myvm2加入蜂窝集群:
C:\Users\i062893\OneDrive\code\docker-workspace\my-first-container>docker-machine ssh myvm2 "docker swarm join --token SWMTKN-1-2zpjxx9ie1a8g8kadizxhy0pygx5sb1lrpjp5wqlu7qxqg2lo6-5h5zw6h0dvq6gf51tly19y9uj 10.58.181.134:2377"
This node joined a swarm as a worker.
之后可以使用docker node ls
查看蜂窝中的所有节点信息:
C:\Users\i062893\OneDrive\code\docker-workspace\my-first-container>docker-machine ssh myvm1 "docker node ls"
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
64ve59yqsdgvcpsphbn59et5v * myvm1 Ready Active Leader 18.09.7
15dve4fu9wuazzqedtvg40lfe myvm2 Ready Active 18.09.7
此时,我们已经组建了一个蜂窝集群,包含了两个节点。一个是经理 (myvm1),另一个是工人 (myvm2)。
在蜂窝集群中部署程序
为了方便演示,我们可以把当前的shell窗口直接连到某一个虚拟机上,方法如下:
运行docker-machine env myvm1
,例如:
C:\Users\i062893\OneDrive\code\docker-workspace\my-first-container>docker-machine env myvm1
SET DOCKER_TLS_VERIFY=1
SET DOCKER_HOST=tcp://10.58.181.134:2376
SET DOCKER_CERT_PATH=C:\Users\i062893\.docker\machine\machines\myvm1
SET DOCKER_MACHINE_NAME=myvm1
SET COMPOSE_CONVERT_WINDOWS_PATHS=true
REM Run this command to configure your shell:
REM @FOR /f "tokens=*" %i IN ('docker-machine env myvm1') DO @%i
提示:如果你的Docker配置了代理,那么需要执行命令: docker-machine env --no-proxy myvm1
否则,你会在接下来的运行中遇到Forbidden的错误。
按照响应消息中的提示,再运行最后一行的代码即可:
C:\Users\i062893\OneDrive\code\docker-workspace\my-first-container>@FOR /f "tokens=*" %i IN ('docker-machine env myvm1') DO @%i
这样,当前shell窗口就和myvm1虚拟机建立了连接。所有后续的命令都会直接在myvm1虚拟机上运行。通过查看虚拟机列表,也可以发现myvm1处于ACTIVE状态 (ACTIVE列显示了一个星号):
C:\Users\i062893\OneDrive\code\docker-workspace\my-first-container>docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
myvm1 * hyperv Running tcp://10.58.181.134:2376 v18.09.7
myvm2 - hyperv Running tcp://10.58.180.164:2376 v18.09.7
使用Part 3 指南中相同的命令来部署一个服务:
C:\Users\i062893\OneDrive\code\docker-workspace\my-first-container>docker stack deploy -c docker-compose.yml getstartedlab
Creating network getstartedlab_webnet
Creating service getstartedlab_web
这个服务包含5个任务,它们会随机的分布在两个虚拟机中。使用docker stack ps getstartedlab
可以查看这些任务的详情。例如,下面的列表显示,1, 3, 5号任务运行在myvm2节点上,而2, 4号任务运行在myvm1节点上。
C:\Users\i062893\OneDrive\code\docker-workspace\my-first-container>docker stack ps getstartedlab
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
3nky30x2zeig getstartedlab_web.1 feiandytan/get-started:part2 myvm2 Running Running less than a second ago
o6vtrdz6dlvb getstartedlab_web.2 feiandytan/get-started:part2 myvm1 Running Running less than a second ago
58xgzjldd6jk getstartedlab_web.3 feiandytan/get-started:part2 myvm2 Running Running less than a second ago
uywciema025m getstartedlab_web.4 feiandytan/get-started:part2 myvm1 Running Running less than a second ago
xfmjvv0jgvly getstartedlab_web.5 feiandytan/get-started:part2 myvm2 Running Running less than a second ago
测试的方式和之前一样,使用curl http://10.58.181.134:4000
或 curl http://10.58.180.164:4000
来访问我们的服务。这里使用的是myvm1或myvm2的IP地址。还记得之前介绍的Ingress routing mesh 机制吗?正是利用了这个机制,使得Docker蜂窝集群的任何一个节点,都可以作为外部web service的访问入口。
清理stack
使用下面的命令删除一个stack:
docker stack rm getstartedlab
使用下面的命令移除一个蜂窝节点:
docker-machine ssh myvm2 "docker swarm leave"
docker-machine ssh myvm1 "docker swarm leave --force"
重启虚拟机
使用docker-machine stop
来停止一个虚拟机:
docker-machine stop myvm1
使用docker-machine start
启动一个虚拟机:
docker-machine start myvm1
使用docker-machine restart
重启虚拟机:
docker-machine restart myvm1
重新生成证书
通常当实体机的网络发生变化时,虚拟机的IP地址也会变化。此时原始的TLS证书就不能使用了。当执行docker-machine ls
查看虚拟机状态时,会看到错误提示:Unable to query docker version: Get https://192.168.31.72:2376/v1.15/version: x509: certificate is valid for 10.59.162.174, not 192.168.31.72
解决方法是运行下面的命令重新生成一个虚拟机的证书:
docker-machine regenerate-certs myvm1
小结
下面列出本章中用到的命令,供大家参考:
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 " # 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 # 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 " # 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: Stacks
在Part 5 指南中,我们一起来了解一下栈的概念。在Docker的世界中,你可以把一组相互关联,共同完成某个程序功能的服务组合成一个栈。在之前的文章中,我们已经使用过栈了:使用docker-compose.yml
文件来定义栈,使用docker stack deploy
命令来部署一个栈。由此可知,栈是Docker中部署(deploy)的最小单元。即使你的程序只有一个服务,你也必须把它包裹在一个栈中,比如Part 4的示例程序就是一个仅包含一个服务的栈。
在进行下面的练习之前,先确保你的蜂窝集群状态正常。
把当前的shell连接到myvm1, 并运行docker node ls
:
C:\Users\i062893\OneDrive\code\docker-workspace\my-first-container>docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
uneyxvztmsxahbilzoneq76tu * myvm1 Ready Active Leader 18.09.7
gnove3cdyjxfpchn99vc3ff5j myvm2 Ready Active 18.09.7
确保每个节点的状态都是Ready。否则请参考Part 4搭建蜂窝集群。
增加一个visualizer服务
接下来,我们在之前的getstartedlab的基础上,新增加一个服务。修改docker-compose.yml文件如下:
version: "3"
services:
web:
image: /get-started:part2
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”。它使用了Docker提供的一个标准的镜像:dockersamples/visualizer:stable。这个服务可以在浏览器中显示当前蜂窝集群各个节点的状态。ports
属性之前已经介绍过了,即把实体机的端口8080映射到容器的端口8080。volumes
属性则是映射磁盘文件,即把实体机的文件"/var/run/docker.sock"映射到容器的文件"/var/run/docker.sock"。而deploy.placement.constraints
属性,则意味着该visualizer服务仅能部署到蜂窝经理节点上,即myvm1虚拟机。
运行docker stack deploy
来部署新的栈:
docker stack deploy -c docker-compose.yml getstartedlab
部署成功后,我们就可以在浏览器中查看visualizer:
再增加一个redis服务
我们重复一遍上述步骤,再新增一个redis服务。在最开始Part 1的python程序中,我们使用到了redis,用来记录当前网站的访问次数。当时由于我们的程序没有包含redis服务,所以返回错误消息。接下来,把redis服务加到docker-compose.yml文件中:
version: "3"
services:
web:
image: /get-started:part2
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服务使用的镜像就是"redis"。并且,redis也和visualizer一样,只运行在经理节点上。
请注意volumes
属性,它表明redis服务需要将实体机的文件"/home/docker/data"映射到容器的文件"/data"。因此在部署这个栈之前,我们先在myvm1虚拟机上创建子目录/home/docker/data
。方法是运行下面的命令:
docker-machine ssh myvm1 "mkdir ./data"
再次运行docker stack deploy来部署新的栈
docker stack deploy -c docker-compose.yml getstartedlab
成功部署后,在myvm1节点上运行docker service ls
查看一下3个服务的状态:
docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
xgd8p4k7x5ig getstartedlab_redis replicated 1/1 redis:latest *:6379->6379/tcp
t2fhws0yxz49 getstartedlab_visualizer replicated 1/1 dockersamples/visualizer:stable *:8080->8080/tcp
z0wttomwgrbt getstartedlab_web replicated 5/5 feiandytan/get-started:part2 *:80->80/tcp
使用curl 来看看网站的访问计数器:
C:\code\docker-workspace\part5-1>curl http://10.59.173.123
Hello World!
Hostname: 2944f07a164d
Visits: 1
C:\code\docker-workspace\part5-1>curl http://10.59.173.123
Hello World!
Hostname: b1b2c6a4fc33
Visits: 2
C:\code\docker-workspace\part5-1>curl http://10.59.173.123
Hello World!
Hostname: ce4344324343
Visits: 3
C:\code\docker-workspace\part5-1>curl http://10.59.173.123
Hello World!
Hostname: aaf34aec3fa4
Visits: 4
最后看一下Visualizer返回的节点状态:
至此,我们已经搭建了一个docker集群,并部署了一个容器化的程序。该程序包含1个栈 (3个服务)。其中redis服务和visualizer服务只在经理节点上运行了一个容器;web服务则运行了5个容器,由swarm自动将5个容器分配给集群中的各个节点。Docker会自动维护各个容器的状态,一旦出现异常,容器会自动重启。最重要的是,每个节点对外提供的web service都可以作为该程序的入口地址,Docker的Ingress routing mesh 实现了网络请求的负载均衡。
上一篇 / 目录 / 下一篇