本文首先从Dockerfile创建了一个简单web镜像
然后将web镜像推送到了远程仓库,以备后面集群中不同机器自动下载
之后使用docker-compose.yml配置了一个应用
而后新建了2台虚拟机作为swarm节点,并部署应用的5个实例在这两台虚拟机上
最后还讲了如何如果更改集群配置、如何扩容您的集群和如重新发布您的应用
一、创建一个简单web镜像,并推送到docker仓库
1、创建Dockerfile
创建一个空目录, 然后CD到新目录,创建名为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
ADD . /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使用了我们尚未创建的几个文件,即app.py和requirements.txt。 下面让我们创建他们。
我们的赢
再创建两个文件,requirements.txt和app.py,并将它们与Dockerfile放在同一个文件夹中。 至此完成了我们的应用程序,您可以看到它非常简单。 当上面的Dockerfile构建成镜像后,由于Dockerfile的ADD命令,app.py和requirements.txt将会被加入到镜像中,并且由于EXPOSE命令暴露了80端口,我们可以通过HTTP访问app.py的输出。
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)
我们准备构建应用程序。 确保您仍处于创建的目录的顶层。 这是ls应该显示的内容:
$ ls
Dockerfile app.py requirements.txt
现在运行build命令。 这将创建一个Docker镜像,我们使用-t为它取了一个友好的名称。
$ docker image ls
REPOSITORY TAG IMAGE ID
friendlyhello latest 326387cea398
运行应用程序,使用-p将计算机的端口4000映射到容器的已发布端口80:
docker run -p 4000:80 friendlyhello
您应该在http://0.0.0.0:80看到Python正在为您的应用程序提供服务的消息。 但是该消息来自容器内部,它不知道您将该容器的端口80映射到4000,从而生成正确的URL http:// localhost:4000。
在Web浏览器中转到该URL,以查看在网页上提供的显示内容。
您还可以在shell中使用curl命令来查看相同的内容。
$ curl http://localhost:4000
Hello World!
Hostname: 8fc990912a14
Visits: cannot connect to Redis, counter disabled
到此镜像创建完成,当然你也可以使用自己的其它web镜像
1、首先到https://hub.docker.com/注册一个账号,保存下用户名密码
2、控制台登陆dockerhub账户
$ docker login
输入刚注册的用户名密码
3、查看镜像
$ docker image ls
REPOSITORY TAG IMAGE ID
friendlyhello latest 326387cea398
3、选择需要上传的镜像,重命名为指定的格式
$ docker tag friendlyhello abs52121/friendlyhello:v1
abs52121:为我自己的dockerhub账户名称,替换成你刚注册的名称
friendlyhello:为自己为镜像取的名字
v1:为任意设置的版本号
4、完成上述操作后,即可提交镜像到自己的仓库
$ docker push abs52121/friendlyhello:v1
docker-compose.yml文件
docker-compose.yml文件是一个YAML文件,用于定义Docker容器在生产中的行为方式。
将下面内容保存为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
resources:
limits:
cpus: "0.1"
memory: 50M
restart_policy:
condition: on-failure
ports:
- "4000:80"
networks:
- webnet
networks:
webnet:
这个docker-compose.yml文件告诉Docker执行以下操作:
从注册中心中提取我们在步骤1中上传的镜像。
从此镜像运行5个实例作为一个服务,服务名为web,限制每个实例使用最多10%的CPU(所有核心)和50MB的RAM。
如果如果容器出错,立即重启。
将主机上的端口4000映射到Web的端口80。
指示Web容器通过称为webnet的负载平衡网络共享端口80。 (在内部,容器发布在web的80端口)
默认使用Webnet网络(负载平衡网络)。
1、初始化swarm
$ docker swarm init
2、现在让我们来运行吧,您需要为您的应用程序命名,在这里它被设置为getstartedlab:
$ docker stack deploy -c docker-compose.yml getstartedlab
3、我们的单个服务在一台主机上运行已部署5个容器实例, 让我们来看一下吧。
$ docker service ls
s31sqx0dmkdh getstartedlab_web replicated 5/5 abs52121/friendlyhello:v1 *:80->80/tcp
$ docker service ps getstartedlab_web
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
rzk868yrs1zm getstartedlab_web.1 abs52121/friendlyhello:v1 linuxkit-025000000001 Running Running about a minute ago
tmp93inu2bu9 getstartedlab_web.2 abs52121/friendlyhello:v1 linuxkit-025000000001 Running Running about a minute ago
jeasl6c1pah1 getstartedlab_web.3 abs52121/friendlyhello:v1 linuxkit-025000000001 Running Running about a minute ago
ik2wb1986qxf getstartedlab_web.4 abs52121/friendlyhello:v1 linuxkit-025000000001 Running Running about a minute ago
s3dgi0lr7clf getstartedlab_web.5 abs52121/friendlyhello:v1 linuxkit-025000000001 Running Running about a minute ago
#查看所有容器id
$ docker container ls -q
4、您可以连续多次运行curl -4 http://localhost:4000,或者在浏览器中转到该URL并点击刷新几次。
无论哪种方式,容器ID都会发生变化,从而证明负载均衡; 对于每个请求,以循环方式选择5个任务中的一个来响应。 容器ID与上一个命令(docker container ls -q)的输出匹配。
5、扩展你的应用
您可以通过更改docker-compose.yml文件,并重新运行docker stack deploy命令来扩展应用程序:
$ docker stack deploy -c docker-compose.yml getstartedlab
Docker执行就地更新,无需杀死任何容器。
现在,重新运行docker container ls -q以查看已重新配置的已部署实例。 如果增加副本数量,则会启动更多任务,从而启动更多容器。
6、退出应用程序和swarm
通过 docker stack rm退出程序
:
$ docker stack rm getstartedlab
退出swarm
$ docker swarm leave --force
7、了解Swarm集群
swarm是一组运行Docker并加入群集的计算机。在此之后,您继续运行您习惯使用的Docker命令,但现在它们由群集管理器在群集上执行。集群中的机器可以是物理的或虚拟的。加入swarm后,它们被称为节点。
Swarm 管理器可以使用多种策略来运行容器,例如“emptiest node” - 它使用容器填充利用率最低的机器。或“global”,它确保每台机器只获得指定容器的一个实例。您可以指示swarm管理器在Compose文件中使用这些策略,就像您上面已经使用的那样。
Swarm 管理器是群中唯一可以执行命令的机器,或授权其他机器作为工作者加入群集。工作者只是在那里提供能力,并且没有权力告诉任何其他机器它能做什么和不能做什么。
到目前为止,您一直在本地计算机上以单主机模式使用Docker。但是Docker也可以切换到swarm模式,这就是使用群集的能力。立即启用群集模式使当前计算机成为swarm管理器(swarm init命令)。之后,Docker就会运行您在管理的swarm上执行的命令,而不仅仅是在当前机器上。
1、首先通过docker-machine创建2个虚拟机(当然也可以使用你目前已经有的物理机或者虚拟机)
现在使用docker-machine创建几个VM,使用VirtualBox驱动程序,在运行命令前请确保你安装了virtualbox虚拟机:
$ docker-machine create --driver virtualbox myvm1
$ docker-machine create --driver virtualbox myvm2
墙内用户可以自行百度下载boot2docker.iso 文件,并使用--virtualbox-boot2docker-url参数指定文件位置
$ python-docker huhaichao$ docker-machine create --driver virtualbox --virtualbox-boot2docker-url=/path/to/boot2docker.iso myvm3
2、您现在创建了两个名为myvm1和myvm2的VM。
使用此命令列出计算机并获取其IP地址。
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
myvm1 - virtualbox Running tcp://192.168.99.100:2376 v18.03.1-ce
myvm2 - virtualbox Running tcp://192.168.99.101:2376 v18.03.1-ce
3、初始化swarm并且为其增加节点
您可以使用docker-machine ssh向VM发送命令。 使用docker swarm init指示m
yvm1成为一个swarm管理器:
$ docker-machine ssh myvm1 "docker swarm init --advertise-addr 192.168.99.100"
Swarm initialized: current node (rxdphwlo6tpo60ql4k1mby8zx) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-63xho3dyvfjt76ivusisk6j1nsrwo9thto8frgja83jl7k04mp-eyopgohzj6agbox1o53swpj38 192.168.99.100:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
也可以使用以下命令进入myvm1虚拟机,然后再然后再执行swarm初始化操作
//进入虚拟机
$ docker-machine --native-ssh ssh myvm1
//初始化swarm
$ docker swarm init --advertise-addr 192.168.99.100
如您所见,对docker swarm init的输出包含一个docker swarm join命令,您可以在要添加的任何节点上执行此命令,加入swarm作为一个worker节点。
复制此命令,并通过docker-machine ssh将其发送到myvm2,让myvm2作为worker加入你的新swarm:
$ docker-machine ssh myvm2 "docker swarm join --token SWMTKN-1-63xho3dyvfjt76ivusisk6j1nsrwo9thto8frgja83jl7k04mp-eyopgohzj6agbox1o53swpj38 192.168.99.100:2377"
This node joined a swarm as a worker.
恭喜你,你已经创建了你的第一个swarm!
在管理器上运行docker node ls以查看此swarm中的节点:
$ docker-machine ssh myvm1 "docker node ls"
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
rxdphwlo6tpo60ql4k1mby8zx * myvm1 Ready Active Leader 18.03.1-ce
tbkcetrx4y6bpbl55hvjgqhaj myvm2 Ready Active 18.03.1-ce
4、离开一个swarm
如果你想重新开始,可以在每个节点运行docker swarm leave。
5、在swarm群集上部署您的应用程序
困难的部分结束了。 现在,您只需重复第2部分中使用的过程即可部署到新的swarm上。 请记住,只有像myvm1这样的群体管理器才能执行Docker命令; worker只是为了提供能力。
与以前一样,运行以下命令在myvm1上部署应用程序。
//复制文件到myvm1
$ docker-machine scp docker-compose.yml myvm1:/home/docker
//在myvm1执行命令,部署集群应用
$ docker-machine ssh myvm1 "docker stack deploy -c docker-compose.yml getstartedlab"
现在您可以使用第2部分中使用的相同docker命令。只是这次注意到服务(和相关容器)已在myvm1和myvm2之间分配
$ docker service ps getstartedlab_web
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
m09niqvz3me5 getstartedlab_web.1 abs52121/friendlyhello:v1 myvm1 Running Running 7 minutes ago
dqe31n93su10 getstartedlab_web.2 abs52121/friendlyhello:v1 myvm2 Running Running 7 minutes ago
qe8ltg98230g getstartedlab_web.3 abs52121/friendlyhello:v1 myvm1 Running Running 7 minutes ago
u830cf28y0d2 getstartedlab_web.4 abs52121/friendlyhello:v1 myvm2 Running Running 7 minutes ago
q8csws9zijtu getstartedlab_web.5 abs52121/friendlyhello:v1 myvm2 Running Running 7 minutes ago
6、访问您的群集
您可以从myvm1或myvm2的IP地址访问您的应用程序。
您创建的网络在它们之间共享并进行负载平衡。 运行docker-machine ls获取虚拟机的IP地址,并在浏览器上访问其中任何一个,点击刷新(或只是通过curl访问)。
访问时有5个容器ID随机展示,这表明了负载平衡。两个IP地址都能访问的原因是swarm中的节点参与入口路由网格。 这可确保部署在swarm中某个端口的服务始终将该端口保留给自身,无论实际运行容器的是哪个节点。 下面是一个图表,说明在三节点群上的端口8080上发布的名为my-web的服务的路由网格是什么样子的:
7、迭代和扩展您的应用程序
你可以用docker stack rm拆掉堆栈。 例如:
$ docker stack rm getstartedlab