@yangwenbo
2023-06-27T19:01:56.000000Z
字数 18712
阅读 317
Docker
Docker Compose 是 Docker 官⽅编排(Orchestration)项⽬之⼀,负责快速的部署分布式应⽤。其代
码⽬前在https://github.com/docker/compose上开源。Compose 定位是 「定义和运⾏多个 Docker 容器的应⽤(Defining and running multi-container Docker applications)」,其前身是开源项⽬ Fig 。
然⽽,在⽇常⼯作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现⼀个 Web 项⽬,除了 Web服务容器本身,往往还需要再加上后端的数据库服务容器或者缓存服务容器,甚⾄还包括负载均衡容器等。Compose 恰好满⾜了这样的需求。它允许⽤户通过⼀个单独的 dockercompose.yml 模板⽂件(YAML 格式)来定义⼀组相关联的应⽤容器为⼀个项⽬(project)。
Compose 中有两个重要的概念:
- 服务 (service):⼀个应⽤的容器,实际上可以包括若⼲运⾏相同镜像的容器实例。
- 项⽬ (project):由⼀组关联的应⽤容器组成的⼀个完整业务单元,在 docker-compose.yml ⽂件中定义。
Compose 的默认管理对象是项⽬,通过⼦命令对项⽬中的⼀组容器进⾏便捷地⽣命周期管理。
Compose 项⽬由 Python 编写,实现上调⽤了 Docker 服务提供的 API 来对容器进⾏管理。所以只要所操作的平台⽀持 Docker API,就可以在其上利⽤ Compose 来进⾏编排管理。
Compose ⽀持 Linux、macOS、Windows 10 三⼤平台。Compose 可以通过 Python 的包管理⼯具 pip 进⾏安装,也可以直接下载编译好的⼆进制⽂件使⽤,甚⾄能够直接在 Docker 容器中运⾏。
前两种⽅式是传统⽅式,适合本地环境下安装使⽤;最后⼀种⽅式则不破坏系统环境,更适合云计算场景。Docker for Mac 、Docker for Windows ⾃带 docker-compose ⼆进制⽂件,安装 Docker 之后可以直接使⽤。
Compose 既然是⼀个 Python 应⽤,⾃然也可以直接⽤容器来执⾏它。
[root@docker ~]# curl -L https://github.com/docker/compose/releases/download/1.8.0/run.sh > /usr/local/bin/docker-compose
[root@docker ~]# chmod +x /usr/local/bin/docker-compose
[root@docker ~]# ll -d /usr/local/bin/docker-compose
-rwxr-xr-x 1 root root 1400 2月 4 15:01 /usr/local/bin/docker-compose
实际上,查看下载的 run.sh 脚本内容,如下:
[root@docker ~]# cat /usr/local/bin/docker-compose
#!/bin/bash
#
# Run docker-compose in a container
#
# This script will attempt to mirror the host paths by using volumes for the
# following paths:
# * $(pwd)
# * $(dirname $COMPOSE_FILE) if it's set
# * $HOME if it's set
#
# You can add additional volumes (or any docker run options) using
# the $COMPOSE_OPTIONS environment variable.
#
set -e
VERSION="1.8.0"
IMAGE="docker/compose:$VERSION"
# Setup options for connecting to docker host
if [ -z "$DOCKER_HOST" ]; then
DOCKER_HOST="/var/run/docker.sock"
fi
if [ -S "$DOCKER_HOST" ]; then
DOCKER_ADDR="-v $DOCKER_HOST:$DOCKER_HOST -e DOCKER_HOST"
else
DOCKER_ADDR="-e DOCKER_HOST -e DOCKER_TLS_VERIFY -e DOCKER_CERT_PATH"
fi
# Setup volume mounts for compose config and context
if [ "$(pwd)" != '/' ]; then
VOLUMES="-v $(pwd):$(pwd)"
fi
if [ -n "$COMPOSE_FILE" ]; then
compose_dir=$(dirname $COMPOSE_FILE)
fi
# TODO: also check --file argument
if [ -n "$compose_dir" ]; then
VOLUMES="$VOLUMES -v $compose_dir:$compose_dir"
fi
if [ -n "$HOME" ]; then
VOLUMES="$VOLUMES -v $HOME:$HOME -v $HOME:/root" # mount $HOME in /root to share docker.config
fi
# Only allocate tty if we detect one
if [ -t 1 ]; then
DOCKER_RUN_OPTIONS="-t"
fi
if [ -t 0 ]; then
DOCKER_RUN_OPTIONS="$DOCKER_RUN_OPTIONS -i"
fi
exec docker run --rm $DOCKER_RUN_OPTIONS $DOCKER_ADDR $COMPOSE_OPTIONS $VOLUMES -w "$(pwd)" $IMAGE "$@"
可以看到,它其实是下载了 docker/compose 镜像并运⾏。
如果是⼆进制包⽅式安装的,删除⼆进制⽂件即可。
[root@docker ~]# rm /usr/local/bin/docker-compose
如果是通过 pip 安装的,则执⾏如下命令即可删除。
[root@docker ~]# pip uninstall docker-compose
下⾯我们⽤ Python 来建⽴⼀个能够记录⻚⾯访问次数的 web ⽹站。 新建⽂件夹,在该⽬录中编写 app.py ⽂件
[root@docker ~]# mkdir web
[root@docker ~]# cd web/
[root@docker web]# vim app.py
[root@docker web]# cat app.py
import time
import redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)
def get_hit_count():
retries = 5
while True:
try:
return cache.incr('hits')
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
time.sleep(0.5)
@app.route('/')
def hello():
count = get_hit_count()
return 'Hello World! I have been seen {} times.\n'.format(count)
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
接着编写 Dockerfile ⽂件,内容为:
[root@docker web]# vim Dockerfile
[root@docker web]# cat Dockerfile
FROM python:3.6-alpine
ADD . /code
WORKDIR /code
RUN pip install redis flask
CMD ["python", "app.py"]
然后是编写 docker-compose.yml ⽂件,这个是 Compose 使⽤的主模板⽂件。
[root@docker web]# vim docker-compose.yml
[root@docker web]# cat docker-compose.yml
version: '2.0'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
redis:
image: "redis:alpine"
运⾏ compose 项⽬:
[root@docker web]# docker-compose up
此时访问本地 5000 端⼝,http://192.168.200.8:5000
每次刷新⻚⾯,计数就会加 1。
对于 Compose 来说,⼤部分命令的对象既可以是项⽬本身,也可以指定为项⽬中的服务或者容器。如果没有特别的说明,命令对象将是项⽬,这意味着项⽬中所有的服务都会受到命令影响。
执⾏docker-compose [COMMAND] --help
或者docker-compose help [COMMAND]
可以查看具体某个命令的使⽤格式。
docker-compose 命令的基本的使⽤格式是:docker-compose [-f=<arg>...] [options] [COMMAND] [ARGS...]
命令选项:
- -f, --file FILE 指定使⽤的 Compose 模板⽂件,默认为 docker-compose.yml,可以多次指定。
- -p, --project-name NAME 指定项⽬名称,默认将使⽤所在⽬录名称作为项⽬名。
- --x-networking 使⽤ Docker 的可拔插⽹络后端特性
- --x-network-driver DRIVER 指定⽹络后端的驱动,默认为 bridge
- --verbose 输出更多调试信息。
- -v, --version 打印版本并退出。
build 格式为docker-compose build [options] [SERVICE...]。 构建(重新构建)项⽬中的服务容器。服务容器⼀旦构建后,将会带上⼀个标记名,例如对于 web 项⽬中的⼀个 db 容器,可能是 web_db。可以随时在项⽬⽬录下运⾏ docker-compose build 来重新构建服务。选项包括:
- --force-rm 删除构建过程中的临时容器。
- --no-cache 构建镜像过程中不使⽤ cache(这将加⻓构建过程)。
- --pull 始终尝试通过 pull 来获取更新版本的镜像。
config: 验证 Compose ⽂件格式是否正确,若正确则显示配置,若格式错误显示错误原因。
down:此命令将会停⽌ up 命令所启动的容器,并移除⽹络
exec:进⼊指定的容器。
help:获得⼀个命令的帮助。
images:列出 Compose ⽂件中包含的镜像。
kill:格式为docker-compose kill [options] [SERVICE...]
。通过发送 SIGKILL 信号来强制停⽌服务容器。⽀持通过 -s 参数来指定发送的信号,例如通过如下指令发送 SIGINT 信号。
[root@docker ~]# docker-compose kill -s SIGINT
logs:格式为docker-compose logs [options] [SERVICE...]
,查看服务容器的输出。默认情况下,
docker-compose 将对不同的服务输出使⽤不同的颜⾊来区分。可以通过 --no-color 来关闭颜⾊。该命令在调试问题的时候⼗分有⽤。
pause:格式为docker-compose pause [SERVICE...]
,暂停⼀个服务容器。
port:格式为docker-compose port [options] SERVICE PRIVATE_PORT
,打印某个容器端⼝所映射的公共端⼝。选项:
- --protocol=proto 指定端⼝协议,tcp(默认值)或者 udp。
- --index=index 如果同⼀服务存在多个容器,指定命令对象容器的序号(默认为 1)。
ps:格式为docker-compose ps [options] [SERVICE...]
,列出项⽬中⽬前的所有容器。选项:
- -q 只打印容器的 ID 信息。
pull:格式为docker-compose pull [options] [SERVICE...]
,拉取服务依赖的镜像。选项:
- --ignore-pull-failures 忽略拉取镜像过程中的错误。
push:推送服务依赖的镜像到 Docker 镜像仓库。
restart:格式为docker-compose restart [options] [SERVICE...]
,重启项⽬中的服务。选项:
- -t, --timeout TIMEOUT 指定重启前停⽌容器的超时(默认为 10 秒)。
rm:格式为docker-compose rm [options] [SERVICE...]
,删除所有(停⽌状态的)服务容器。推荐先执⾏docker-compose stop
命令来停⽌容器。选项:
- -f, --force 强制直接删除,包括⾮停⽌状态的容器。⼀般尽量不要使⽤该选项。
- -v 删除容器所挂载的数据卷。
run:格式为docker-compose run [options] [-p PORT...] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]
,在指定服务上执⾏⼀个命令。例如:
[root@docker ~]# docker-compose run ubuntu ping docker.com
将会启动⼀个 ubuntu 服务容器,并执⾏ ping docker.com命令。默认情况下,如果存在关联,则所有关联的服务将会⾃动被启动,除⾮这些服务已经在运⾏中。
该命令类似启动容器后运⾏指定的命令,相关卷、链接等等都将会按照配置⾃动创建。
给定命令将会覆盖原有的⾃动运⾏命令; 不会⾃动创建端⼝,以避免冲突。
如果不希望⾃动启动关联的容器,可以使⽤ --no-deps 选项,例如:
[root@docker ~]# docker-compose run --no-deps web python manage.py shell
将不会启动 web 容器所关联的其它容器,选项:
- -d 后台运⾏容器。
- --name NAME 为容器指定⼀个名字。
- --entrypoint CMD 覆盖默认的容器启动指令。
- -e KEY=VAL 设置环境变量值,可多次使⽤选项来设置多个环境变量。
- -u, --user="" 指定运⾏容器的⽤户名或者 uid。
- --no-deps 不⾃动启动关联的服务容器。
- --rm 运⾏命令后⾃动删除容器,d 模式下将忽略。
- -p, --publish=[] 映射容器端⼝到本地主机。
- --service-ports 配置服务端⼝并映射到本地主机。
- -T 不分配伪 tty,意味着依赖 tty 的指令将⽆法运⾏。
scale:格式为docker-compose scale [options] [SERVICE=NUM...]
,设置指定服务运⾏的容器个数。通过service=num 的参数来设置数量。例如:
[root@docker ~]# docker-compose scale web=3 db=2
将启动 3 个容器运⾏ web 服务,2 个容器运⾏ db 服务。
⼀般的,当指定数⽬多于该服务当前实际运⾏容器,将新创建并启动容器;反之,将停⽌容器。选项:
- -t, --timeout TIMEOUT 停⽌容器时候的超时(默认为 10 秒)。
start:格式为docker-compose start [SERVICE...]
,启动已经存在的服务容器。
stop:格式为docker-compose stop [options] [SERVICE...]
, 停⽌已经处于运⾏状态的容器,但不删除它。通过docker-compose start
可以再次启动这些容器。选项:
- -t, --timeout TIMEOUT 停⽌容器时候的超时(默认为 10 秒)。
top:查看各个服务容器内运⾏的进程。
unpause:格式为docker-compose unpause [SERVICE...]
,恢复处于暂停状态中的服务。
up:格式为docker-compose up [options] [SERVICE...]
,该命令⼗分强⼤,它将尝试⾃动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的⼀系列操作。链接的服务都将会被⾃动启动,除⾮已经处于运⾏状态。 可以说,⼤部分时候都可以直接通过该命令来启动⼀个项⽬。
默认情况,docker-compose up
启动的容器都在前台,控制台将会同时打印所有容器的输出信息,可以很⽅便进⾏调试。 当通过 Ctrl-C 停⽌命令时,所有容器将会停⽌。
如果使⽤docker-compose up -d
,将会在后台启动并运⾏所有的容器。⼀般推荐⽣产环境下使⽤该选项。
默认情况,如果服务容器已经存在,docker-compose up
将会尝试停⽌容器,然后重新创建(保持使⽤ volumes-from 挂载的卷),以保证新启动的服务匹配 docker-compose.yml ⽂件的最新内容。如果⽤户不希望容器被停⽌并重新创建,可以使⽤docker-compose up --no-recreate
。这样将只会启动处于停⽌状态的容器,⽽忽略已经运⾏的服务。
如果⽤户只想重新部署某个服务,可以使⽤docker-compose up --no-deps -d <SERVICE_NAME>
来重新创建服务并后台停⽌旧服务,启动新服务,并不会影响到其所依赖的服务。选项:
- -d 在后台运⾏服务容器。
- --no-color 不使⽤颜⾊来区分不同的服务的控制台输出。
- --no-deps 不启动服务所链接的容器。
- --force-recreate 强制重新创建容器,不能与 --no-recreate 同时使⽤。
- --no-recreate 如果容器已经存在了,则不重新创建,不能与 --force-recreate 同时使⽤。
- --no-build 不⾃动构建缺失的服务镜像。
- -t, --timeout TIMEOUT 停⽌容器时候的超时(默认为 10 秒)。
Docker Machine 是 Docker 官⽅编排(Orchestration)项⽬之⼀,负责在多种平台上快速安装 Docker环境。
Docker Machine 项⽬基于 Go 语⾔实现,⽬前在Github上进⾏维护。
Docker Machine 是 Docker 官⽅提供的⼀个⼯具,它可以帮助我们在远程的机器上安装 Docker,或者在虚拟机 host 上直接安装虚拟机并在虚拟机中安装 Docker。我们还可以通过 docker-machine 命令来管理这些虚拟机和 Docker。
Docker Machine 可以在多种操作系统平台上安装,包括 Linux、macOS,以及 Windows。
在 Linux 上的也安装⼗分简单,从官⽅ GitHub Release处直接下载编译好的⼆进制⽂件即可。 例如,在 Linux 64 位系统上直接下载对应的⼆进制包。
[root@docker ~]# curl -L https://github.com/docker/machine/releases/download/v0.13.0/docker-machine-`uname -s`-`uname -m` > /usr/local/bin/docker-machine
[root@docker ~]# chmod +x /usr/local/bin/docker-machine
[root@docker ~]# ll -d /usr/local/bin/docker-machine
-rwxr-xr-x 1 root root 26574656 2月 6 18:58 /usr/local/bin/docker-machine
完成后,查看版本信息。
[root@docker ~]# docker-machine -v
docker-machine version 0.13.0, build 9ba6da9
Docker Machine ⽀持多种后端驱动,包括虚拟机、本地主机和云平台等。
使⽤virtualbox
类型的驱动,创建⼀台 Docker 主机,命名为 test。
[root@docker ~]# docker-machine create -d virtualbox test
你也可以在创建时加上如下参数,来配置主机或者主机上的 Docker。
- --engine-opt dns=114.114.114.114配置 Docker 的默认 DNS
- --engine-registry-mirror https://registry.docker-cn.com配置 Docker 的仓库镜像
- --virtualbox-memory 2048 配置主机内存
- --virtualbox-cpu-count 2 配置主机 CPU
更多参数请使⽤ docker-machine create --driver virtualbox --help
命令查看。
[root@docker ~]# docker-machine create -d generic \
--generic-ip-address=192.168.200.6 \
--generic-ssh-user=root \
--generic-ssh-key ~/.ssh/id_rsa \
dev
创建好主机之后,查看主机
[root@docker ~]# docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER
ERRORStest - virtualbox Running tcp://192.168.200.8:2376 v17.1
0.0-ce
创建主机成功后,可以通过 env 命令来让后续操作对象都是⽬标主机。
[root@docker ~]# docker-machine env test
后续根据提示在命令⾏输⼊命令之后就可以操作 test 主机。也可以通过 SSH 登录到主机。
[root@docker ~]# docker-machine ssh test
docker@test:~$ docker --version
Docker version 17.10.0-ce, build f4ffd25
连接到主机之后你就可以在其上使⽤ Docker 了。
通过 -d 选项可以选择⽀持的驱动类型:
- amazonec2
- azure
- digitalocean
- exoscale
- generic
- hyperv
- none
- openstack
- rackspace
- softlayer
- virtualbox
- vmwarevcloudair
- vmwarefusion
- vmwarevsphere
- active 查看活跃的 Docker 主机
- config 输出连接的配置信息
- create 创建⼀个 Docker 主机
- env 显示连接到某个主机需要的环境变量
- inspect 输出主机更多信息
- ip 获取主机地址
- kill 停⽌某个主机
- ls 列出所有管理的主机
- provision 重新设置⼀个已存在的主机
- regenerate-certs 为某个主机重新⽣成 TLS 认证信息
- restart 重启主机
- rm 删除某台主机
- ssh SSH 到主机上执⾏命令
- scp 在主机之间复制⽂件
- mount 挂载主机⽬录到本地
- start 启动⼀个主机
- status 查看主机状态
- stop 停⽌⼀个主机
- upgrade 更新主机 Docker 版本为最新
- url 获取主机的 URL
- version 输出 docker-machine 版本信息
- help 输出帮助信息
每个命令,⼜带有不同的参数,可以通过如下命令来查看具体的⽤法:
[root@docker ~]# docker-machine COMMAND --help
Swarm 是使⽤SwarmKit构建的 Docker 引擎内置(原⽣)的集群管理和编排⼯具。 Docker Swarm 是Docker 官⽅三剑客项⽬之⼀,提供 Docker 容器集群服务,是 Docker 官⽅对容器云⽣态进⾏⽀持的核⼼⽅案。
使⽤它,⽤户可以将多个 Docker 主机封装为单个⼤型的虚拟 Docker 主机,快速打造⼀套容器云平台。Swarm mode 内置 kv存储功能,提供了众多的新特性,⽐如:具有容错能⼒的去中⼼化设计、内置服务发现、负载均衡、路由⽹格、动态伸缩、滚动更新、安全传输等。使得 Docker 原⽣的 Swarm集群具备与 Mesos 、 Kubernetes 竞争的实⼒。使⽤ Swarm集群之前需要了解以下⼏个概念。
运⾏ Docker 的主机可以主动初始化⼀个 Swarm 集群或者加⼊⼀个已存在的 Swarm 集群,这样这个运⾏ Docker 的主机就成为⼀个 Swarm 集群的节点 (node) 。节点分为 管理 (manager) 节点和⼯作(worker) 节点 。
管理节点⽤于 Swarm 集群的管理, docker swarm 命令基本只能在管理节点执⾏(节点退出集群命令 docker swarm leave 可以在⼯作节点执⾏)。⼀个 Swarm 集群可以有多个管理节点,但只有⼀个管理节点可以成为 leader ,leader 通过 raft 协议实现。
⼯作节点是任务执⾏节点,管理节点将服务 ( service ) 下发⾄⼯作节点执⾏。管理节点默认也作为⼯作节点。你也可以通过配置让服务只运在管理节点。来⾃ Docker 官⽹的这张图⽚形象的展示了集群中管理节点与⼯作节点的关系。
任务(Task) 是 Swarm 中的最⼩的调度单位,⽬前来说就是⼀个单⼀的容器; 服务(Services) 是指⼀组任务的集合,服务定义了任务的属性。服务有两种模式:
- replicated services 按照⼀定规则在各个⼯作节点上运⾏指定个数的任务。
- global services 每个⼯作节点上运⾏⼀个任务
两种模式通过 docker service create 的 --mode 参数指定。来⾃ Docker 官⽹的这张图⽚形象的展示了容器、任务、服务的关系。
我们这⾥利⽤上⼀节的 docker machine 来充当集群的主机,⾸先先创建⼀个 manager 节点,然后在该节点上执⾏初始化集群命令:
[root@docker ~]# docker-machine create -d virtualbox manager
执⾏ docker swarm init 命令的节点⾃动成为管理节点。
管理节点初始化完成后,然后同样的⽤ docker-machine 创建⼯作节点,然后将其加⼊到管理节点之中去即可:
[root@docker ~]# docker-machine create -d virtualbox worker1
我们可以看到上⾯的提示信息:This node joined a swarm as a worker.,表明节点已经加⼊到 swarm 集群之中了。
经过上边的两步,我们已经拥有了⼀个最⼩的 Swarm 集群,包含⼀个管理节点和两个⼯作节点。
管理节点使⽤ docker node ls 查看集群:
[root@docker ~]# docker node ls
[root@docker ~]# docker service ls
[root@docker ~]# docker-machine ls
[root@docker ~]# docker service ls
[root@docker ~]# docker service ps nginx
使⽤ docker service logs 来查看某个服务的⽇志。
[root@docker ~]# docker service logs nginx
使⽤ docker service rm 来从 Swarm 集群移除某个服务:
[root@docker ~]# docker service rm nginx
nginx
正如之前使⽤ docker-compose.yml
来⼀次配置、启动多个容器,在 Swarm
集群中也可以使⽤ compose
⽂件(docker-compose.yml)来配置、启动多个服务。
上⼀节中,我们使⽤ docker service create
⼀次只能部署⼀个服务,使⽤ docker-compose.yml
我们可以⼀次启动多个关联的服务。
我们以在 Swarm
集群中部署 WordPress
为例进⾏说明:(docker-compose.yml)
version: "3"
services:
wordpress:
image: wordpress
ports:
- 80:80
networks:
- overlay
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
deploy:
mode: replicated
replicas: 3
db:
image: mysql
networks:
- overlay
volumes:
- db-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
deploy:
placement:
constraints: [node.role == manager]
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
stop_grace_period: 1m30s
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
volumes:
db-data:
networks:
overlay:
其中constraints: [node.role == manager]是调度策略,⽂档地址:https://docs.docker.com/swarm/scheduler/filter/
在 Swarm 集群管理节点新建该⽂件,其中的 visualizer 服务提供⼀个可视化⻚⾯,我们可以从浏览器中很直观的查看集群中各个服务的运⾏节点。
在 Swarm 集群中使⽤ docker-compose.yml 我们⽤ docker stack
命令,下⾯我们对该命令进⾏详细讲解。
部署服务使⽤ docker stack deploy
,其中 -c
参数指定 compose ⽂件名。
[root@docker ~]# docker stack deploy -c docker-compose.yml wordpres
[root@docker ~]# docker stack ls
NAME SERVICES
wordpress 3
要移除服务,使⽤ docker stack down
:
[root@docker ~]# docker stack down wordpress
Removing service wordpress_db
Removing service wordpress_visualizer
Removing service wordpress_wordpress
Removing network wordpress_overlay
Removing network wordpress_default
该命令不会移除服务所使⽤的数据卷 ,如果你想移除数据卷请使⽤docker volume rm
。
下⾯我们介绍⼏个可以⽤图形化的⽅式来管理 Docker 的⼯具。
Shipyard:https://github.com/shipyard/shipyard(已停⽌维护)
Portainer(基于 Go)是⼀个轻量级的管理界⾯,可让您轻松管理 Docker 主机或 Swarm 集群。
Portainer 的使⽤意图是简单部署。它包含可以在任何 Docker 引擎上运⾏的单个容器(Docker for Linux 和 Docker for Windows)。
Portainer 允许您管理 Docker 容器、image、volume、network 等。 它与独⽴的 Docker 引擎和Docker Swarm 兼容。
Docker 命令安装:
[root@docker ~]# docker volume create portainer_data
portainer_data
[root@docker ~]# docker volume ls
DRIVER VOLUME NAME
local portainer_data
[root@docker ~]# docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
portainer/portainer latest 62771b0b9b09 6 months ago 79.1MB
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f20b865d83e7 portainer/portainer "/portainer" 25 seconds ago Up 24 seconds 0.0.0.0:9000->9000/tcp hungry_euclid
Rancher
是⼀个开源的企业级容器管理平台。通过Rancher
,企业不必⾃⼰使⽤⼀系列的开源软件去从头搭建容器服务平台。Rancher
提供了在⽣产环境中使⽤管理Docker
和Kubernetes
的全栈化容器部署与管理平台。
cAdvisor 是 Google 开发的容器监控⼯具,我们来看看 cAdvisor 有什么能耐。
- 监控 Docker Host cAdvisor 会显示当前 host 的资源使⽤情况,包括 CPU、内存、⽹络、⽂件系统等。
- 监控容器 点击 Docker Containers 链接,显示容器列表。点击某个容器,⽐如 sysdig,进⼊该容器的监控⻚⾯。
以上就是 cAdvisor 的主要功能,总结起来主要两点:
- 展示 Host 和容器两个层次的监控数据。
- 展示历史变化数据。
由于 cAdvisor 提供的操作界⾯略显简陋,⽽且需要在不同⻚⾯之间跳转,并且只能监控⼀个 host,这不免会让⼈质疑它的实⽤性。但 cAdvisor 的⼀个亮点是它可以将监控到的数据导出给第三⽅⼯具,由这些⼯具进⼀步加⼯处理。
我们可以把 cAdvisor 定位为⼀个监控数据收集器,收集和导出数据是它的强项,⽽⾮展示数据。cAdvisor ⽀持很多第三⽅⼯具,其中就包括后⾯我们重点要学习的 Prometheus 。
[root@docker ~]# docker run \
--volume=/:/rootfs:ro \
--volume=/var/run:/var/run:rw \
--volume=/sys:/sys:ro \
--volume=/var/lib/docker/:/var/lib/docker:ro \
--volume=/dev/disk/:/dev/disk:ro \
--publish=8080:8080 \
--detach=true \
--name=cadvisor \
google/cadvisor:latest
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
portainer/portainer latest 62771b0b9b09 6 months ago 79.1MB
google/cadvisor latest eb1210707573 2 years ago 69.6MB
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1335debc08cd google/cadvisor:latest "/usr/bin/cadvisor -…" 52 seconds ago Up 51 seconds 0.0.0.0:8080->8080/tcp cadvisor
f20b865d83e7 portainer/portainer "/portainer" 28 minutes ago Up 20 minutes 0.0.0.0:9000->9000/tcp hungry_euclid
通过访问地址:http://192.168.200.8:8080/containers/ 可以查看所有容器信息:
除此之外,cAdvisor 还提供了⼀个 Rest
API:https://github.com/google/cadvisor/blob/master/docs/api.md
cAdvisor 通过该 REST API 暴露监控数据,格式如下:
http://<hostname>:<port>/api/<version>/<request>
Docker
的⼝号是 Build,Ship,and Run Any App,Anywhere,在我们使⽤ Docker 的⼤部分时候,的确能感觉到其优越性,但是往往在我们 Build ⼀个应⽤的时候,是将我们的源代码也构建进去的,这对于类似于 golang 这样的编译型语⾔肯定是不⾏的,因为实际运⾏的时候我只需要把最终构建的⼆进制包给你就⾏,把源码也⼀起打包在镜像中,需要承担很多⻛险,即使是脚本语⾔,在构的时候也可能需要使⽤到⼀些上线的⼯具,这样⽆疑也增⼤了我们的镜像体积。
⽐如我们现在有⼀个最简单的 golang 服务,需要构建⼀个最⼩的 Docker 镜像,源码如下:
[root@docker ~]# mkdir web02
[root@docker ~]# cd web02/
[root@docker web02]# vim app-server
[root@docker web02]# cat app-server
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
router := gin.Default()
router.GET("/ping", func(c *gin.Context) {
c.String(http.StatusOK, "PONG")
})
router.Run(":8080")
}
我们最终的⽬的都是将最终的可执⾏⽂件放到⼀个最⼩的镜像(⽐如 alpine )中去执⾏,怎样得到最终的编译好的⽂件呢?基于 Docker 的指导思想,我们需要在⼀个标准的容器中编译,⽐如在⼀个
Ubuntu 镜像中先安装编译的环境,然后编译,最后也在该容器中执⾏即可。
但是如果我们想把编译后的⽂件放置到 alpine 镜像中执⾏呢?我们就得通过上⾯的 Ubuntu 镜像将编译完成的⽂件通过 volume挂载到我们的主机上,然后我们再将这个⽂件挂载到 alpine 镜像中去。
这种解决⽅案理论上肯定是可⾏的,但是这样的话在构建镜像的时候我们就得定义两步了,第⼀步是先⽤⼀个通⽤的镜像编译镜像,第⼆步是将编译后的⽂件复制到 alpine 镜像中执⾏,⽽且通⽤镜像编译后的⽂件在 alpine 镜像中不⼀定能执⾏。
定义编译阶段的 Dockerfile :(保存为Dockerfile.build)
[root@docker web02]# vim Dockerfile.build
[root@docker web02]# cat Dockerfile.build
FROM golang
WORKDIR /go/src/app
ADD . /go/src/app
RUN go get -u -v github.com/kardianos/govendor
RUN govendor sync
RUN GOOS=linux GOARCH=386 go build -v -o /go/src/app/app-server
定义 alpine 镜像:(保存为Dockerfile.old)
[root@docker web02]# vim Dockerfile.old
[root@docker web02]# cat Dockerfile.old
FROM alpine:latest
RUN apk add -U tzdata
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
WORKDIR /root/
COPY app-server .
CMD ["./app-server"]
根据我们的执⾏步骤,我们还可以简单定义成⼀个脚本:(保存为build.sh)
[root@docker web02]# vim build.sh
[root@docker web02]# cat build.sh
#!/bin/sh
echo Building cnych/docker-multi-stage-demo:build
docker build -t cnych/docker-multi-stage-demo:build . -f Dockerfile.build
docker create --name extract cnych/docker-multi-stage-demo:build
docker cp extract:/go/src/app/app-server ./app-server
docker rm -f extract
echo Building cnych/docker-multi-stage-demo:old
docker build --no-cache -t cnych/docker-multi-stage-demo:old . -f Dockerfile.old
rm ./app-server
[root@docker web02]# chmod +x build.sh
[root@docker web02]# ll -d build.sh
-rwxr-xr-x 1 root root 423 2月 7 18:17 build.sh
[root@docker web02]# sh build.sh
当我们执⾏完上⾯的构建脚本后,就实现了我们的⽬标。http://192.168.200.8:8080/ping
有没有⼀种更加简单的⽅式来实现上⾯的镜像构建过程呢?Docker 17.05版本以后,官⽅就提供了一个新的特性: Multi-stage builds (多阶段构建)。 使⽤多阶段构建,你可以在⼀个Dockerfile中使⽤多个 FROM 语句。每个 FROM 指令都可以使⽤不同的基础镜像,并表示开始⼀个新的构建阶段。你可以很⽅便的将⼀个阶段的⽂件复制到另外⼀个阶段,在最终的镜像中保留下你需要的内容即可。
我们可以调整前⾯⼀节的 Dockerfile 来使⽤多阶段构建:(保存为Dockerfile)
[root@docker ~]# mkdir web03
[root@docker ~]# cd web03/
[root@docker web03]# vim Dockerfile
[root@docker web03]# cat Dockerfile
FROM golang AS build-env
ADD . /go/src/app
WORKDIR /go/src/app
RUN go get -u -v github.com/kardianos/govendor
RUN govendor sync
RUN GOOS=linux GOARCH=386 go build -v -o /go/src/app/app-server
FROM alpine
RUN apk add -U tzdata
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
COPY --from=build-env /go/src/app/app-server /usr/local/bin/app-server
EXPOSE 8080
CMD [ "app-server" ]
现在我们只需要⼀个 Dockerfile ⽂件即可,也不需要拆分构建脚本了,只需要执⾏ build 命令即可:
[root@docker web03]# docker build -t cnych/docker-multi-stage-demo:latest .
默认情况下,构建阶段是没有命令的,我们可以通过它们的索引来引⽤它们,第⼀个 FROM 指令从 0 开始,我们也可以⽤ AS 指令为阶段命令,⽐如我们这⾥的将第⼀阶段命名为 build-env ,然后在其他阶段需要引⽤的时候使⽤ --from=build-env 参数即可。
最后我们简单的运⾏下该容器测试:
[root@docker web03]# docker run --rm -p 8080:8080 cnych/docker-multi-stage-demo:latest
运⾏成功后,我们可以在浏览器中打开 http://192.168.200.8:8080/ping 地址,可以看到PONG返回。
现在我们就把两个镜像的⽂件最终合并到⼀个镜像⾥⾯了。