Docker

一 docker的基础

Docker 是一个开源的应用容器引擎,主要利用 linux 内核 namespace 实现沙盒隔离,用
cgroup 实现资源限制。
Docker 支持三种不同的镜像层次存储的 drivers:
aufs、devicemapper、btrfs ;
Aufs:
AUFS (AnotherUnionFS) 是一种 Union FS, 简单来说就是支持将不同目录挂载到同一个虚
拟 文 件 系 统 下 (unite several directories into a single virtual filesystem) 的 文 件 系 统 。 Aufs
driver 是 docker 最早支持的 driver,但是 aufs 只是 linux 内核的一个补丁集而且不太可以会
被合并加入到 linux 内核中。但是由于 aufs 是唯一一个 storage driver 可以实现容器间共享可
执行及可共享的运行库, 所以当你跑成千上百个拥有相同程序代码或者运行库时时候,aufs
是个相当不错的选择。
Device Mapper:
Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在
该机制下,用户可以很方便的根据自己的需要制定实现存储资源的管理策略 ( 详
见:http://www.ibm.com/developerworks/cn/linux/l-devmapper/index.html) 。
Device mapper driver 会创建一个 100G 的简单文件包含你的镜像和容器。每一个容器被限
制 在 10G 大 小 的 卷 内 。 ( 如 果 想 要 调 整 , 参
考 :http://jpetazzo.github.io/2014/01/29/docker-device-mapper-resize/ 。 中 文 译 文 :
http://zhumeng8337797.blog.163.com/blog/static/100768914201452405120107/ )
你可以在启动 docker daemon 时用参数-s 指定 driver:
docker -d -s devicemapper ;
Btrfs:
Btufs driver 在 docker build 可以很高效。但是跟 devicemapper 一样不支持设备间共享存
储(文档里是 does not share executable memory between devices)。
在 没 有 aufs 支 持 的 linux 发 行 版 本 上 (CentOS,opensuse 等 ) 安 装 docker 可 能 就 使 用 了
devicemapper driver。

二 实验操作

1 环境搭建 rhel7.3

[root@foundation39 docker]# uname -r
3.10.0-514.el7.x86_64
[root@foundation39 docker]# rpm -qa |grep docker
docker-ce-18.03.1.ce-1.el7.centos.x86_64

安装的过程中rhel7.3 系统会有以下报错:

docker:/usr/bin/docker:relocation 
error:/usr/bin/docker:symboldm_task_get_info_with_deferred_remove, version Base not defined in file libdevmapper.so.1.02 with link time reference

需要安装以下升级版本

container-selinux-2.21-1.el7.noarch.rpm
libsemanage-2.5-8.el7.x86_64.rpm
libsemanage-python-2.5-8.el7.x86_64.rpm
pigz-2.3.4-1.el7.x86_64.rpm
policycoreutils-2.5-17.1.el7.x86_64.rpm
policycoreutils-python-2.5-17.1.el7.x86_64.rpm

2 容器的管理

# docker run -it --name vm1 ubuntu bash 创建容器
# docker ps -a    查看容器进程
# docker attach vm1  连接容器
# docker top vm1     查看容器状态
# docker logs vm1 查看容器指令输出 -f 参数可以实时查看
# docker inspect vm1 查看容器详情
# docker stats vm1 查看容器资源使用率
# docker diff vm1 查看容器修改
# docker run -d --name vm1 ubuntu bash -c "while true; do echo hello; sleep 1; done"
后台运行
# docker stop vm1 停止容器
# docker start vm1 启动容器
# docker kill vm1 强制干掉容器
# docker restart vm1 重启容器
# docker pause/unpause vm1   暂停/恢复容器
# docker rm vm1    删除容器
# docker export vm1 > vm1.tar   导出容器
# docker import vm1.tar image    导入容器为镜像 image

3 镜像的管理

# docker search  查询镜像
# docker pull    拉取镜像
# docker push      推送镜像

镜像默认可以从 docker hub 上下载,这是 docker 官方的公共仓库,为我们免费提供了大量
已经容器化的应用镜像,避免我们重复的去造轮子。但是官方并没有在国内部署服务器,
如果你不走 vpn 的话真的是太慢了,报错和超时让人非常的郁闷。
本次实验都是走的阿里云的docker镜像国内缓存服务器。当然配置完后你得确保你当前主机能够上网!这样我们就可以直接从官网pull下你想要的镜像

4 数据卷管理

docker run 在创建容器时使用 -v 参数可以挂载一个或多个数据卷到当前运行的容器中,-v
的作用是将宿主机上的目录作为容器的数据卷挂载到容器中,使宿主机和容器之间可以共
享一个目录。

挂载数据卷到新创建的容器上:
# docker run -it --name james -v /tmp/data1:/data1 -v /tmp/data2:/data2 rhel7 /bin/bash
-v 参数可以重复使用,挂载多个数据卷到容器中,冒号前面的是宿主机的目录(本地目录
不存在 docker 会自动创建),冒号后面的是容器中的挂载目录。

数据卷容器:
# docker create --name data -v /tmp/sharedata:/sharedata rhel7 /bin/true
# docker run -it --name vm1 --volumes-from data rhel7 /bin/bash
# docker run -it --name vm2 --volumes-from data rhel7 /bin/bash

备份数据卷:
# docker run --rm --volumes-from data -v /tmp/backup:/backup rhel7 tar cf   /backup/test.tar/sharedata

5 网络管理

Docker 在启动时会创建一个虚拟网桥 docker0,默认地址为 172.17.0.1/16, 容器启动后都会
被桥接到 docker0 上,并自动分配到一个 IP 地址。

容器的四种网络模式:
bridge 桥接模式、host 模式、container 模式和 none 模式
启动容器时可以使用 --net 参数指定,默认是桥接模式。
以下是 docker 网络初始化的过程:

 

Bridge 桥接模式的实现步骤主要如下:
(1) Docker Daemon 利用 veth pair 技术,在宿主机上创建两个虚拟网络接口设备,假设为
veth0 和 veth1。而 veth pair 技术的特性可以保证无论哪一个 veth 接收到网络报文,都会将
报文传输给另一方。
(2) Docker Daemon 将 veth0 附加到 Docker Daemon 创建的 docker0 网桥上。保证宿主机的网络报文可以发往 veth0;
(3) Docker Daemon 将 veth1 添加到 Docker Container 所属的 namespace 下,并被改名为 eth0。
如此一来,保证宿主机的网络报文若发往 veth0,则立即会被 eth0 接收,实现宿主机到
Docker Container 网络的联通性;同时,也保证 Docker Container 单独使用 eth0,实现容器网
络环境的隔离性。

容器内的ip

当前真机的ip

Host 网络模式:
host 模式是 bridge 桥接模式很好的补充。采用 host 模式的 Docker Container,可以直接使用
宿主机的 IP 地址与外界进行通信,若宿主机的 eth0 是一个公有 IP,那么容器也拥有这个公
有 IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行 NAT 转换。当然,
有这样的方便,肯定会损失部分其他的特性,最明显的是 Docker Container 网络环境隔离性
的弱化,即容器不再拥有隔离、独立的网络栈。另外,使用 host 模式的 Docker Container 虽
然可以让容器内部的服务和传统情况无差别、无改造的使用,但是由于网络隔离性的弱
化,该容器会与宿主机共享竞争网络栈的使用;另外,容器内部将不再拥有所有的端口资
源,原因是部分端口资源已经被宿主机本身的服务占用,还有部分端口已经用以 bridge 网
络模式容器的端口映射。

从这里可以看出完全和当前主机的ip一致

也可以用下面这种更直观的方式

Container 网络模式:
(1) 查找 other container(即需要被共享网络环境的容器)的网络 namespace;
(2) 将新创建的 Docker Container(也是需要共享其他网络的容器)的 namespace,使用
other container 的 namespace。
Docker Container 的 other container 网络模式,可以用来更好的服务于容器间的通信。
在这种模式下的 Docker Container 可以通过 localhost 来访问 namespace 下的其他容器,传输
效率较高。虽然多个容器共享网络环境,但是多个容器形成的整体依然与宿主机以及其他
容器形成网络隔离。另外,这种模式还节约了一定数量的网络资源。但是需要注意的是,
它并没有改善容器与宿主机以外世界通信的情况。

None 网络模式:
网络环境为 none,即不为 Docker Container 任何的网络环境。一旦 Docker Container 采用了none 网络模式,那么容器内部就只能使用 loopback 网络设备,不会再有其他的网络资源。可以说 none 模式为 Docker Container 做了极少的网络设定,但是俗话说得好“少即是多”在没有网络配置的情况下,作为 Docker 开发者,才能在这基础做其他无限多可能的网络定制开发。这也恰巧体现了 Docker 设计理念的开放。

真机上也是什么都没有

在 none 网络模式下分配固定 ip:
netns 是在 linux 中提供网络虚拟化的一个项目,使用 netns 网络空间虚拟化可以在本地虚拟化出多个网络环境,目前 netns 在 lxc 容器中被用来为容器提供网络。使用 netns 创建的网络空间独立于当前系统的网络空间,其中的网络设备以及 iptables 规则等都是独立的,就好像进入了另外一个网络一样。

ip link add name veth0 type veth peer name veth1

\

ln -s /proc/10213/ns/net 10213

[root@foundation39 netns]# ls
10213
[root@foundation39 netns]# pwd
/var/run/netns

[root@foundation39 netns]# ip link set veth1 netns 10213 这里真机和容器建立连接
[root@foundation39 netns]# ip netns exec 10213 ip link set veth1 name eth0 更名

ip netns exec 10213 ip link set eth0 up

ip netns exec 10213 ip add add 172.17.0.100/24 dev eth0

ip netns exec 10213 ip route add default via 172.17.0.250

6 容器间互联

--link 参数可以在不映射端口的前提下为两个容器间建立安全连接, --link 参数可以连接一个
或多个容器到将要创建的容器。
--link 参数的格式为 --link name:alias,其中 name 是要链接的容器的名称,alias 是这个连
接的别名。

[root@foundation39 docker]# docker run -d --name vm1 nginx
395282a385e4c9f9a71c70418b9a9dc4d4ccb550ef0352e3874b5254299bd777
[root@foundation39 docker]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
395282a385e4        nginx               "nginx -g 'daemon of…"   4 seconds ago       Up 3 seconds        80/tcp              vm1
[root@foundation39 docker]# docker run -it --name vm2 --link vm1:nginx ubuntu
root@5941eb77c810:/# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
27: eth0@if28: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
root@5941eb77c810:/# env |grep nginx 
NGINX_NAME=/vm2/nginx
root@5941eb77c810:/# 

nginx源码编译生成镜像

Dockerfile 编写

vim Dockerfile

FROM rhel7
COPY dvd.repo /etc/yum.repos.d/dvd.repo
ADD nginx-1.14.0.tar.gz /mnt
RUN rpmdb --rebuilddb && yum install -y gcc pcre-devel openssl-devel make 
&& cd /mnt/nginx-1.14.0 
&& ./configure --prefix=/usr/local/nginx --with-http_ssl_module && make && make install && rm -rf /mnt/nginx-1.14.0 
&& yum remove -y gcc pcre-devel openssl-devel make && yum clean all
EXPOSE 80
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

 

当然也要有dvd.repo的yum源,因为安装的时候总是需要一些依赖包当然源码编译需要从网上下载比如:nginx-1.14.0.tar.gz

[root@foundation39 docker]# docker build -t nginx:v1 .
Sending build context to Docker daemon  1.806MB
Step 1/6 : FROM rhel7
 ---> 0a3eb3fde7fd
Step 2/6 : COPY dvd.repo /etc/yum.repos.d/dvd.repo
 ---> Using cache
 ---> 5a6cbd5050f7
Step 3/6 : ADD nginx-1.14.0.tar.gz /mnt
 ---> Using cache
 ---> 55fb438f0fbd
Step 4/6 : RUN rpmdb --rebuilddb && yum install -y gcc pcre-devel openssl-devel make && cd /mnt/nginx-1.14.0 && ./configure --prefix=/usr/local/nginx --with-http_ssl_module && make && make install && rm -rf /mnt/nginx-1.14.0 && yum remove -y gcc pcre-devel openssl-devel make && yum clean all
 ---> Running in c7421f8e6411
。。。。。
Complete!
Skipping unreadable repository '///etc/yum.repos.d/rhel7.repo'
Cleaning repos: dvd
Cleaning up everything
Removing intermediate container c7421f8e6411
 ---> a4da48f942f3
Step 5/6 : EXPOSE 80
 ---> Running in c77c6499b0a6
Removing intermediate container c77c6499b0a6
 ---> 19b99e4c8cdb
Step 6/6 : CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
 ---> Running in af01b29ce110
Removing intermediate container af01b29ce110
 ---> dff0e66110bc
Successfully built dff0e66110bc
Successfully tagged nginx:v1


[root@foundation39 docker]# docker images nginx
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
nginx               v1                  dff0e66110bc        About a minute ago   337MB
nginx               1.14.0              ecc98fc2f376        9 days ago           109MB
nginx               latest              c82521676580        3 months ago         109MB
[root@foundation39 docker]# docker history nginx:v1
IMAGE               CREATED              CREATED BY                                      SIZE                COMMENT
dff0e66110bc        About a minute ago   /bin/sh -c #(nop)  CMD ["/usr/local/nginx/sb…   0B                  
19b99e4c8cdb        About a minute ago   /bin/sh -c #(nop)  EXPOSE 80                    0B                  
a4da48f942f3        About a minute ago   /bin/sh -c rpmdb --rebuilddb && yum install …   190MB               
55fb438f0fbd        5 minutes ago        /bin/sh -c #(nop) ADD file:33a23abd712beadf0…   6.06MB              
5a6cbd5050f7        5 minutes ago        /bin/sh -c #(nop) COPY file:d5a1d5f41bce7d12…   75B                 
0a3eb3fde7fd        4 years ago                                                          140MB               Imported from -
[root@foundation39 docker]# docker run -d --name vm1 nginx:v1
f7fb2cc9f774666484a0f51590bd3d81b2ceba724591886757cb96f6f3c67c13
[root@foundation39 docker]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
f7fb2cc9f774        nginx:v1            "/usr/local/nginx/sb…"   6 seconds ago       Up 5 seconds        80/tcp              vm1

docker inspect vm1

"IPAddress": "172.17.0.2",

浏览器查看http://172.17.0.2/

 

但是在实际生产活动中,就仅仅一个服务,就占了337M的空间,那对内存资源来说是一种浪费!下来我尝试来压缩镜像,首先在刚才history中可以发现编译中这一层就占用了190mb,那就先做这一块的优化,可以先去掉debug产生的二进制文件。

在Dockerfile 增加  && sed -i 's/CFLAGS="CFLAGS -g"/#CFLAGS="CFLAGS -g"/g' auto/cc/gcc


发现并没有什么用!

那就继续优化,通过查找资料发现,安装的过程中会调用大量的系统自带的lib包,从而会产生大量垃圾文件

那就做了以下的优化!

FROM rhel7 as build  
COPY dvd.repo /etc/yum.repos.d/dvd.repo     向镜像中增加文件
ADD nginx-1.14.0.tar.gz /mnt ADD 命令支持添加本地的 tar 压缩包到容器中指定目录,压缩包会被自动解压为目录,也可以自动下载 URL 并拷贝到镜像
RUN rpmdb --rebuilddb && yum install -y gcc pcre-devel openssl-devel make && 
cd /mnt/nginx-1.14.0
&& sed -i 's/CFLAGS="CFLAGS -g"/#CFLAGS="CFLAGS -g"/g' auto/cc/gcc 
&& ./configure --prefix=/usr/local/nginx --with-http_ssl_module && make && make install && rm -rf /mnt/nginx-1.14.0 && yum remove -y gcc pcre-devel openssl-devel make 
&& yum clean all

FROM gcr.io/distroless/base
COPY --from=build /usr/local/nginx /usr/local/nginx
ADD build.tar /lib64/
EXPOSE 80      对外连接端口号
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"] 容器启动后执行的命令

gcr.io/distroless/base 这个镜像直接在官网上往下pull的 ,build.tar 包是在官方封装好的nginx中镜像中,运行容器之后查看后,把所有需要的lib文件,做成一个tar包。

突然少了很多!还得测试一下才能证明是ok的

[root@foundation39 docker]# docker run -it --name vm2 nginx:v2 bash
docker: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"bash\": executable file not found in $PATH": unknown.
[root@foundation39 docker]#

测试发现还是启动不了,怀疑是CMD 启动脚本的问题,修改几次后,还有一点问题,后续我在补充一下~

下面再提供一种别人的解决办法

FROM nginx:1.14.0 as base

# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
# ARG TIME_ZONE

RUN mkdir -p /opt/var/cache/nginx && \
    cp -a --parents /usr/lib/nginx /opt && \
    cp -a --parents /usr/share/nginx /opt && \
    cp -a --parents /var/log/nginx /opt && \
    cp -aL --parents /var/run /opt && \
    cp -a --parents /etc/nginx /opt && \
    cp -a --parents /etc/passwd /opt && \
    cp -a --parents /etc/group /opt && \
    cp -a --parents /usr/sbin/nginx /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libpcre.so.* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libc.so.* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libdl.so.* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libpthread.so.* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libcrypt.so.* /opt && \
    cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \
    cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \
    cp /usr/share/zoneinfo/Asia/Shanghai /opt/etc/localtime

FROM gcr.io/distroless/base

COPY --from=base /opt /

EXPOSE 80

ENTRYPOINT ["nginx", "-g", "daemon off;"]

7 Docker Compose

Docker Compose 将所管理的容器分为三层,工程(project),服务(service)以及容器
(contaienr)。Docker Compose 运行的目录下的所有文件(docker-compose.yml, extends 文
件或环境变量文件等)组成一个工程,若无特殊指定工程名即为当前目录名。一个工程当
中可包含多个服务,每个服务中定义了容器运行的镜像,参数,依赖。一个服务当中可包
括多个容器实例,Docker Compose 并没有解决负载均衡的问题,因此需要借助其他工具实
现服务发现及负载均衡。
Docker Compose 是一个用来创建和运行多容器应用的工具。使用 Compose 首先需要编写
Compose 文件来描述多个容器服务以及之间的关联,然后通过命令根据配置启动所有的容
器。

实验测试:

从网上下载docker-compose-Linux-x86_64-1.22.0

[root@foundation39 compose]# cd /usr/local/bin/
[root@foundation39 bin]# ls
docker-compose-Linux-x86_64-1.22.0  rht-vmctl  rht-vmicons  rht-vmsetkeyboard
[root@foundation39 bin]#

mkdir compose
vim docker-compose.yml
apache:
    build: ./web
    expose:
        - 80
nginx:
    image: nginx
    expose:
        - 80

haproxy:
    image: haproxy
    volumes:
        - ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
    links:
        - apache
        - nginx
    ports:
        - "8080:80"
    expose:
        - 80
~                       

mkdir web
cd web/
vim Dockerfile
FROM rhel7
EXPOSE 80
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y httpd && yum clean all
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]

当然还有有yum源

mkdir haproxy
vim haproxy.cfg
global
   log 127.0.0.1 local0
   log 127.0.0.1 local1 notice
defaults
  log global
  mode http
  option httplog
  option dontlognull
  timeout connect 5000ms
  timeout client 50000ms
  timeout server 50000ms
  stats uri /status
frontend balancer
    bind 0.0.0.0:80
    default_backend web_backends
backend web_backends
     balance roundrobin
    server web1 apache:80 check
    server web2 nginx:80 check



[root@foundation39 compose]# ls
docker-compose.yml  haproxy  web
[root@foundation39 compose]# pwd
/tmp/docker/compose
[root@foundation39 compose]# docker-compose-Linux-x86_64-1.22.0 up
Creating compose_apache_1 ... done
Creating compose_nginx_1  ... done
Creating compose_haproxy_1 ... done
Attaching to compose_nginx_1, compose_apache_1, compose_haproxy_1
apache_1   | AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message
haproxy_1  | <7>haproxy-systemd-wrapper: executing /usr/local/sbin/haproxy -p /run/haproxy.pid -f /usr/local/etc/haproxy/haproxy.cfg -Ds 

负载均衡测试:

[root@foundation39 compose]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                  NAMES
2bc2bd3c887e        haproxy             "/docker-entrypoint.…"   About a minute ago   Up About a minute   0.0.0.0:8080->80/tcp   compose_haproxy_1
3bd4944ba70f        nginx               "nginx -g 'daemon of…"   About a minute ago   Up About a minute   80/tcp                 compose_nginx_1
0c702e05b63a        compose_apache      "/usr/sbin/httpd -D …"   About a minute ago   Up About a minute   80/tcp                 compose_apache_1
[root@foundation39 compose]# 

浏览器访问http://172.25.254.39:8080/

8 Docker swarm

Swarm 是 Docker 公司在 2014 年 12 月初发布的一套较为简单的工具,用来管理 Docker 集
群,它将一群 Docker 宿主机变成一个单一的,虚拟的主机。Swarm 使用标准的 Docker API
接口作为其前端访问入口,换言之,各种形式的 Docker Client(docker client in go, docker_py,
docker 等)均可以直接与 Swarm 通信。Swarm 几乎全部用 Go 语言来完成开发。
Swarm deamon 只是一个调度器(Scheduler)加路由器(router),Swarm 自己不运行容器,它
只是接受 docker 客户端发送过来的请求,调度适合的节点来运行容器,这意味着,即使
Swarm 由于某些原因挂掉了,集群中的节点也会照常运行,当 Swarm 重新恢复运行之后,
它会收集重建集群信息。下面是 Swarm 的结构图:

实验环境

                          主机               角色
 172.25.39.11      Manager
172.25.39.12      worker
172,25.39.13

      worker

在manager端创建swarm环境,获取token

docker swarm init --advertise-addr=172.25.39.11

在其他两个worker端

docker swarm join --token 后面跟manager生成的token和172.25.39.11:2377

在集群运行的容器

[root@server1 ~]# docker images nginx
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              c82521676580        3 months ago        109MB


在集群上导入visualizer图形监控

[root@server1 ~]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                             PORTS
gih7njxxsku5        viz                 replicated          1/1                 dockersamples/visualizer:latest   *:8080->8080/tcp


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值