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)。下面列出了本章节使用到的所有命令,供大家参考。




docker svnserver 设置用户 dockerservice_jsp上传到webservice


Part 2: 容器

当你按照上述步骤确认了Docker的运行环境正常之后,你可以着手创建自己的容器镜像了。首先创建一个新的目录:


docker svnserver 设置用户 dockerservice_jsp上传到webservice_02


Dockerfile

在此目录中新建一个文本文件,命名为Dockerfile。文件内容如下:


docker svnserver 设置用户 dockerservice_docker_03


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包含下面两行:

FlaskRedis

app.py的内容如下:

from flask import Flaskfrom redis import Redis, RedisErrorimport osimport socket# Connect to Redisredis = 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:

这段代码的逻辑很简单,程序会启动一个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 lsREPOSITORY TAG IMAGE ID CREATED SIZEfriendlyhello 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运行的区别:


docker svnserver 设置用户 dockerservice_docker_04


docker svnserver 设置用户 dockerservice_List_05


使用curl或浏览器来测试这个程序:

curl http://localhost:4000

Hello World!

Hostname: 6be4e1853e71Visits: cannot connect to Redis, counter disabled

停止容器

在容器正在运行的命令行窗口中,点击CTRL+C会退出这个python 程序,但是Windows系统比较特殊,该操作不会停止容器。正确的做法是使用命令docker container stop来停止一个运行的容器。方法是,先执行 docker container ls 找到正在运行的容器ID。

docker container lsCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES6be4e1853e71 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,并按提示输入用户名和密码。

然后给你的镜像设置一个标签。标签是对镜像的唯一标识。完整的标签格式是:/:
其中,/ 表明镜像会上传到你id中的某个镜像仓库。例如:

docker tag friendlyhello feiandytan/get-started:part2

上述命令为镜像friendlyhello创建了一个新的标签,表明此镜像将上传到我的id feiandytan下的仓库 get-started中,并且将其version记为part2。

最后一步就是发布:
docker push /get-started:part

一旦发布成功,你就可以在任意一台安装了Docker的电脑上运行该容器。方法是执行下面的命令:
docker run -p 4000:80 /get-started:part

小结

下面列出本章用到的命令,供大家参考:

docker build -t friendlyhello . # Create image using this directory's Dockerfiledocker run -p 4000:80 friendlyhello # Run "friendlyhello" mapping port 4000 to 80docker run -d -p 4000:80 friendlyhello # Same thing, but in detached modedocker container ls # List all running containersdocker container ls -a # List all containers, even those not runningdocker container stop  # Gracefully stop the specified containerdocker container kill  # Force shutdown of the specified containerdocker container rm  # Remove specified container from this machinedocker container rm $(docker container ls -a -q) # Remove all containersdocker image ls -a # List all images on this machinedocker image rm  # Remove specified image from this machinedocker image rm $(docker image ls -a -q) # Remove all images from this machinedocker login # Log in this CLI session using your Docker credentialsdocker tag  username/repository:tag # Tag  for upload to registrydocker push username/repository:tag # Upload tagged image to registrydocker 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: - webnetnetworks: webnet:

提示:要替换成你的docker id。

上述配置表明:

  1. 服务加载的镜像是/get-started:part2
  2. 启动5个容器实例来组成一个服务。服务的名称为"web"。
  3. 每个容器最多使用一个CPU内核的10%,以及50MB内存。
  4. 容器在失败状态下自动重启。
  5. 映射实体机端口4000到容器的端口80。
  6. 服务使用的网络名为"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:甥敳獲i062893OneDrivecodedocker-workspacemy-first-container>docker service lsID NAME MODE REPLICAS IMAGE PORTSypyx4ed2uzur getstartedlab_web replicated 0/10 feiandytan/get-started:part2 *:4000->80/tcp

执行命令docker stack services 查看某个stack的所有服务。例如:

C:甥敳獲i062893OneDrivecodedocker-workspacemy-first-container>docker stack services getstartedlabID NAME MODE REPLICAS IMAGE PORTSypyx4ed2uzur 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 getstartedlabdocker swarm leave --force

小结

下面列出本章使用到的docker命令,供大家参考:

docker swarm init # Init this machine as a swarm managerdocker stack ls # List stacks or appsdocker stack deploy -c   # Run the specified Compose filedocker service ls # List running services associated with an appdocker service ps  # List tasks associated with an appdocker inspect  # Inspect task or containerdocker container ls -q # List container IDsdocker stack rm  # Tear down an applicationdocker swarm leave --force # Take down a single node swarm from the manager