【狂神说Java】Docker最新超详细版教程通俗易懂(2) 2020-05-16 容器数据卷,Dockerfile,yum报错解决,发布镜像,自定义网络,部署Redis集群,Portainer

1、数据卷 初识Dockerfile

  • 以前是 commit 实现

Dockerfile就是用来构建docker镜像的构建文件!命令脚本!先体验一下!
通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个个的命令,每个命令都是一层!

新建dockerfile1

FROM centos

VOLUME ["volume01","volume02"]

CMD echo "---end---"

CMD /bin/bash

#创建—个dockerfile文件,名字可以随机建议Dockerfile
#文件中的内容指令(大写)参数
#这里的每个命令,就是镜像的一层!

构建 build

docker build -f dockerfile1 -t kuangshen/centos:1.0 .

# --file string             Name of the Dockerfile (Default is 'PATH/Dockerfile')
#  -t, --tag list                Name and optionally a tag in the 'name:tag' format

Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos
 ---> 5d0da3dc9764
Step 2/4 : VOLUME ["volume01","volume02"]
 ---> Running in 07052d98aa2a
Removing intermediate container 07052d98aa2a
 ---> 88a7bea16c13
Step 3/4 : CMD echo "----end----"
 ---> Running in 4837676c2b9b
Removing intermediate container 4837676c2b9b
 ---> 8dd170668b6c
Step 4/4 : CMD /bin/bash
 ---> Running in 419c914e2fec
Removing intermediate container 419c914e2fec
 ---> 661e51fdc915
Successfully built 661e51fdc915
Successfully tagged kuangshen/centos:1.0

运行容器 查看匿名数据卷

docker run -it 661e51fdc915 /bin/bash
ls -l
# 在 /目录下 有 volume01 和 volume02 目录
#这个目录就是我们生成镜像的时候自动挂载的,数据卷目录
# 在 volume01 创建一个文件
touch container11.txt

# 查看这个卷
docker inspect e5955415c7cc


 "Mounts": [
            {
                "Type": "volume",
                "Name": "627b0b26023ab4a640f57d51735b6153380962556f658d1f4a02d72b9bbf8efa",
                "Source": "/var/lib/docker/volumes/627b0b26023ab4a640f57d51735b6153380962556f658d1f4a02d72b9bbf8efa/_data",
                "Destination": "volume01",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "6c64746b327a8a98603009dddf0b841e77309460bda03e7a97841e83f58f9a40",
                "Source": "/var/lib/docker/volumes/6c64746b327a8a98603009dddf0b841e77309460bda03e7a97841e83f58f9a40/_data",
                "Destination": "volume02",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }


 "Volumes": {
                "volume01": {},
                "volume02": {}
            },


# 进入 /var/lib/docker/volumes/627b0b26023ab4af4a02d72b9bbf8efa/_data,如果有 新建的文件container11.txt

这个卷和外部一定有一个同步的目录!

  • 匿名挂载 (volume01 并不是起名字,而是 指定 容器内目录)
mounts
英
/maʊnts/
n.
加载的文件系统;山峰(mount 的复数)
v.
增长,装上,爬上,乘马(mount 的单三形式)
n.
(Mounts)人名;(英)芒茨

测试一下刚才的文件是否同步出去了!
这种方式我们未来使用的十分多,因为我们通常会构建自己的镜像!假设构建镜像时候没有挂载卷,

  • 说的没用吧

要手动镜像挂载 -v 卷名:容器内路径!

复习挂载数据卷的3种方式

# 全路径挂载
# -e 配置环境
docker run -d -p 3310:3306 
-v /home/mysql/conf:/etc/mysql/conf.d 
-v /home/mysql/data:/var/lib/mysql 
-e MYSQL_ROOT_PASSWORD=123456 
--name mysql01 mysql:5.7

#匿名挂载,同上。上面指定的 也相当于 /volume01
docker run -d -P --name nginx01 -v /etc/nginx nginx

#具名挂载
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx

docker volume ls #可以看到juming-nginx。叫做 具名挂载。

# 具名和匿名 都在宿主机的 /var/lib/docker/volumes 目录下

数据卷容器 --volumes-from

  • 相当于 继承了 父类

多个mysql同步数据!

centos01 父容器 数据卷容器:利用这个容器,给别的容器共享数据

  • centos02 实现数据同步到 01,数据共享
docker run -it --name docker01 kuangshen/centos:1.0
docker run -it --name docker02 --volumes-from docker01 kuangshen/centos:1.0
# docker01 叫做数据卷容器

# 之后 随便在一个 容器里 新建文件,会自动同步到 另一个容器

# 在新建一个容器,数据也是同步的
docker run -it --name docker03 --volumes-from docker01 kuangshen/centos:1.0

# 此时删除 docker01,d2 和 d3的数据都在
# 所有共享的文件,都是 双向拷贝

删除数据卷

docker voluem rm XXX

mysql 共享

# -e 配置环境
docker run -d -p 3310:3306 
-v /etc/mysql/conf.d #去掉宿主机的目录,变为匿名挂载
-v /var/lib/mysql 
-e MYSQL_ROOT_PASSWORD=123456 
--name mysql01 mysql:5.7


docker run -d -p 3310:3306 
-e MYSQL_ROOT_PASSWORD=123456 
--name mysql02
--volumes-from mysql01 #挂载到01
mysql:5.7

docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

结论∶
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。但是—旦你持久化到了本地,这个时候,本地的数据是不会删除的!

2、DockerFile

dockerfile是用来构建dokcer镜像的文件!命令参数脚本!构建步骤:
1、编写一个dockerfile 文件
2、docker build构建成为一个镜像
3、docker run运行镜像
4、docker push发布镜像(DockerHub、阿里云镜像仓库!)

随便搜一个如 centos,在版本处,点进入 即可看到。

https://hub.docker.com/

FROM scratch #最底层的镜像
ADD centos-7-x86_64-docker.tar.xz /

LABEL \
    org.label-schema.schema-version="1.0" \
    org.label-schema.name="CentOS Base Image" \
    org.label-schema.vendor="CentOS" \
CMD ["/bin/bash"]

很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像!官方既然可以制作镜像,那我们也可以!

构建过程

每个都是一层

  • 可写容器 container 下面打包后,启动它,就是 在加一个 可写容器
  • 镜像 Tomcat
  • 镜像 jdk
  • rootfs 基础镜像 (centos/ubuntu)
  • bootfs

基础知识∶
1、每个保留关键字(指令)都是必须是大写字母
2、执行从上到下顺序执行
3、#表示注释
4、每一个指令都会创建提交一个新的镜像层,并提交!

dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!Docker镜像逐渐成为企业交付的标准,必须要掌握!

DockerFile :构建文件,定义了一切的步骤,源代码
Dockerlmages :通过DockerFile构建生成的镜像,最终发布和运行的产品!
Docker容器∶容器就是镜像运行起来提供服务器

指令

FROM centos

VOLUME ["volume01","volume02"]

CMD echo "---end---"

CMD /bin/bash
BUILD:
FROM
MAINTAINER
COPY
ADD
RUN
ONBUILD
.dockerignore

Both:
WORKDIR
USER

RUN:
CMD
ENV
EXPOSE
VOLUME
ENTRYPOINT
both
det.
双方,两者
pron.
两者
conj.
…和…都;……和……都
adj.
两…,双…

maintainer
英
/meɪnˈteɪnə(r)/
n.
维修工;保持器;维护设备,维护员;(史)犯包揽诉讼罪者
FROM
·这个镜像的妈妈是谁?(指定基础镜像)

MAINTAINER
告诉别人,谁负责养它?(指定维护者信息)

RUN
你想让它干啥(在命令前面加上RUN即可)

ADD
给它点创业资金(COPY文件,会自动解压)

WORKDIR
·我是cd,今天刚化了妆(设置当前工作目录)

VOLUME
给它一个存放行李的地方(设置卷,挂载主机目录)

EXPOSE
它要打开的门是啥(指定对外的端口)

RUN
·奔跑吧,兄弟!(指定容器启动后的要干的事借)


FROM
#基础镜镜像,一切从这里开始构建

MAINTAINER
#镜像是谁写的,姓名+邮箱

RUN
#镜像构建的时侯需要运行的命令

ADD
#步骤: tomcat境像,这个tomcat压缩包!添加内容

WORKDIR
#镜像的工作目录。就是默认的目录

VOLUME
#挂载的目录

EXPOSE
#暴露端口配置


CMD
#指定这个容器启动的时候要运行的命令,只 有最后一个会生效,可被替代
比如配置的:ls -a
docker run -l #此 -l会替换掉 ls -a
#如果用:ENTRYPOINT 配置的, -l 会追加到后面 变成:ls -a -l

ENTRYPOINT
#指定这个容器启动的时候要运行的命令,可以追加命令

ONBUILD
#当构建一个被继承DockerFile这个时候就会运行ONBUILD 的指令。触发指令。

COPY
#类似ADD ,将我们文件拷贝到镜像中

ENV
#构建的时候设置环境变量!
#environment
#比如mysql -e设置密码

构建自己的centos

Docker Hub 中 99%镜像都是从这个基础镜像过来的FROM scratch),然后配置需要的软件和配置来进行的构建

FROM scratch #最底层的镜像
scratch
英
/skrætʃ/
v.
(用指甲)挠,轻抓;(用指甲或利器)抓破,划破;划出,刮出(痕迹);(用爪子)抓,刨;(鸟、哺乳动物,尤指鸡)
n.
(某人皮肤上的)划痕,划伤;刮痕,划痕;抓,挠;刮擦声 ;
  • mydockerfile-centos
FROM centos
MAINTAINER kuangshen<123456@qq.com>

#键值对
ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash
docker build -f dockerfile1 -t kuangshen/centos:1.0 .
docker build -f mydockerfile-centos -t mycentos:0.1 .

#命令docker build -f dockerfile文件路径 -t 镜像名:[tag]
# 现在构建因为centos8 yum源需要更新,没法装 vim
# 所以 先解决了 yum的问题。然后用 commit 从当前容器上 构建了一个 centos
# 然后 基于这个正常 centos ,就能用上面的 RUN yum -y install vim

docker run -it mycentos:0.2

# 默认/usr/local,就是 WORKDIR 设置的
# 如果不配置,默认是 / 根目录

# 查看 images 的构建过程
docker history 0483b7c819d4

# 看mysql 即可看到 mysql的挂载目录
# 通过docker搜索,点进入 是这样写的 VOLUME /var/lib/mysql
VOLUME [/var/lib/mysql]  #匿名挂载
# 当然看元数据信息也可以看到 这个默认的挂载
docker inspect 87e830b7df9d
# 进入这个默认的挂载。新建一个数据库,果然多了个文件
cd /var/lib/docker/volumes/425e1XX/_data

yum报错解决

Error: Failed to download metadata for repo ‘appstream’: Cannot prepare internal mirrorlist: No URLs in mirrorlist

cd /etc/yum.repos.d/

sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*

# 可以跳过这个步骤
# 如果已经安装了wget就不需要这一步
yum install wget –y
# 更新yum源为阿里源
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo

yum clean all

yum makecache
# 验证
yum install -y vim

# yum update -y 更新yum源

CMD 和 ENTRYPOINT

  • entry point
CMD
#指定这个容器启动的时候要运行的命令,只 有最后一个会生效,可被替代
比如配置的:ls -a
docker run -l #此 -l会替换掉 ls -a
#如果用:ENTRYPOINT 配置的, -l 会追加到后面 变成:ls -a -l

ENTRYPOINT
#指定这个容器启动的时候要运行的命令,可以追加命令
FROM centos
CMD ["ls","-a"] #RUN 的时候,就会执行这个命令
docker build -f dockerfile-cmd-test -t cmdtest .
docker run xxx


#想追加一个命令-ls -al
docker run dd8e4401d72f -l

# -l替换了CMD ["ls", "-a"]命令,-l不是命令所以报错
# 所以只好: docker run 140b3c8675a7 ls -al

# 如果使用 ENTRYPOINT 就可以 docker run -l

实战 Tomcat

1、准备镜像文件tomcat压缩包,jdk的压缩包!

2、编写dockerfile文件,官方命名Dockerfile

  • 就是 不用加 -f 指定了
Dockerfile
FROM centos
MAINTAINER kuangshen<12312@qq.com>

COPY readme.txt /usr/local/readme.txt

ADD jdk-8u271-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.70.tar.gz /usr/local/

#RUN yum -y install vim注意报错

ENV MYPATH /usr/local
WORKDIR $MYPATH

# 创建环境变量 JAVA_HOME
ENV JAVA_HOME /usr/local/jdk1.8.0_271

# 标准配置 export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
# 这里少配置了 . 。当前目录“.”不能丢,把当前目录丢掉也是常见的错误。
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

# 创建 CATALINA_HOME。CATALINA_BASH 感觉并没有用到
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.70
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.70

#标准配置:export PATH=$JAVA_HOME/bin:$PATH
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-9.0.70/bin/startup.sh && tail -f /usr/local/apache-tomcat-9.0.70/logs/catalina.out
build
docker build -t diytomcat:0.1

docker run -d -p 9090:8080 
--name diytomcat01
-v /home/diytomcat/test:
   /usr/local/apache-tomcat-9.0.70/webapps/test
   
-v /home/diytomcat/tomcatlogs/:
   /usr/local/apache-tomcat-9.0.70/logs
diytomcat:0.1

docker run -d -p 9090:8080 --name diytomcat01 -v /home/diytomcat/build/tomcat/test:/usr/local/apache-tomcat-9.0.70/webapps/test -v /home/diytomcat/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.70/logs diytomcat:0.1

# 启动成功后,即可访问。
测试数据卷
cd /home/diytomcat/build/tomcat/test
mkdir WEB-INFO
vim web.xml

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
</web-app>

cd ..
vim index.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <title>JSP - Hello World</title>
</head>
<body>
<h1><%= "Hello World!" %>
</h1>
<br/>
<a href="hello-servlet">Hello Servlet</a>

<form action="/servlet/login" method="post">
    <input type="text" name="username">
    <input type="submit">
</form>
<% System.out.println("hahahah"); %>


</body>
</html>
#之后访问:http://192.168.44.147:9090/test/,即可看到
#进入日志目录: tail -f catalina.out,即可看到打印的日志。
    
#因为dockerfile的最后指定了 tail -f xxx
 docker attach ab574399cb12 #会进入容器的那个终端,访问Tomcat,也能看到日志。

Tomcat的核心

Tomcat的核心分为3个部分:
(1)Web容器---处理静态页面;
(2)catalina --- 一个servlet容器-----处理servlet;
(3)还有就是JSP容器,它就是把jsp页面翻译成一般的servlet。

发布自己的镜像

DockerHub

https://hub.docker.com/

docker login -u xxx
#输入密码
Login Succeeded

docker push 自己账户名/hello-world

# 起名字
docker tag xxxx kuangshen/diytomcat:1.0

# 即可推送成功
docker push 自己的账户名/my-hello-world:0.0.1

docker logout 退出
发布到阿里云

阿里云镜像服务上
1、登录阿里云
2、找到容器镜像服务

3、创建命名空间

4、创建容器镜像

  • 然后 按照 阿里的教程即可
 登录阿里云Docker Registry
$ docker login --username=xxx registry.cn-hangzhou.aliyuncs.com
用于登录的用户名为阿里云账号全名,密码为开通服务时设置的密码。

您可以在访问凭证页面修改凭证密码。

2. 从Registry中拉取镜像
$ docker pull registry.cn-hangzhou.aliyuncs.com/alidemowztest/tenkai-test-01:[镜像版本号]

3. 将镜像推送到Registry
$ docker login --username=xxx registry.cn-hangzhou.aliyuncs.com

$ docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/alidemowztest/tenkai-test-01:[镜像版本号]
## 我的测试。然后再push 这一长串,果然可以
docker tag feb5d9fea6a5 registry.cn-hangzhou.aliyuncs.com/alidemowztest/tenkai-test-01:0.0.1

$ docker push registry.cn-hangzhou.aliyuncs.com/alidemowztest/tenkai-test-01:[镜像版本号]
请根据实际镜像信息替换示例中的[ImageId][镜像版本号]参数。

4. 选择合适的镜像仓库地址
从ECS推送镜像时,可以选择使用镜像仓库内网地址。推送速度将得到提升并且将不会损耗您的公网流量。

如果您使用的机器位于VPC网络,请使用 registry-vpc.cn-hangzhou.aliyuncs.com 作为Registry的域名登录。

5. 示例
使用"docker tag"命令重命名镜像,并将它通过专有网络地址推送至Registry。

$ docker images
REPOSITORY                                                         TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
registry.aliyuncs.com/acs/agent                                    0.7-dfb6816         37bb9c63c8b2        7 days ago          37.89 MB
$ docker tag 37bb9c63c8b2 registry-vpc.cn-hangzhou.aliyuncs.com/acs/agent:0.7-dfb6816
使用 "docker push" 命令将该镜像推送至远程。

$ docker push registry-vpc.cn-hangzhou.aliyuncs.com/acs/agent:0.7-dfb6816

3、 总结

Dockerfile——build——Images——run——Containers

  • Containers——commit——Images
  • 镜像 起 tag 又变成一个镜像(只是一个引用,一删除同时删除)
  • 容器:start stop restart

Images——push——Docker registry

  • 拉取为 pull
  • 镜像 save 保存为 backup.tar
    • load 是从 backup.tar 加载。
save 和 load
docker save --help
Usage:  docker save [OPTIONS] IMAGE [IMAGE...]
Save one or more images to a tar archive (streamed to STDOUT by default)
Options:
  -o, --output string   Write to a file, instead of STDOUT

docker load --help
Usage:  docker load [OPTIONS]
Load an image from a tar archive or STDIN
Options:
  -i, --input string   Read from tar archive file, instead of STDIN
  -q, --quiet          Suppress the load output
docker save -o ./hello-world.tar hello-world

docker load -i ./hello-world.tar

4、Docker 网络

  • 删除容器和镜像
docker rmi -f $(docker images -aq)

基本知识 172.17 或18

ip addr
1: lo:  #本机回还地址
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host

2: ens33:  #或 eth0@if262 内网地址。下面新生成的vethc@if261
    inet 192.168.44.147/24 brd 192.168.44.255 scope global noprefixroute ens33

3: docker0: #docker地址,相当于路由器
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
docker run -d -P --name tomcat01 tomcat:9.0

docker exec -it tomcat01 ip addr
docker exec -it tomcat01 hostname -I
#可以查看到ip
172.17.0.2

#查看容器的内部网络地址ip addr ,发现容器启动的时候会得到一个 eth0@if262 ip地址,docker分配的!

#linux可以ping 通docker容器内部

宿主机和容器 网卡

1、我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0

桥接模式,使用的技术是evth-pair技术!
再次测试ip addr,多了一个 veth XXX 网卡。

# 87是编号 和 if86。 和 容器内的 网卡是对应的。
87: vethb57e7b8@if86: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether c2:72:b6:75:2b:56 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::c072:b6ff:fe75:2b56/64 scope link
       valid_lft forever preferred_lft forever

2、在启动一个容器测试,发现又多了一对网卡~!

docker run -d -P -it --name centos02 centos #启动时,记得带it
docker exec -it centos02 ip addr

 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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
92: eth0@if93: <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 link-netnsid 0
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
 ip addr #再次 看宿主机网卡,会多了一个。 和 上面的对应。
 #宿主机:93: veth629c860@if92
 #容器:92: eth0@if93
93: veth629c860@if92: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether 42:7b:d0:7f:7c:61 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::407b:d0ff:fe7f:7c61/64 scope link
       valid_lft forever preferred_lft forever
  • 每个容器 和 宿主机 都对接 接口。
    • 这样 宿主机 和 各个容器,以及各个容器之间,都是可以ping 通。
docker exec -it tomcat02 ping 172.18.0.2 #直接用 tomcat02 ping
# tomcat02 的ip 是 172.18.0.3
#结论:容器和容器之间是可以互相ping通的!

# 但并不是直连的。 通过网卡映射 访问到 宿主机 172.17.0.1,宿主机在转发到 要通信的网卡。
#结论: tomcat01和tomcat02是公用的一个路由器,docker0。
#所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用IP


# 我们发现这个容器带来网卡,都是—对对的
# evth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一段连着协议,一段彼此相连
# 正因为有这个特性,evth-pair 充当一个桥梁,连接各种虚拟网络设备的
# openstac,Docker容器之间的连接,oV5的连接,都是使用evth-pair 技术

小结
Docker使用的是Linux的桥接,宿主机中是一个Dokcer容器的网桥docker0。

  • 大约能分配 65535

Docker 中的所有的网络接口都是虚拟的。虚拟的转发效率高!|

– link

思考一个场景,我们编写了一个微服务,database url=ip:,项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以名字来进行访问容器?

docker exec -it tomcat02 ping tomcat01 #直接ping不通

# 使用 --link后,即可ping通
docker run -it -d -P --name centos04 --link centos02 centos
docker exec -it centos04 ping centos02
# 注意:因为 centos02 启动时 为配置,还无法ping 通 04

docker exec -it centos02 ping centos04
ping: centos04: Name or service not known


docker network ls
docker network inspect xxxxx #看网卡里的配置

"IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16", #大概255*255个
                    "Gateway": "172.17.0.1"
                }
            ]
        },
  # 可以看到所有容器的IP
 "Containers": {
            "0031d56555b36c8f5b2ccf512320f01f0872c0d2d224e2bf1ad79682facaa76a": {
                "Name": "centos02",
                "EndpointID": "7c936a05d26846672ba14e3a36c192427bd04374a5e428cfeca51d4a58f60507",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "ef1bacd516033eec060a690d33d07c480465b3ff0d24c092cdeaac65cf81b865": {
                "Name": "tomcat01",
                "EndpointID": "d8961fbcd917e0f185d4be45715ae3a0040634798aa24709299b2b346d21f940",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        }
docker inspect c578fa32f5a4  #在 centos04,可以找到 02的信息


            "Links": [
                "/centos02:/centos04/centos02"
            ],
            
docker exec -it centos04 cat /etc/hosts #即可发现原理
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3      centos02 0031d56555b3
172.17.0.5      c578fa32f5a4

本质探究:–link就是我们在hosts配置中增加了一个172.18.0.3 tomcat02 312857784cd4

我们现在玩Docker已经不建议使用–link 了 !

自定义网络!不使用docker0 !
docker0问题:他不支持容器名连接访问!

自定义网络

基本知识
docker network ls
docker network rm mynet

网络模式
bridge :桥接docker 。 0.2 和 0.3 不能访问,通过 0.1 路由IP 访问

  • 自己创建的 也使用 桥接

none :不配置网络

host :和宿主机共享网络

container :容器内网貉连通!(用的少!局限性大 )

docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
ee3c31d14c0b   bridge    bridge    local
3521b736c297   host      host      local
42e41dd1d8f1   none      null      local
 docker network --help

Usage:  docker network COMMAND

Manage networks

Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks
创建 和 启动 network create
#我们直接启动的命令--net bridge,而这个就是我们的docker0
docker run -d -P --name tomcat01 --net bridge tomcat

docker network create 
--driver bridge 
--subnet 192.168.0.0/16 #192.168.0.2 —— 192.168.255.254
--gateway 192.168.0.1
mynet

docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet

docker network ls
#03e3a8ac1986   mynet     bridge    local
 
docker network inspect mynet
docker run -it -d -P --name centos-net-01 --net mynet centos
docker exec -it ccb65262f490 ip addr #即可看到 IP是用了自己的网络

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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
101: eth0@if102: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:c0:a8:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.0.2/16 brd 192.168.255.255 scope global eth0
       valid_lft forever preferred_lft forever

# 查看网络的 Containers 属性,即可看到这个 IP
docker network inspect mynet

[
    {
        "Name": "mynet",
        "Id": "03e3a8ac1986138c0b31cfa1638f69021b1278599413abf6f29e9a1a58e204c6",
        "Created": "2023-01-09T22:40:15.848154138-05:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "ccb65262f4905d79c72621f45904d4fd9ee492ae8ddf31c134557e72f581492e": {
                "Name": "centos-net-01",
                "EndpointID": "e9439983e9d8ee7e51ba8671d4c279fa479d1735058916aba004df5d525d8bac",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
docker run -it -d -P --name centos-net-02 --net mynet centos

# 自定义网络都是 可以 ping 通的
docker exec centos-net-02 ping centos-net-01
docker exec -it centos-net-02 ping centos-net-01

我们自定义的网络docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络!
好处:
redis -不同的集群使用不同的网络,保证集群是安全和健康的mysql -不同的集群使用不同的网络,保证集群是安全和健康的

网络连接 connect

默认:启动网络启动两个容器 如 centos1

  • centos1如何 和 我们的 mynet 通信?
  • 网络 要打通
docker network connect --help

Usage:  docker network connect [OPTIONS] NETWORK CONTAINER

Connect a container to a network

Options:
      --alias strings           Add network-scoped alias for the container
      --driver-opt strings      driver options for the network
      --ip string               IPv4 address (e.g., 172.30.100.104)
      --ip6 string              IPv6 address (e.g., 2001:db8::33)
      --link list               Add link to another container
      --link-local-ip strings   Add a link-local address for the container
docker run -it -d -P --name centos01 centos
# 打通后,即可 相互ping通
docker network connect mynet centos01
docker exec -it centos-net-02 ping centos01

#1个容器两个ip地址
docker network inspect mynet #即可看到,多了一个 centos01 的 IP
        "Containers": {
            "14ffd86527d5267c872f2dfa05dfbbc9cfe75f51efb11e6e110b7a2bb8506a5b": {
                "Name": "centos01",
                "EndpointID": "3be5ce3e0323244505c75777e30742bd37d8cab31d334be102daa2c596f6a049",
                "MacAddress": "02:42:c0:a8:00:04",
                "IPv4Address": "192.168.0.4/16",
                "IPv6Address": ""
            },

结论∶假设要跨网络操作别人,就需要使用docker neIwork connect连通!。。|

5. 部署Redis集群

分片+高可用+负载均衡

3主3从,一个主机,都有一个从。主机挂了 从机上。

创建网卡和配置

# 创建网卡
docker network create redis --subnet 172.38.0.0/16

for port in $(seq 1 6); \ #循环1-6
do \
mkdir -p /mydata/redis/node-${port}/conf #在宿主机创建 xxx/config
touch /mydata/redis/node-${port}/conf/redis.conf #创建配置文件
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf #在配置文件写数据
port 6379 #端口
bind 0.0.0.0 #本机IP
cluster-enabled yes #开启集群
cluster-config-file nodes.conf #使用nodes.conf配置
cluster-announce-ip 172.38.0.1${port} #ip
cluster-announce-port 6379 #端口
cluster-announce-bus-port 16379 #总线端口
appendonly yes #只是添加属性
EOF
done

EOF一般指文件结尾。 文件结尾(英语:End of File,缩写为EOF

循环 启动


#老师的版本,下载不下来,就不下载了。 redis:5.0.9-alpine3.11
for port in $(seq 1 6); \
do \
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} redis redis-server /etc/redis/redis.conf;
done

# 把port 换成1,就是启动第一个
#对外暴露在 6317端口,和 16371 端口。
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \ #容器的 data挂载在 node-1/data下
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \ #配置文件 也挂载到对应的配置
#使用 自定义的redis网络,指定ip,运行的是 redis 。启动后:执行 redis-server,配置文件为redis.conf
-d --net redis --ip 172.38.0.11 redis redis-server /etc/redis/redis.conf;


因为:和 宿主机是同一个目录。
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf

port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-announce-ip 172.38.0.11
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes

测试集群

docker exec -it redis-1 /bin/sh #redis 没 bash,用sh

# 创建集群,分片为1
redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1

redis-cli -c #连接集群
cluster info #集群信息
cluster nodes #节点信息

set a b
-> Redirected to slot [15495] located at 172.38.0.13:6379
OK

#把 redis-3 服务器停了
docker stop f24da9f26b52
#重连,客户端
redis-cli -c
get a #依然能获取到,从机 会顶上去。

cluster nodes #13IP失败。14变成了主
b5e51538e03810b186311cd2b75ab659a240a7e5 172.38.0.14:6379@16379 myself,master - 0 1673330840000 7 connected 10923-16383
efceaccdacc75632e6221a49422d99981c839588 172.38.0.13:6379@16379 master,fail - 1673330710245 1673330705046 3 connected

idea编写Dockerfile

FROM java:8

COPY *.jar /app.jar

CMD ["--server.port=8080"]

EXPOSE 8080

ENTRYPOINT ["java","-jar","/app.jar"]
docker build -t boot-demo-01:0.0.1 .
docker run -d -P --name boot1 boot-demo-01:0.0.1

Docker Compose和Swarm 和 CI/CD Jenkins

  • Compose 容器编排
  • Swarm 集群部署

Docker-Compose

是什么

Docker-Compose是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。

Compose 是 Docker公司推出的一个工具软件,可以管理多个Docker容器组成一个应用。你需要定义一个YAML格式的配置文件docker-compose.yml,写好多个容器之间的调用关系。然后,只要一个命令,就能同时启动/关闭这些容器

docker compose.yml

Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML格式)来定义一组相关联的应用容器为一个项目
( project)。
可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。Docker-Compose解决了容器与容器之间如何管理编排的问题。

官网

https://docs.docker.com/compose/compose-file/compose-file-v3/

安装:

https://docs.docker.com/compose/install/

  • 这里用 yum 也可以直接安装
sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
  • 卸载
sudo rm /usr/local/bin/docker-compose

核心概念

一文件

docker-compose.yml

compose
英
/kəmˈpəʊz/
v.
组成,构成;作曲;撰写(信、诗或演讲稿);使镇静,使平静;为(照片、图像)构图;排版,排稿

两要索:

服务( service)

  • 一个个应用容器实例,比如订单微服务、库存微服务、mysql容器、nginx容器或者redis容器

工程( proiect)

  • 由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml文件中定义。

使用步骤

编写Dockerfile定义各个微服务应用并构建出对应的镜像文件使用docker-compose.yml

定义一个完整业务单元,安排好整体应用中的各个容器服务。最后,执行docker-compose up命令

来启动并运行整个应用程序,完成一键部署上线

Compose常用命令:使用 docker compose 才能运行
docker-compose -h
#查看帮助

docker-compose up
#启动所有docker-compose服务
docker-compose up -d
#启动所有docker-compose服务并后台运行

docker-compose down
#停止并删除容器、网络、卷、镜像。

docker-compose exec yml里面的服务id
#进入容器实例内部 docker-compose exec docker-compose.yml文件中写的服务id /bin/bash


docker-compose ps
#展示当前docker-compose编排过的运行的所有容器

docker-compose top
#展示当前docker-compose编排过的容器进程

docker-compose logs yml里面的服务id
#查看容器输出日志

dokcer-compose config #检查配置

dokcer-compose config -q #检查配置,有问题才有输出

docker-compose restart #重启服务
docker-compose start # 启动服务docker-compose stop#停止服务

Portainer

监控

统计

Portainer是一款轻量级的应用,它提供了图形化界面,用于方便地管理Docker环境,包括单机环境和集群环境。

https://www.portainer.io/
https://docs.portainer.io/v/ce-2.9/start/install/server/docker/linux

docker命令安装Z
第一次登录需创建admin,访问地址: xX×.XXX.XXX.XXX:9000Z设置admin用户和密码后首次登陆团

选择local选项卡后本地docker详细信息展示

上一步的图形展示,能想得起对应命令吗?

Docker图形化界面管理工具!提供一个后台面板供我们操作!

portainer
'pɔ:teinə/
n.
集装箱岸吊,码头货柜起重机

Rancher ( CI/CD再用)

# 百度的。下面的 加了-ce 和 没加一样。下载下来都是 portainer/portainer
docker run -d  --name portainer -p 8000:8000 -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v /app/portainer_data:/data --restart always --privileged=true portainer/portainer-ce

# 老师的
# -v是挂载
docker run -d -p 8088:9000
--restart always #systemctl restart docker ,重启docker后,容器还在。
-v /var/run/docker.sock:/var/run/docker.sock
--privileged=true 
portainer/portainer

#尚硅谷老师的,比百度。
#多加了:-p 8000:8000
#容器为:portainer/portainer


大约在0.6版,privileged被引入docker。
使用该参数,container内的root拥有真正的root权限。
甚至允许你在docker容器中启动docker容器。
docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          12        3         3.455GB   3.326GB (96%)
Containers      8         1         197B      197B (100%)
Local Volumes   1         0         0B        0B
Build Cache     0         0         0B        0B


docker stack

  • 包含了 docker compose

Docker Compose,它是用来进行一个完整的应用程序相互依赖的多个容器的编排的,但是缺点是不能在分布式多机器上使用;我们也介绍了Docker swarm,它构建了docker集群,并且可以通过docker service在不同集群节点上运行容器服务,但是缺点是不能同时编排多个服务。

我们一个完整的应用需要的服务往往不止一个,通过docker service 命令来部署的话会很麻烦,所以这里要讲一下 Docker Stack,它用于向swarm集群部署完整的应用程序堆栈,可以在分布式多机器上同时编排多个有依赖关系的服务。

Stack 能够在单个声明文件中定义复杂的多服务应用,还提供了简单的方式来部署应用并管理其完整的生命周期:初始化部署 -> 健康检查 -> 扩容 -> 更新 -> 回滚,以及其他功能!可以简单地理解为Stack是集群下的Compose。

Docker Stack 编排依赖于声明文件,其实也就是Docker Compse文件,不过Stack对于Compose文件有一个要求,文件的规范版本(顶层关键字version)必须是“3.0”或以上,而且一些Docker Compse文件中的关键字不受支支持

CIG

7.Docker容器监控之
CAdvisor+lnfluxDB+Granfana

advisor
英
/ədˈvaɪzə/
n.
顾问;指导教师;劝告者

influx
英
/ˈɪnflʌks/
n.
(人或物的)大量涌入,大量流入;(水)流入,注入(河,湖,海)

grandfather
英
/ˈɡrænfɑːðə(r)/
n.
祖父;始祖
vt.
不受新规定限制
docker stats

通过docker stats命令可以很方便的看到当前宿主机上所有容器的CPU,内存以及网络流量等数据,一般小公司够用了。。.

docker stats统计结果只能是当前宿主机的全部容器,数据资料是实时的,没有地方存储、没有健康指标过线预警等功能

一句话
CAdvisor监控收集+InfluxDB存储数据+Granfana展示图表

CAdvisor
CAdvisor是一个容器资源监控工具,包括容器的内存,CPU,网络IO,磁盘IO等监控,同时提供了一个WEB页面用于查看容器的实时运行状态。CAdvisor默认存储2分钟的数据,而且只是针对单物理机。不过,CAdvisor提供了很多数据集成接口,支持InfluxDB,Redis,Kafka,Elasticsearch等集成,可以加上对应配置将监控数据发往这些数据库存储起来。
CAdvisor功能主要有两点:
·展示Host和容器两个层次的监控数据。·展示历史变化数据。

lnfluxDB
InfluxDB是用Go语言编写的一个开源分布式时序、事件和指标数据库,无需外部依赖。
CAdvisor默认只在本机保存最近2分钟的数据,为了持久化存储数据和统一收集展示监控
数据,需要将数据存储到InfluxDB中。InfluxDB是一个时序数据库,专门用于存储时序相关数据,很适合存储CAdvisor的数据。而且,cAdvisor本身已经提供了InfluxDB的集成方法,丰启动容器时指定配置即可。
lnfluxDB主要功能:
。基于时间序列,支持与时间有关的相关函数(如最大、最小、求和等);。可度量性:你可以实时对大量数据进行计算;
。基于事件:它支持任意的事件数据;

Granfana
Grafana是一个开源的数据监控分析可视化平台,支持多种数据源配置(支持的数据源包括
InfluxDB,MySQL,Elasticsearch,OpenTSDB,Graphite等)和丰富的插件及模板功能,支持图表权限控制和报警。
Grafan主要特性:
·灵活丰富的图形化选项。可以混合多种风格。支持白天和夜间模式。多个数据源

狂神收费教程

Swarm 简介

https://docs.docker.com/get-started/

找到文档,

Run your app in production

  • Scale your app 即是和 swarm相关的

选择:How nodes work

https://docs.docker.com/engine/swarm/how-swarm-mode-works/nodes/

管理节点

工作节点

Raft consensus group 一致性算法

consensus
美
/kənˈsensəs/
n.
一致看法,共识

raft
英
/rɑːft/
n.
木排,木筏; 橡皮艇,充气船;(游泳、跳水的)浮台;大量,许多;
v.
乘坐筏子(度河),用筏子运送;(浮冰)随浮冰流淌;

swarm帮助

docker swarm --help

Usage:  docker swarm COMMAND

Manage Swarm

Commands:
  ca          Display and rotate the root CA
  init        Initialize a swarm
  join        Join a swarm as a node and/or manager
  join-token  Manage join tokens
  leave       Leave the swarm
  unlock      Unlock swarm
  unlock-key  Manage the unlock key
  update      Update the swarm
  
docker swarm init --help

Usage:  docker swarm init [OPTIONS]
Initialize a swarm
Options:
      --advertise-addr string                  Advertised address (format: <ip|interface>[:port])
      
      
docker swarm init --advertise-addr +管理主节点IP

搭建docker集群

docker swarm init --advertise-addr 192.168.44.147
Swarm initialized: current node (juauycya2hkfhme51tt4x224d) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-0q9pyz5qvak4vlj1211eckvrsmiwj66c6p8sjfv0kuysh4i1qa-ckl6w2nho2uqa6v0uw9l241yn 192.168.44.147:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

docker swarm join-token manager #在主节点生成 主节点。 docker swarm join --token xxx,生成的是 注解的。
docker swarm join-token worker  #在主节点生成 工作节点,如上 打印。To add a worker to this swarm
  • 其他节点,都要运行 加入的
docker swarm join --token SWMTKN-1-0q9pyz5qv1yn 192.168.44.147:2377
docker node ls #主节点是 Leader,后面加的主节点为Readhable。工作节点是空。

ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
juauycya2hkfhme51tt4x224d *   kentai01   Ready     Active         Leader           20.10.22

reachable
英
/ˈriːtʃəbl/
adj.
可获得的;可达成的
  • 主节点,最低要3个。为了 匹配一致性算法。

云原生时代
Go语言!必须掌握!Java、Go!
Docker是Go开发的
K8S 也是Go的项目Etcd都是Go的项目!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值