D04-Docker compose

D04-Docker compose

4.1 Compose install

4.2 Docker-Compose命令说明

4.3 Docker-Compose YAML语法使用说明

4.4 Docker-Compose使用实例

4.5 Docker Compose UI

4.6 测试环境转换示例


4 Docker compose

Docker Compose 是 Docker 容器进行编排的工具,定义和运行多容器的应用,可以一条命令启动多个容器。

使用Compose 基本上分为三步:

  1. Dockerfile 定义应用的运行环境
  2. docker-compose.yml 定义组成应用的各服务
  3. docker-compose up 启动整个应用

Compose 项目目前在 Github (https://github.com/docker/compose)上进行维护,目前最新版本是 1.21。

Compose 定位是“defining and running complex applications with Docker”,前身是 Fig,兼容 Fig 的模板文件。

Dockerfile 可以让用户管理一个单独的应用容器;而 Compose 则允许用户在一个模板(YAML 格式)中定义一组相关联的应用容器(被称为一个 project,即项目),例如一个 Web 服务容器再加上后端的数据库服务容器等。

该项目由 Python 编写,实际上调用了 Docker 提供的 API 来实现。

4.1 Compose install

4.1.2 PIP 安装

这种方式最为推荐。

执行命令。

$ sudo pip install -U docker-compose

安装成功后,可以查看 docker-compose 版本及命令的用法。

[root@node-pc1 ~]# docker-compose -v
docker-compose version 1.21.1, build 5a3f1a3
[root@node-pc1 ~]# docker-compose -h
Define and run multi-container applications with Docker.

Usage:
  docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
  docker-compose -h|--help

Options:
  -f, --file FILE             Specify an alternate compose file
                              (default: docker-compose.yml)
  -p, --project-name NAME     Specify an alternate project name
                              (default: directory name)
  --verbose                   Show more output
  --log-level LEVEL           Set log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
  --no-ansi                   Do not print ANSI control characters
  -v, --version               Print version and exit
  -H, --host HOST             Daemon socket to connect to

  --tls                       Use TLS; implied by --tlsverify
  --tlscacert CA_PATH         Trust certs signed only by this CA
  --tlscert CLIENT_CERT_PATH  Path to TLS certificate file
  --tlskey TLS_KEY_PATH       Path to TLS key file
  --tlsverify                 Use TLS and verify the remote
  --skip-hostname-check       Don't check the daemon's hostname against the
                              name specified in the client certificate
  --project-directory PATH    Specify an alternate working directory
                              (default: the path of the Compose file)
  --compatibility             If set, Compose will attempt to convert deploy
                              keys in v3 files to their non-Swarm equivalent

Commands:
  build              Build or rebuild services
  bundle             Generate a Docker bundle from the Compose file
  config             Validate and view the Compose file
  create             Create services
  down               Stop and remove containers, networks, images, and volumes
  events             Receive real time events from containers
  exec               Execute a command in a running container
  help               Get help on a command
  images             List images
  kill               Kill containers
  logs               View output from containers
  pause              Pause services
  port               Print the public port for a port binding
  ps                 List containers
  pull               Pull service images
  push               Push service images
  restart            Restart services
  rm                 Remove stopped containers
  run                Run a one-off command
  scale              Set number of containers for a service
  start              Start services
  stop               Stop services
  top                Display the running processes
  unpause            Unpause services
  up                 Create and start containers
  version            Show the Docker-Compose version information
View Code

 

添加 bash 补全命令。


$ curl -L https://raw.githubusercontent.com/docker/compose/1.21.1/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose

4.1.3 二进制包

发布的二进制包可以在 https://github.com/docker/compose/releases 找到。

下载后直接放到执行路径即可。

例如,在常见的 Linux 平台上。

$ sudo curl -L https://github.com/docker/compose/releases/download/1.21.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
$ sudo chmod a+x /usr/local/bin/docker-compose 

4.2 Docker-Compose命令说明

大部分命令都可以运行在一个或多个服务上。如果没有特别的说明,命令则应用在项目所有的服务上。

执行docker-compose [COMMAND] --help查看具体某个命令的使用说明。

基本的使用格式

docker-compose [options] [COMMAND] [ARGS...]

常用选项

-f, --file FILE           指定启动模版文件(一个非docker-compose.yml命名的yaml文件,默认为docker-compose.yml)
-p, --project-name NAME   指定一个替代项目名称 (默认是directory名)-d 以daemon的方式启动容器
--x-networking            (EXPERIMENTAL) 使用新的网络功能
--x-network-driver DRIVER (EXPERIMENTAL) 指定网络驱动程序,桥 (default: "bridge").
--verbose:输出详细信息
--version 打印版本并退出。

常用命令

概览

build 构建或重建服务
help 命令帮助
kill 杀掉容器
logs 显示容器的输出内容
port 打印绑定的开放端口
ps 显示容器
pull 拉取服务镜像
restart 重启服务
rm 删除停止的容器
run 运行一个一次性命令
scale 设置服务的容器数目
start 开启服务
stop 停止服务
up 创建并启动容器

详细

build
构建或重新构建服务。
服务一旦构建后,将会带上一个标记名,例如 web_db。
可以随时在项目目录下运行 docker-compose build 来重新构建服务。

help
获得一个命令的帮助。

kill
通过发送SIGKILL信号来强制停止服务容器。支持通过参数来指定发送的信号,例如 docker-compose kill -s SIGINT

logs
查看服务的输出。

port
打印绑定的公共端口。

ps
输出运行的容器列表。

pull
拉取服务镜像。

rm
删除停止的服务容器。

run
在一个服务上执行一个命令。例如:docker-compose run ubuntu ping docker.com将会启动一个ubuntu 服务,执行 ping docker.com 命令。

默认情况下,所有关联的服务将会自动被启动,除非这些服务已经在运行中。该命令类似启动容器后运行指定的命令,相关卷、链接等等都将会按照期望创建。

如果不希望自动启动关联的容器,可以使用 --no-deps 选项,例如 docker-compose run --no-deps web python manage.py shell 将不会启动 web 容器所关联的其它容器。

scale
设置同一个服务运行的容器个数。

通过 service=num 的参数来设置数量。例如:docker-compose scale web=2 worker=3

start
启动一个已经存在的服务容器。

stop
停止一个已经运行的容器,但不删除它。通过 docker-compose start可以再次启动这些容器。

restart
重启服务容器

up
构建,(重新)创建,启动,链接一个服务相关的容器。链接的服务都将会启动,除非他们已经运行。

默认情况, docker-compose up 将会整合所有容器的输出,并且退出时,所有容器将会停止。如果使用 docker-compose up -d ,将会在后台启动并运行所有的容器。

默认情况,如果该服务的容器已经存在, docker-compose up 将会停止并尝试重新创建他们(保持使用 volumes-from 挂载的卷),以保证 docker-compose.yml 的修改生效。
如果你不想容器被停止并重新创建,可以使用 docker-compose up --no-recreate。如果需要的话,这样将会启动已经停止的容器。 pause 暂停容器服务 version 显示Docker-Compose版本信息 环境变量 环境变量可以用来配置Compose的行为。 以DOCKER_开头的变量和用来配置 Docker 命令行客户端的使用一样。 COMPOSE_PROJECT_NAME 设置通过Compose启动的每一个容器前添加的项目名称,默认是当前工作目录的名字。 COMPOSE_FILE 设置要使用的 docker-compose.yml 的路径。默认路径是当前工作目录。 DOCKER_HOST 设置Docker daemon的地址。默认使用unix:///var/run/docker.sock,与Docker客户端采用的默认值一致。 DOCKER_TLS_VERIFY 如果设置不为空,则与 Docker daemon 交互通过 TLS 进行。 DOCKER_CERT_PATH 配置TLS通信所需要的验证(ca.pem、cert.pem 和 key.pem)文件的路径,默认是 ~/.docker 。 Docker-Compose命令对比 image vs build image:如果镜像在本地不存在,Compose 将会尝试pull这个镜像。 build:指定 Dockerfile 所在文件夹的路径。 Compose 将会利用它自动构建这个镜像,然后使用这个镜像。 links vs external_links links:链接到其它服务中的容器。使用服务名称(同时作为别名)或服务名称:服务别名 (SERVICE:ALIAS) 格式都可以。使用的别名将会自动在服务容器中的 /etc/hosts 里创建。 external_links:链接到 docker-compose.yml 外部的容器,甚至 并非 Compose 管理的容器。 ports vs expose ports 暴露端口信息。使用:宿主:容器 (HOST:CONTAINER)格式或者仅仅指定容器的端口(宿主将会随机选择端口)都可以。 当使用 HOST:CONTAINER 格式来映射端口时,如果你使用的容器端口小于 60 你可能会得到错误得结果,因为 YAML 将会解析 xx:yy 这种数字格式为 60 进制。所以建议采用字符串格式。 expose 暴露端口,但不映射到宿主机,只被连接的服务访问。 volumes vs volumes_from volumes 卷挂载路径设置。可以设置宿主机路径 (HOST:CONTAINER) 或加上访问模式 (HOST:CONTAINER:ro)。ro就是readonly的意思,只读模式。 volumes_from 从另一个服务或容器挂载它的所有卷。

 

大部分时候都可以直接通过该命令来启动一个项目。

默认情况,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>

来重新创建服务并后台停止旧服务,启动新服务,并不会影响到其所依赖的服务。

 


 

4.3 Docker-Compose YAML语法使用说明

默认的模板文件是 docker-compose.yml,其中定义的每个服务都必须通过image指令指定镜像或build指令(需要 Dockerfile)来自动构建。

默认的模板文件名称为 docker-compose.yml,格式为 YAML 格式。

version: "3"

services:
  webapp:
    image: examples/web
    ports:
      - "80:80"
    volumes:
      - "/data"

其它大部分指令都跟docker run中的类似。

image 使用的镜像
build 指定Dockerfile构建
command 启动执行命令
links 链接其他容器    
ports 端口映射
expose 暴露端口
volumes 挂载路径
volumes_from 从容器挂载
environment 环境变量

 

如果使用build指令,在Dockerfile中设置的选项(例如:CMD, EXPOSE, VOLUME, ENV 等) 将会自动被获取,无需在docker-compose.yml中再次设置。

build

这个是创建docker镜像时的选项,通过本地的dockerfile来创建,而不是通过image id来pull。
其中build还有一些小选项。

build:
  context: ./webapp
  dockerfile: Dockerfile-alternate
  args:
    - buildno=1
    - user=someuser

 

context上下文是docker build中很重要的一个概念。build构建镜像必须指定context。

context是 docker build 命令的工作目录。默认情况下,如果不额外指定 Dockerfile 的话,会将 Context 下的名为 Dockerfile 的文件作为 Dockerfile。

dockerfile选项是值得备选的dockerfile。args是一些提供的参数。

image: 使用的镜像

指定为镜像名称或镜像 ID。如果镜像在本地不存在,Compose 将会尝试拉去这个镜像。

例如:

image: ubuntu
image: orchardup/postgresql
image: a4bc65fd

 

links

链接到其它服务中的容器,使一个容器可以主动的去和另外一个容器通讯。使用服务名称(同时作为别名)或服务名称:服务别名 (SERVICE:ALIAS) 格式都可以。

links:
 - db
 - db:database
 - redis

 

使用的别名将会自动在服务容器中的 /etc/hosts 里创建。例如:

172.17.2.186  db
172.17.2.186  database
172.17.2.187  redis

相应的环境变量也将被创建。

external_links

链接到 docker-compose.yml 外部的容器,甚至 并非 Compose 管理的容器。参数格式跟 links 类似。

external_links:
 - redis_1
 - project_db_1:mysql
 - project_db_1:postgresql

 

expose

这个是给link用的,将一些端口暴露给link到这个container上的containers。暴露端口,但不映射到宿主机,只被连接的服务访问

expose:
    - "3000"
    - "8000"

 

ports

暴露端口信息,这个是将端口和本机端口映射的选项,写法如下,其实跟docker -p一样。

使用宿主:容器 (HOST:CONTAINER)格式或者仅仅指定容器的端口(宿主将会随机选择端口)都可以。

ports:
    - "3000"
    - "3000-3005"
    - "8000:8000"
    - "9090-9091:8080-8081"
    - "49100:22"
    - "127.0.0.1:8001:8001"
    - "127.0.0.1:5000-5010:5000-5010"

 

注:当使用 HOST:CONTAINER 格式来映射端口时,如果你使用的容器端口小于 60 你可能会得到错误得结果,因为 YAML 将会解析 xx:yy 这种数字格式为 60 进制。所以建议采用字符串格式。

environment:

设置环境变量。你可以使用数组或字典两种格式。

只给定名称的变量会自动获取它在 Compose 主机上的值,可以用来防止泄露不必要的数据。

environment:
  RACK_ENV: development
  SESSION_SECRET:

environment:
  - RACK_ENV=development
  - SESSION_SECRET

 

env_file

从文件中获取环境变量,可以为单独的文件路径或列表。

如果通过 docker-compose -f FILE 指定了模板文件,则 env_file 中路径会基于模板文件路径。

如果有变量名称与 environment 指令冲突,则以后者为准。

env_file: .env

env_file:
  - ./common.env
  - ./apps/web.env
  - /opt/secrets.env

 

环境变量文件中每一行必须符合格式,支持 # 开头的注释行。

# common.env: Set Rails/Rack environment
RACK_ENV=development

volumes

将本机的文件夹挂载到container中,这一点在使用zmq的ipc通讯方式时用到了。

volumes:
    # Just specify a path and let the Engine create a volume
        - /var/lib/mysql

    # Specify an absolute path mapping
        - /opt/data:/var/lib/mysql

    # Path on the host, relative to the Compose file
        - ./cache:/tmp/cache

    # User-relative path
        - ~/configs:/etc/configs/:ro

    # Named volume
        - datavolume:/var/lib/mysql

 

卷挂载路径设置。可以设置宿主机路径 (HOST:CONTAINER) 或加上访问模式 (HOST:CONTAINER:ro)。

volumes:
 - /var/lib/mysql
 - cache/:/tmp/cache
 - ~/configs:/etc/configs/:ro

volumes_from

从另一个服务或容器挂载它的所有卷。

volumes_from:
 - service_name
 - container_name

 

extends

基于已有的服务进行扩展。例如我们已经有了一个webapp服务,模板文件为 common.yml。

# common.yml
webapp:
  build: ./webapp
  environment:
    - DEBUG=false
    - SEND_EMAILS=false

编写一个新的 development.yml 文件,使用 common.yml 中的 webapp 服务进行扩展。

# development.yml
web:
  extends:
    file: common.yml
    service: webapp
  ports:
    - "8000:8000"
  links:
    - db
  environment:
    - DEBUG=true
db:
  image: postgres

后者会自动继承 common.yml 中的 webapp 服务及相关环节变量。

net(已弃用)

设置网络模式。使用和 docker client 的 –net 参数一样的值。

# 指定容器的网络类型,v1 使用 net ;v2 v3 使用network_mode

net: "bridge"
net: "none"
net: "container:[name or id]"
net: "host"

 

network_mode

设置网络模式。使用和 docker run 的 --network 参数一样的值。

network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"

 

networks

配置容器连接的网络。

version: "3"
services:

  some-service:
    networks:
     - some-network
     - other-network

networks:
  some-network:
  other-network:
networks:
      default:
        ipv4_address: 172.30.23.27

networks: 在 compose file V3中, 允许我们通过networks关键字定义一个基于 Docker0 网络的 subnet。

然后将我们的服务添加到这个subnet中。

这样做的好处实现了服务之间的隔离,一旦我们不需要这组服务了,我们可以通过命令“docker-compose down” 卸载服务和对应的subnet,他不会对其他的服务造成影响。

pid

跟主机系统共享进程命名空间。打开该选项的容器可以相互通过进程 ID 来访问和操作。

pid: "host"

dns

配置 DNS 服务器。可以是一个值,也可以是一个列表。

dns: 8.8.8.8
dns:
  - 8.8.8.8
  - 9.9.9.9

 

cap_add, cap_drop

添加或放弃容器的 Linux 能力(Capabiliity)。

cap_add:
  - ALL

cap_drop:
  - NET_ADMIN
  - SYS_ADMIN

 

dns_search

配置 DNS 搜索域。可以是一个值,也可以是一个列表。

dns_search: example.com
dns_search:
  - domain1.example.com
  - domain2.example.com

 

command

覆盖容器启动后默认执行的命令。

command: bundle exec thin -p 3000
command: echo "hello world"
 

secrets

存储敏感数据,例如 mysql 服务密码。

version: "3"
services:

mysql:
  image: mysql
  environment:
    MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
  secrets:
    - db_root_password
    - my_other_secret

secrets:
  my_secret:
    file: ./my_secret.txt
  my_other_secret:
    external: true

 

security_opt

指定容器模板标签(label)机制的默认属性(用户、角色、类型、级别等)。例如配置标签的用户名和角色名。

security_opt:
    - label:user:USER
    - label:role:ROLE

 

stop_signal

设置另一个信号来停止容器。在默认情况下使用的是 SIGTERM 停止容器。

stop_signal: SIGUSR1

sysctls

配置容器内核参数。

sysctls:
  net.core.somaxconn: 1024
  net.ipv4.tcp_syncookies: 0

sysctls:
  - net.core.somaxconn=1024
  - net.ipv4.tcp_syncookies=0 

ulimits

指定容器的 ulimits 限制值。

例如,指定最大进程数为 65535,指定文件句柄数为 20000(软限制,应用可以随时修改,不能超过硬限制) 和 40000(系统硬限制,只能 root 用户提高)。

 ulimits:
    nproc: 65535
    nofile:
      soft: 20000
      hard: 40000

 

container_name

指定容器名称。默认将会使用 项目名称_服务名称_序号 这样的格式。

container_name: docker-web-container

注意: 指定容器名称后,该服务将无法进行扩展(scale),因为 Docker 不允许多个容器具有相同的名称。

depends_on

解决容器的依赖、启动先后的问题。以下例子中会先启动 redis db 再启动 web

version: '3'

services:
  web:
    build: .
    depends_on:
      - db
      - redis

  redis:
    image: redis

  db:
    image: postgres

注意:web 服务不会等待 redis db 「完全启动」之后才启动。

 

healthcheck

通过命令检查容器是否健康运行。

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"]
  interval: 1m30s
  timeout: 10s
  retries: 3

 

labels

为容器添加 Docker 元数据(metadata)信息。例如可以为容器添加辅助说明信息。

labels:
  com.startupteam.description: "webapp for a startup team"
  com.startupteam.department: "devops department"
  com.startupteam.release: "rc3 for v1.0"

 

logging

配置日志选项。

logging:
  driver: syslog
  options:
    syslog-address: "tcp://192.168.0.42:123"

 

目前支持三种日志驱动类型。

driver: "json-file"
driver: "syslog"
driver: "none"
options 配置日志驱动的相关参数。

options:
  max-size: "200k"
  max-file: "10"

 

 

其它选项

working_dir, entrypoint, user, hostname, domainname, mem_limit, privileged, restart, stdin_open, tty, cpu_sharesv 这些都是和 docker run 支持的选项类似。

cpu_shares: 73
working_dir: /code
entrypoint: /code/entrypoint.sh
user: postgresql
hostname: foo
domainname: foo.com
mem_limit: 1000000000
privileged: true
restart: always
stdin_open: true
tty: true


为服务器指定一个静态IP
version: '3'

services:
  app:
    image: busybox
    command: ifconfig
    networks:
      app_net:
        ipv4_address: 172.16.238.10
        ipv6_address: 2001:3984:3989::10

networks:
  app_net:
    driver: bridge
    enable_ipv6: true
    ipam:
      driver: default
      config:
      -
        subnet: 172.16.238.0/24
      -
        subnet: 2001:3984:3989::/64

 




 

4.4 Docker-Compose使用实例

创建一个Wordpress应用,首先建立一个应用的目录

mkdir wordpress
cd wordpress

 

创建 docker-compose.yml

[root@node-pc1 wordpress]# cat docker-compose.yml 
version: '2'
services:
  db:
    image: mysql:5.7
    volumes:
      - "./data/db:/var/lib/mysql"
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: wordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress

  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    links:
      - db
    ports:
      - "8000:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_PASSWORD: wordpress

 

MySQL的数据目录挂载到当前目录下,./.data/db不存在时会自动创建

使用的是docker-compose up -d启动应用

[root@node-pc1 wordpress]# docker-compose up -d
Creating wordpress_db_1 ... done
Creating wordpress_wordpress_1 ... done

确认启动成功

[root@node-pc1 wordpress]# docker-compose ps
        Name                       Command               State          Ports        
-------------------------------------------------------------------------------------
wordpress_db_1          docker-entrypoint.sh mysqld      Up      3306/tcp            
wordpress_wordpress_1   docker-entrypoint.sh apach ...   Up      0.0.0.0:8000->80/tcp

 

访问应用

http://localhost:8000/

初始化设置后,就可以看到Wordpress的页面

 


 

4.5 Docker Compose UI

Docker Compose UI,一个可在网页上的直观的进行Docker Compose操作的项目。


 

https://www.ctolib.com/docker-compose-ui.html
https://github.com/francescou/docker-compose-ui

 

 

4.6 测试环境转换示例

docker run

docker run -itd --restart=always \
--net=macvlan_br0 --ip=21.1.7.102 \
--name=ump-test1 --hostname=ump-test2 \
--sysctl kernel.msgmnb=13107200 \
--sysctl kernel.msgmni=512 \
--sysctl kernel.msgmax=65536 \
--sysctl kernel.shmmax=69719476736 \
--sysctl kernel.sem='500 256000 250 1024' \
-v /mnt/update:/update \
172.28.2.2:4000/ump:20180413 \
/usr/sbin/sshd -D

 

docker-compose.yml

##启动应用 默认为docker-compose.yml
docker-compose up -d
##指定yml文件
docker-compose -f uat1-compose.yml up -d
##查看
docker-compose ps

 

创建macvlan,为容器分配和主机同一网段的IP,外部可直接访问

[root@node-pc1 compose]# cat docker-compose.yml 
version: '3'
services:
  ump-test1:
    image: 172.28.2.2:4000/ump:20180413
    volumes:
      - /mnt/update:/update
    restart: always
    hostname: ump1svc
#    network_mode: "macvlan_br0"
    networks:
      macvlan_br0:
        ipv4_address: "21.1.7.110"
#        ipv6_adress:...
    sysctls:
      - kernel.msgmnb=13107200
      - kernel.msgmni=512
      - kernel.msgmax=65536
      - kernel.shmmax=69719476736
      - kernel.sem=500 256000 250 1024
    command: /bin/bash -c /root/docker/run.sh
#networks:
#  macvlan_br0:
#    driver: macvlan

#docker network create -d macvlan --subnet=21.1.7.0/24 --gateway=21.1.7.254 -o parent=br0  macvlan_br0
networks:
  macvlan_br0:
    driver: macvlan
    driver_opts:
      parent: br0
#      gateway: 21.1.7.254
    ipam:
      config:
      - subnet: 21.1.7.0/24
[root@node-pc1 compose]# 

 

 

参考:https://blog.csdn.net/qq_36148847/article/details/79427878

macvlan的compose格式:https://mritd.me/2017/05/12/docker-uses-the-host-network-segment-ip/?utm_source=tuicool&utm_medium=referral

posted @ 2018-04-27 17:15  Cslc-DaweiJ  阅读(561)  评论(0)    收藏  举报