Docker 高级命令

Docker的基础操作

Compose

Docker Compose 使用的YAML 定义多服务应用,也可以使用JSON

命令

Docker Compose会使用目录名作为项目名称,而且会在所有资源名称加上前缀目录名_

启动 up

docker-compose up
    -d, --detach 在后台运行

停止并移除 down

docker-compose down
     --rmi TYPE :'all' 移除所有相关的镜像。 'local': 移除没image字段的镜像
      -v, --volumes : 删除在'volumes'部分中声明的命名卷和附加到容器的匿名卷。 

查看状态 ps

docker-compose psf

列出进程 top

docker-compose top

停止 stop

stop命令会停止容器但是不会删除资源

docker-compose stop

删除容器 rm

删除相关的容器和网络,但是不会删除卷和镜像

docker-compose rm 

重启 restart

docker-compose restart

语法

点击这里查看更多示例

Version

这个是必须指定的,而且总是位于第一行,他定义了文件格式的版本。

版本之间的兼容关系见此链接

version: "3.2"

Services

用于定义不同的服务。compose会将每个服务部署在各自的容器中,而且key作为容器名字的一部分。

  • build . 指定docker基于当前目录下Dockerfile中定义的指令来构建新镜像。
  • command 启动的命令
  • ports 指定映射的端口
  • networks 使docker可以将服务连接到指定的网络上,这个网络应该是已存在的。或者在Network中定义的网络,对于overlay来说,还需要定义一个attachable,这样独立的容器才能链接上它(compose部署的不是服务而是容器)。
  • volumes 挂载卷,卷应该是已存在的,或者在下面定义的。
  • image 指定一个镜像
services:
  web:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/code
      - logvolume01:/var/log
    links:
      - redis
  redis:
    image: redis

Networks

用于指引Docker创建新的网络,默认情况下会创建一个bridge网络。

networks:
    over-bet:
    driver: overlay
    attachable: true

Volumes

用于指引Docker创建新的卷。

volumes:
  logvolume01: {}
volumes:
  - .:/code
  - logvolume01:/var/log

Stack

Docker Stack 适用于大规模场景和生产环境。

Stack文件就是Docker Compose文件,但是要求version必须大于3.0。

StackCompose不同的是,Stack不支持构建,部署之前,所有的必须都要构建完成。

命令

部署 deploy

docker stack deploy -c file.yml STACK
#   -c,  Compose的位置,不指定则从stdin读取

管理

如果想要对service进行操作,不推荐直接使用命令,推荐是修改yml文件,然后重新部署。在重新部署中,只会更新存在表更的部分。

docker stack ls
docker stack ps
docker stack rm # 删除不会有确认,要谨慎。而且不会删除卷。

查看服务

docker stack services

语法

image

这个是唯一的必填字段。

image: ....

stop_grace_period

这个属性可以调整从发出SIGTERM信号到发出SIGKILL信号的时间间隔,默认是10秒。

stop_grace_period: 2m30s

volumes

用于挂载提前创建的卷,或主机目录到某个服务副本中。

volumes:
  - "/var/run/docker.sock:/var/run/docker.sock"

ports

默认情况下,所有的端口映射都是Ingress模式,如果想要使用Host模式,则要使用完整语法的写法。

ports:
    - "80:80"

ports:
    - target: 80
      publish: 80
      mode: host

secrets

密钥以普通文本的形式挂载到服务副本中。文件名就是target属性定义的名称。路径为/run/secrets/NAME

secrets:
  - source: revprox_cert
    target: revprox_cert
  - source: revprox_key
    target: revprox_key

服务内的 networks

指定副本连接的网络,网络相关定义必须位于顶级关键字neitowrk下, 如果不存在,会默认以overlay新建一个。

networks:
  - front-tier

networks:
  - front-tier
  - back-tier
  - payment

environment

这个关键字允许用户在服务副本中注入环境变量。

environment:
  USER: gordonuser
  DB_PASSWORD_FILE: /run/secrets/postgres_password
  DB: atsea

deploy

定义部署约束。部署约束是一种拓扑感知定时任务,目前swarm允许通过以下几种方式进行调度

  • 节点ID 例如:node.id==123
  • 节点名称 例如:node.hostname==abc
  • 节点角色 例如:node.role!=manager
  • 节点引擎标签 例如:engine.labels.operatingsystem==ubuntu20.04
  • 节点自定义标签 例如:node.labels.zone==p1
deploy:
  replicas: 2
  update_config:  # 定义了服务在滚动升级的时候具体如何才做
    parallelism: 2  # 每次更新的副本数
    failure_action: rollback  # 回滚,默认是pause,升级失败后阻止其他副本升级,还可以是continue
  placement:
    constraints:
      - 'node.role == worker'
  restart_policy: # 定义了容器异常退出的重启策略
    condition: on-failure # 非0返回值退出会立即重启(on-failure)
    delay: 5s     # 每次启动间隔
    max_attempts: 3 # 最多重试次数
    window: 120s  # 等待最多120秒来检测是否启动成功

volumes

密钥管理

只有swarm的管理节点才能使用docker secret命令。

密钥以普通文本的形式挂载到服务副本中。文件名就是配置文件中target属性定义的名称。

路径为/run/secrets/NAME

创建密钥

docker secret create [OPTIONS] SECRET [file|-]
#  -d, --driver string            Secret driver
#  -l, --label list               Secret labels
#      --template-driver string   Template driver

echo file.crt | docker secret create SECRET -
docker secret create SECRET file.crt

列出密钥

docker secret ls

删除密钥

docker secret rm SECRET
docker secret remove SECRET

Swarm

Raft共识算法

Swarm管理节点指南

HA(高可用)

swarm节点内置HA支持,swarm使用raft共识算法实现节点管理。

使用HA要注意:

  • 部署奇数个管理节点
  • 不要部署太多管理节点

    • 3 个 Manager 节点最多可以同时容忍 1 个 Manager 节点失效的情况下保证高可用。
    • 5 个 Manager 节点最多可以同时容忍 2 个 Manager 节点失效的情况下保证高可用。
    • N 个 Manager 节点最多可以同时容忍 (N−1)/2个 Manager 节点失效的情况下保证高可用。
    • Docker 建议的情况下,使用 7 个 Manager 节点就够了,否则会降低集群的性能。

服务命令

创建服务

docker service create 
    --name NAME  
    -p ... 
    --replicas N 
    --mode global # 使用全局模式,,每个节点只运行一个副本
    --network NETWORKNAME
    -d  # 立即退出而不是等待服务完成
    IMAGE
# -p, --publish
# -p 80:80
# --publish published=80,target=80,mode=host

列出服务

docker service ls
# ID             NAME      MODE         REPLICAS   IMAGE          PORTS
# xio5zrmcc7p0   nginx     replicated   5/5        nginx:latest   *:4480->80/tcp
# u0hfbk889yc4   test      replicated   1/1        redis:latest   

查看服务

docker service ps NAME
docker service inspect NAME # 查看更详细的信息

服务的扩缩容

docker service scale NAME=N

删除服务

docker service rm NAME

滚动升级

docker service 
    --images IMAGE
    --update-parallelism N 
    --update-delay TIME 
    NAME

查看日志

docker service logs NAME

如果使用第三方日志驱动,需要相应的日至平台工具查看日志。在创建的时候指定--logodriver--log-opts可以强某一个服务使用不同的日志驱动。

集群命令

创建集群

docker swarm init
    --advertise-addr 10.0.0.1:2377  # 指定其他节点连接到当前管理节点的IP和端口
    --listen-addr 10.0.0.1:2377     # 指定用来承载Swarm流量的IP和端口

其他帮助信息使用docker swarm init --help输出。

列出节点

docker node ls

管理节点

  • 将节点提为管理节点
docker node promote <NODE>
  • 将节点从管理者降级为普通节点
docker node demote <NODE>
  • 删除节点
docker node rm [-f] <NODE> [<NODE>...]

更新节点

更新节点的功能包括:

  • 修改节点可用性

    docker node update --availability <TYPE> <NODENAME>
    # TYPE 可以是以下三个值
    #     active : 正常工作的节点,可以给节点分配任务
    #     pause  : 不会分配新的任务,但是现有任务会正常运行
    #     drain  : 不会分配新的任务,关闭现有任务并将其安排在其他节点上。
  • 修改节点的LABEL

    docker node update --label-add LABEL NODENAME   # 给指定节点加入一个值为空的标签。
    docker node update --label-add foo --label-add bar worker1 # 增加两个标签。
    docker node update --label-add type=queue worker1 # 增加一个KV为 type=>queue 的标签。
    docker node update --label-rm LABEL NODENAME # 删除指定节点的一个标签。
  • 列出节点的LABEL

    # 列出所有节点
    docker node ls -q | xargs docker node inspect \
      -f '{{ .ID }} [{{ .Description.Hostname }}]: {{ .Spec.Labels }}'
      
    # 列出单个节点
    docker node inspect -f '{{ .Spec.Labels }}' <NODE>
  • 设置管理节点

    docker node update  --role worker NODENAME
    docker node update  --role manager NODENAME

锁定和解锁Swarm

开启锁定后,管理节点重启后需要解锁才能使用。因为用于加密 swarm 节点之间通信的 TLS 密钥和用于加密和解密磁盘上的 Raft 日志的密钥会加载到每个管理器节点的内存中。Docker使用所谓的 autolock 保护这些密钥。

  • 开启锁定

    docker swarm update --autoload=true
    # OR
    # 在创建的时候加入 --autoload
  • 关闭锁定

    docker swarm unlock
  • 查看当前的解锁密钥

    docker swarm unlock-key
  • 轮换密钥

    docker swarm unlock-key --rotate

加入集群

可以使用下文的列出加入密钥获取接入的命令。

docker swarm join --token <KEY>
#  --availability <string>  节点的可用状态 ("active"|"pause"|"drain") (默认是 active)

KEY由四个字段组成,使用字符-进行分割。

PREFIX - VERSION - SWARM ID -TOKEN

  • PREFIX :永远是SWMTKN,这样可以方便的匹配,避免发布到公共环境。
  • VERSION :表示了swarm的版本信息。
  • SWARM ID :是swarm认证信息的哈希值。
  • TOKEN :决定令牌是管理者还是工作者的准入令牌

对于join命令,要注意两个选项,分别是:

  • --advertise-addr 向外通告的地址。
  • --listen-addr 监听的地址。

如果服务器获取的是一个局域网地址,就需要注意这两个参数,配置错误可能会导致overlay网络错误。

加入集群前,要注意设置主机名

hostnamectl set-hostname <你想要的主机名>

加入成功后docker会返回类似的结果,代表加入成功。

This node joined a swarm as a worker.

列出加入密钥

docker swarm join-token worker # 列出作为worker加入此次节点的token
docker swarm join-token manager  # 列出作为manager加入此次节点的token

退出集群

docker swarm leave
# 管理节点退出要加 -f

Overlay网络

overlay 只能在swarm的管理节点可见

创建网络

docker network create -d/--driver overlay NAME

Docker 安全

Name Space

Linux Docker使用下列内核命名空间

  • PID

每个容器都拥有自己的进程树。命名空间内看不到其他容器的进程树。

  • NET

Docker使用这个命名空间提供隔离的网络栈。每个网络栈都有自己的接口ID地址端口地址路由表

  • MNT

每个容器都有互相隔离的根目录。

  • IPC

IPC提供共享内存,不同容器间也是独立的。

  • USER

Docker允许用户使用这个命名映射用户到主机不同的用户上。

  • UTS

使用UTS命名空间提供每个主机自己的主机名称。

Control Group

控制组用于限额限制

Capability

这个机制用来保证,用于在以root用户运行容器的同时,还移除非必须的root能力

Seccomp

Docker使用过滤模式的Seccomp来限制容器对宿主机内核发起的系统调用。

Docker 注意事项

  1. Docker 套接字位置 unix://var/run/docker.sock
  2. 判断自己是不是在Docker容器内部 A.cat /proc/1/cgroup | grep docker B.ls /.dockerenv
  3. 不要把 docker的 sock文件挂载到docker内部,或把dockerapi暴露给公网。
  4. 高危参数 --privileged 谨慎使用。
  5. 注意以下参数的使用

    --cap-add=SYS_ADMIN  启动时,允许执行mount特权操作,需获得资源挂载进行利用。
    --net=host           启动时,绕过Network Namespace
    --pid=host           启动时,绕过PID Namespace
    --ipc=host           启动时,绕过IPC Namespace