学习笔记-Docker

Docker

概述

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

  • 虚拟机技术
  • Docker容器技术

区别:

  • 传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后再这个系统上安装和运行软件
  • 容器内的应用直接运行在宿主机的内容,容器没有自己的内核,也没有虚拟硬件
  • 每个容器相互隔离,每个容器内都有属于自己的文件系统,互不影响

DevOps(开发、运维)

更快速交付与部署:Docker可以快速打包镜像发布测试

更便捷的升级和扩缩容:使用Docker可以积木式管理项目

更简单的系统运维:开发测试环境高度一致

更高效的计算资源的利用:Docker是内核级的虚拟化,节省计算资源,可以在一个物理机中运行多个容器实例

概念

镜像(Image) :

docker镜像好比是模板,可以通过该模板创建一个或多个的容器服务。例如tomcat镜像==> run ==> comcat01容器(提供给服务器)

最终服务运行或者项目运行就是在容器中

容器(Container):

Docker利用容器技术,独立运行一个或者以个组应用,通过镜像来创建

可以将这个容器理解为一个建议==Linux==系统

仓库(Repository):

存放镜像地方 又分为私有仓库|公有仓库

Docker Hub(官方,国外)可以通过配置镜像加速

配置Docker

安装

# 卸载旧版本
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

# 更新
yum install -y yum-utils
 
# 配置下载路径                
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
 https://download.docker.com/linux/centos/docker-ce.repo (官网镜像)       
 http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo(阿里镜像)

 
 # 清理缓存
 yum makecache fast
 
 # 安装
 yum install docker-ce docker-ce-cli containerd.io
 
 # 启动
 systemctl start docker
 docker version #版本查看
 
 # 运行实例
 docker run hello-world
 
 # 查看已存在镜像
 docker iamges
 
 # 卸载docker
 # 卸载依赖
 yum remove docker-ce docker-ce-cli containerd.io
 #卸载资源
 rm -rf /var/lib/docker # docker默认工作路径
 rm -rf /var/lib/containerd

image-20210816155123775

镜像加速

使用阿里云的镜像加速器,阿里云服务器内使用

常用命令

帮助命令

docker version # docker版本信息
docker info # 显示docker系统信息,包括镜像和容器数量
docker 命令 --help # 帮助命令

官网帮助文档: Reference documentation | Docker Documentation

镜像命令

[root@lyneLinux /]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    d1165f221234   5 months ago   13.3kB

REPOSITORY   :  镜像仓库源
TAG          :  镜像标签
IMAGE ID     : 镜像ID
CREATED      :  镜像创建时间
SIZE         : 镜像大小
# 搜索镜像
docker search

[root@lyneLinux /]# docker search mysql -f=STARS=3000
NAME      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql     MySQL is a widely used, open-source relation…   11281     [OK]       
mariadb   MariaDB Server is a high performing open sou…   4280      [OK] 
####################
# 下载镜像 
docker pull mysql
docker pull mysql:5.7

[root@lyneLinux /]# docker pull mysql
Using default tag: latest # latest默认下载最新版
latest: Pulling from library/mysql
33847f680f63: Pull complete  # 分层下载 image核心,联合文件下载
5cb67864e624: Pull complete 
1a2b594783f5: Pull complete 
b30e406dd925: Pull complete 
48901e306e4c: Pull complete 
603d2b7147fd: Pull complete 
802aa684c1c4: Pull complete 
715d3c143a06: Pull complete 
6978e1b7a511: Pull complete 
f0d78b0ac1be: Pull complete 
35a94d251ed1: Pull complete 
36f75719b1a9: Pull complete 
Digest: sha256:8b928a5117cf5c2238c7a09cd28c2e801ac98f91c3f8203a8938ae51f14700fd
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 真实下载地址
#########
[root@lyneLinux /]# docker pull mysql:5.7
5.7: Pulling from library/mysql
33847f680f63: Already exists # 已下载的分层,节省内存
5cb67864e624: Already exists 
1a2b594783f5: Already exists 
b30e406dd925: Already exists 
48901e306e4c: Already exists 
603d2b7147fd: Already exists 
802aa684c1c4: Already exists 
5b5a19178915: Pull complete 
f9ce7411c6e4: Pull complete 
f51f6977d9b2: Pull complete 
aeb6b16ce012: Pull complete 
Digest: sha256:be70d18aedc37927293e7947c8de41ae6490ecd4c79df1db40d1b5b5af7d9596
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
[root@lyneLinux /]# 
############
# 删除镜像
docker rmi -f [REPOSITORY|IMAGE ID] [REPOSITORY|IMAGE ID] ...# 删除一个或者多个容器
docker rmi -f $(docker images) #删除所有

容器命令

先有镜像才有容器

# 容器启动
docker run [option] image
# ---- 参数 ------
# --name="Name" : 容器名字,用来区分容器
# -d                             后台方式运行
# -it              使用交互方式运行,进入容器查看内容
# -p              指定容器的端口 e.g:  -p [主机端口]:[容器端口] | -p [容器端口] | [容器端口]
# -P              随机指定端口
# ----------------

docker run -it centos /bin/bash #前台模式进入
exit # 退出并停止
Ctrl + P + Q # 容器不停止退出
#################
# 查询容器
docer ps # 列出正在运行的容器
                -a   #列出历史运行的容器
        -n=? #列出最近的容器
                -q   #只显示容器编号
#################
# 删除容器
docker rm [容器Id] # 删除容器
                    -f # 强制删除
docker ps -a -q|xargs docker rm # 删除所有容器
docker rm -f $(docker ps -aq)   # 删除所有容器
#################
docker start [容器Id]       # 启动容器
docker restart [容器Id]     # 重启容器
docker stop [容器Id]            # 停止当前正在运行的容器
docker kill [容器Id]            # 强制停止正在运行的容器

其他命令

后台启动容器,必须要有个前台进程

docker 发现没有应用就会自动停止

docker run -d centos

docker logs    [options] [ID]
                        -f    # 输出
                        -t    # 时间戳
                        --tail [num]# 字符串形式 num:要显示的行数
[root@lyneLinux /]# docker logs -f -t --tail 10 8c8d72748224

查看容器中的进程信息 top

docker top [ID]

[root@lyneLinux /]# docker top 8c8d72748224
UID                 PID             PPID             C           STIME            TTY              TIME                CMD
root                8911            8892             0           19:04            pts/0            00:00:00            /bin/bash

查看镜像源数据

docker inspect [ID]

[root@lyneLinux /]# docker inspect 8c8d72748224
[
    {
        "Id": "8c8d72748224897ea2c06e170badaae8feba989f8bd06ce421464e58757d409d",
        "Created": "2021-08-16T11:04:32.074849647Z",
        "Path": "/bin/bash",
        "Args": [],
        "State": {
            "Status": "r
            ...

进入当前正在运行的容器

# 方式一
# 进入容器后开启新的终端【新进程】
docker exec -it [ID] bashShell

[root@lyneLinux /]# docker exec -it  8c8d72748224 /bin/bash
[root@8c8d72748224 /]# ps -ef

# 方式二
# 进入容器正在执行的终端
docker attach [ID]

容器拷贝文件到主机

docker cp 容器ID:容器内路径 目的地主机路径
docker cp 8c8d72748224:/home/test.txt /home


# 查询CPU负载
docker stats

...

image-20210816200414535

部署nginx

[root@lyneLinux /]# docker run nginx --name nginx01 -p 3344:80 nginx
/docker-entrypoint.sh: 38: exec: --name: not found
[root@lyneLinux /]# docker run -d --name nginx01 -p 3344:80 nginx
210215ed00caa6a4b359d1f9f6c785b3a10f6ddef252237f9031b8a9d4ef5da3
[root@lyneLinux /]# curl localhost:3344
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

[root@lyneLinux /]# docker exec -it nginx01 /bin/bash
root@210215ed00ca:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@210215ed00ca:/# cd /etc/nginx/
root@210215ed00ca:/etc/nginx# ls
conf.d    fastcgi_params    mime.types  modules  nginx.conf  scgi_params  uwsgi_params
root@210215ed00ca:/etc/nginx# 

部署Tomcat

[root@lyneLinux /]# docker run -d --name tomcat01 -p 3344:8080 tomcat:9.0
f8b94ead6dcd65b08cdf1568d674d8e3cb238531fac719dac6ac649d29ee8ebc
root@f8b94ead6dcd:/usr/local/tomcat# ls
BUILDING.txt  CONTRIBUTING.md  LICENSE    NOTICE    README.md  RELEASE-NOTES  RUNNING.txt  bin  conf  lib  logs  native-jni-lib  temp  webapps  webapps.dist  work
root@f8b94ead6dcd:/usr/local/tomcat# cp -r webapps.dist/* webapps

部署ES+Kibana

# 增加内存限制 -e
docker run -d --name elasticsearch -p 9200:9200 -p9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms256m -XMx512m" elasticsearch:7.6.2

可视化

portainer :Docker图形化界面管理工具,提供后台面板

#安装
docker run -d -p 8080:9000 \
--resart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

Docker镜像

镜像:是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。

获取途径:

  • 远程仓库下载
  • 拷贝
  • 制作镜像DockerFIle

镜像加载原理

UnionFS(联合文件系统)

UnionFS (联合文件系统): Union文件系统(UnionFS )是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtualfilesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性︰一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

Docker镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS.
bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs (root file system),在bootfs之上。包含的就是典型Linux系统中的/dev,/proc, /bin,/etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu , Centos等等。

image-20210816214138993

分层镜像

所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于Ubuntu Linux16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。

image-20210816214344664

image-20210816214420454

image-20210816214446294

image-20210816214459781

特点

Docker镜像都是只读的,当容器启动后,一个新的可写层被加载到镜像的顶部——容器层

容器成之下的都叫镜像层

Commit镜像

命令与Git类似

docker commit 提交容器成为一个新的副本
docker commit -m-"描述信息" -a="作者" 容器ID 目标镜像名:[TAG]

docker commit -a="hidewnd" -m="Update webAPP" ab7396bd04d1 tomcat02:1.0
[root@lyneLinux ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
tomcat02     1.0       ee69899e1f13   8 seconds ago   673MB
tomcat       9.0       710ec5c56683   9 days ago      668MB
redis        latest    aa4d65e670d6   3 weeks ago     105MB
nginx        latest    08b152afcfae   3 weeks ago     133MB
[root@lyneLinux ~]# 

容器数据卷

容器之间有一个数据共享的技术

卷技术:目录挂载,将容器内的目录挂载到Linux上

容器的持久化和同步操作,容器间也可以进行数据共享

使用数据卷

方式1,直接使用命令挂载 -v

docker run -it -v 主机目录:容器内目录

docker run -it -v /home/ceshi:/home centos # 绑定

安装MySQL

数据持久化问题

[root@lyneLinux /]# docker pull mysql:5.7
...
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

假设将容器删除,挂载到本地的数据卷依旧没有丢失,实现了容器数据持久化的功能

具名挂载与匿名挂载

# 匿名挂载
-v 容器内路径
docker run -d -p --name nginx01 -v /ect/nginx nginx

# 查看所有的卷(volume)清空
docker volume ls

# 具名挂载
-v 卷名:容器内路径
docker run -d -p --name nginx02 -v juming-nginx:/ect/nginx nginx

# 查询卷路径
docker volume inspect [卷名]

扩展

# 通过 -v 容器内路径:ro|rw 改变读写权限
# ro: 只读 只能通过宿主机操作
# rw: 读写
# 设置容器权限后,容器对挂载的内容就有限制
docker run -d -p --name nginx01 -v juming-nginx:/ect/nginx:ro nginx
docker run -d -p --name nginx01 -v juming-nginx:/ect/nginx:rw nginx

方式二:DockerFile

DockerFile:用来构建docker镜像的构建文件—命令脚本

通过这个脚本可以生成镜像 每个命令都是一层镜像

dockerfile文件

FROM centos
VOLUME ["volume1","volume2"]
CMD echo "----end-----"
CMD /bin/bash

构建DockerFile

docker build -f dockerfile文件路径 -t 镜像名:TAG .

构建的镜像在实例容器时自动挂载到随机目录

数据卷容器

数据卷容器类似于拷贝-备份机制

docker run -it --name docker01 center
docker run -it --name docker02 --volumes-from docker01 center # docker02的数据挂载到docker01中
...

可以进行链式挂载,当第一个容器被删除后,数据不丢失,其他容器仍然可以访问,直到所有挂载的容器都被移除后,挂载文件才失效

应用:多个mysql实现数据共享

结论

容器之间配置信息的传递,

数据卷容器的生命周期一直持续到没有容器使用为止

DockerFile

docker是用来构建docker镜像的文件——命令参数脚本

docker镜像主流企业交付的标准

标准文件命令:Dockerfile

构建流程:

  1. 编写一个dockerfile文件
  2. docker build构建成为一个镜像
  3. docker run运行镜像
  4. docker push发布镜像

发布地址:

  • DockerHub
  • 阿里云镜像仓库

DockerFile文件

关键字全大写

FROM          # 基础镜像源 
MAINTAINER        # 镜像作者信息 格式:名字<邮箱>
RUN                        # 镜像构建的时候需要运行的命令
ADD                    # 镜像构建的步骤 添加内容 如tomcat压缩包(自动解压) 格式:文件名 容器内文件地址 
WORKDIR             # 镜像的工作目录
VOLUME                # 卷挂载目录
EXPOSE                # 保留暴露配置
CMD                        # 指定容器启动的时候需要运行的命令 CMD命令都运行,但只有最后一条CMD命令生效,可被替代
ENTRYPOINT        # 指定容器启动的时候需要运行的命令 可以追加命令
ENV                        # 构建时设置环境变量 如:JAVA_HOME、CLASS_PATH 格式:变量名 变量信息
COPY                    # 类似于ADD 将宿主机文件拷贝到镜像中 格式:文件名 容器内文件地址

ENTRYPOINTCMD区别:docker run时进行追加命令时CMD后需要全命令;ENTRYPOINT不需要

最基层镜像:scratch 大多数官方镜像的基础镜像源是这个

每一条指令可以理解为是一层镜像

image-20210817182514164

自定义centos的DockerFile文件

FROM centos
MAINTAINER hidewnd<908751915@qq.com>

ENV MYPATH /user/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo "-----success-------"
CMD echo "mypath: " + $MYPATH

CMD bin/bash 

编译构建

docker build -f DockerFile -t mycentos:0.1 . 

制作tomcat镜像

FROM centos
MAINTAINER lyne<908751915@qq.com>
COPY readme.txt /usr/local/readme.txt

ADD jdk-8u301-linux-x64.tar.gz /usr/local
ADD apache-tomcat-9.0.52.tar.gz /usr/local
RUN yum -y install vim

ENV MYPATH /usr/local
WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk1.8.0_301
ENV CLASSPATH $JAVAHOME/lib/dt.jar:$JAVAHOME/lib/tools,jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.52
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.52
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-9.0.52/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.52/bin/logs/catalina.out

编译

docker build -t mytomcat:0.1 .

创建时挂载

docker run -d -p 9090:8080 --name mytomcat01 -v /home/lyne/build/tomcat/test:/usr/local/apache-tomcat-9.0.52/webapps/test -v /home/lyne/build/tomcat/tomcatlogs:/usr/local/apache-tomcat-9.0.52/logs mytomcat:0.1

发布Docker镜像到Docker Hub

docker login # 登录Docker Hub
docker push [REPOSITORY]:[TAG] # 上传镜像
# docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG] # 标记本地镜像,将其归入某一仓库。
docker tag ubuntu:15.10 runoob/ubuntu:v3 # 修改名

发布Docker镜像到阿里云

  1. 登录阿里云Docker Registry
$ docker login --username=hid**** registry.cn-shanghai.aliyuncs.com

用于登录的用户名为阿里云账号全名,密码为开通服务时设置的密码。

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

  1. 从Registry中拉取镜像
$ docker pull registry.cn-shanghai.aliyuncs.com/hidewnd/hidewnds_tudy:[镜像版本号]
  1. 将镜像推送到Registry
$ docker login --username=hid**** registry.cn-shanghai.aliyuncs.com$ docker tag [ImageId] registry.cn-shanghai.aliyuncs.com/hidewnd/hidewnds_tudy:[镜像版本号]$ docker push registry.cn-shanghai.aliyuncs.com/hidewnd/hidewnds_tudy:[镜像版本号]
  1. 示例

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

$ docker imagesREPOSITORY                                                         TAG                 IMAGE ID            CREATED             VIRTUAL SIZEregistry.aliyuncs.com/acs/agent                                    0.7-dfb6816         37bb9c63c8b2        7 days ago          37.89 MB$ docker tag 37bb9c63c8b2 registry-vpc.cn-shanghai.aliyuncs.com/acs/agent:0.7-dfb6816

使用 "docker push" 命令将该镜像推送至远程。

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

镜像打包

# docker save [OPTIONS] IMAGE [IMAGE...] # 将指定镜像保存成 tar 归档文件
runoob@runoob:~$: docker save -o my_ubuntu_v3.tar runoob/ubuntu:v3
# docker load [OPTIONS] # 导入使用 docker save 命令导出的镜像。
runoob@runoob:~$: docker load --input fedora.tar

Docker网络

Docker0

概念

image-20210817200216384

每当启动一个docker容器时,docker就会给docker容器分配一个IP。就会有有一个默认网卡docker0

每个docker容器会生成一对网桥

docker0:桥接模式,使用evth-pair技术。

evth-pair:一对虚拟设备接口,是成对出现,一端连着协议,一端彼此相连

​ evth-pair充当桥梁,连接各种虚拟网络设备

所有的容器在不指定网络的清空下,都是由docker0路由的,统一分配一个默认的可用IP,并生成一对网桥

当容器删除时,对应网桥自动删除

image-20210817200837620

结论

image-20210817201223620

Docker中的所有网络接口都是虚拟的,虚拟转发效率高(内网传递)

容器互联

--link

使用容器名进行连接

docker run -d -P --name tomcat01 tomcat 
docker run -d -P --name tomcat02 --link tomcat01 tomcat # --link 与tomcat01连通

docker exec -it tomcat02 ping tomcat01 # ping测试

要注意的是,link连接是单向连通

--link操作==>在容器内的/etc/hosts配置中加入地址映射

docker0 不支持容器名连接访问

自定义网络

自定义网络默认可以使用域名连接访问

自定义网络docker已经自动维护好对应的关系

连接在同一个自定义网络的容器之间端口自动相互暴露,不会向以外的显示任何端口,更好进行容器间相互通信与隔离

docker network # 查询网络
                            ls #列出所有网络

# 其中,bridge网络的docker0的

网络模式

  • bridge 桥接(默认)
  • none 不配置网络(默认)
  • host 和宿主主机共享网络(默认)
  • container 容器内网络连通(用的少,局限性大)
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet # 自定义网络
docker run -d -P --name tomcat01 --net mynet # 使用自定义网络创建

网络连通

docker0中的容器连通到自定义网络中的容器

# 默认情况,不同网卡下的容器无法进行连通
# 需要进行connect 连接 docker network connect [options] network container
docker network connect mynet tomcat01 # 将docker0的tomcat01连通到mynet网络中  相当于一个容器两个IP

image-20210817213107496

Redis集群

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

# 通过脚本创建redis配置
for port in $(seq 1 6);
do
mkdir -p /home/redistest/redis/node-${port}/conf
touch /home/redistest/redis/node-${port}/conf/redis.conf
cat << EOF >>/home/redistest/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file node.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done

# 创建Redis容器
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /home/redistest/redis/node-1/data:/data \
-v /home/redistest/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#########
docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
-v /home/redistest/redis/node-2/data:/data \
-v /home/redistest/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#########
docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
-v /home/redistest/redis/node-3/data:/data \
-v /home/redistest/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
-v /home/redistest/redis/node-4/data:/data \
-v /home/redistest/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
-v /home/redistest/redis/node-5/data:/data \
-v /home/redistest/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /home/redistest/redis/node-6/data:/data \
-v /home/redistest/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
...
##一共创建6个redis容器##
#########
# 进入容器
docker exec -it redis-1 /bin/sh

# 创建集群
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 nodes # 查询信息
cluster info # 查询节信息

微服务打包Docker

1.构建springboot应用
2.打包应用
3.编写dockerfile
4.构建docker
5.发布运行

Dockerfile

FROM java:11
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]

Docker Compose

介绍

Compose 是用于定义和运行多容器 Docker 应用程序的工具。

通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。

步骤:

  1. Dockerfile文件定义Docker容器
  2. docker-compose.yml定义服务

    # 官网示例
    version: "3.9"  # optional since v1.27.0
    services:
      web:
        build: .
        ports:
    - "5000:5000"
        volumes:
    - .:/code
    - logvolume01:/var/log
        links:
    - redis
      redis:
        image: redis
    volumes:
      logvolume01: {}
  1. 使用docker compose up命令运行

也就是说是批量的容器编排,可以通过compose一键管理多个微服务/环境

概念

Service(服务)

​ 容器应用,如web程序、mysql、redis

Project(项目)

​ 一组关联的容器所形成的一个业务单元。

安装

# 下载镜像
    # github镜像
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    # 国内镜像 1.25.5
curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
# 授权     
sudo chmod +x /usr/local/bin/docker-compose
# 如果上述操作后无法使用,再创建软链
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

离线安装

# 1.上传离线文件
# 文件地址:https://github.com/docker/compose/tags
# 2. 执行
sudo mv docker-compose-Linux-x86_64 /usr/local/bin/docker-compose
# 3.授权
sudo chmod +x /usr/local/bin/docker-compose

官网实例

  1. 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)
  2. requirements.txt文件

    flask
    redis
  3. Dockerfile构建文件:将应用打包成一个镜像

# syntax=docker/dockerfile:1
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]


4. *docker-compose.yml*配置文件 :定义服务需要的环境,web,redis...

version: "3.9"
services:

 web:
   build: .
   ports:
     - "5000:5000"
 redis:
   image: "redis:alpine"

5. 启动

docker-compose up




默认服务名:`[文件名]_[服务名]_[num]`

​    num表示服务的副本数,集群状态便于管理 

默认创建docker网络:`[文件名]_default` 

​    在app.py文件中通过*cache = redis.Redis(**host='redis'**, port=6379)* 进行域名设置,访问通过域名访问。创建的服务自动加入网络中



### 配置

> yaml规则

结构只有三层

- version:版本
- services:服务
  - 服务1
 - 服务配置信息
  - 服务2
  - 服务配置信息
  - ...
 - ...
- 其他配置信息 网络、卷、全局规则...
  - vomlumes
  - networks
  - configs

第一层

version: '' # compose版本

第二层

services:

service1:
    container_name: # 指定自定义容器名称
    image: # 镜像
    build: # Dockfile文件构建
        context: # 文件地址
        dockfile: # 文件
    ports: # 暴露端口
    depends_on: # 容器依赖,该容器在依赖容器启动后执行
    ...
service2:
    images
    build
    ports
    ...    

第三层

volumes:
cofigs:
networks:




> 微服务

1. 编写项目微服务

   application.porperties

server.port=8080
spring.redis.host=redis




2. Dockerfile构建镜像

FROM openjdk:11-jre
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]




3. docker-compose.yml编排项目

version:"3.8"
services:

   app:
       build: .
       image: app
       depends_on:
           - redis
       ports:
           - "8080:8080"
   redis:
       image: "library/redis:alpine"
       



4. 放入服务器

5. *docker-compose up --build* 启动服务

docker-compose运行后服务生产一个个容器,由docker直接管理,也可以由k8s进行进一步封装管理

> 部署wordpress博客

1. 创建服务文件

mkdir my_wordpress
cd my_wordpress/


2. 创建*docker-compose.yml*文件

version: "3.9"

services:

 db:
   image: mysql:5.7
   volumes:
     - db_data:/var/lib/mysql
   restart: always
   environment:
     MYSQL_ROOT_PASSWORD: somewordpress
     MYSQL_DATABASE: wordpress
     MYSQL_USER: wordpress
     MYSQL_PASSWORD: wordpress
   
 wordpress:
   depends_on:
     - db
   image: wordpress:latest
   volumes:
     - wordpress_data:/var/www/html
   ports:
     - "8000:80"
   restart: always
   environment:
     WORDPRESS_DB_HOST: db:3306
     WORDPRESS_DB_USER: wordpress
     WORDPRESS_DB_PASSWORD: wordpress
     WORDPRESS_DB_NAME: wordpress

volumes:

 db_data: {}
 wordpress_data: {}

3. 后台启动

docker-compose up -d








## Docker Swarm

集群

Swarm 是目前 Docker 官方唯一指定(绑定)的集群管理工具。Docker 1.12 内嵌了 swarm mode 集群管理模式

特点:

- Docker Engine集成集群管理

  创建一个Docker Engine的Swarm模式

- 去中心化设计

  Manager/Worker 节点。manager节点故障不影响应用

- 扩缩容

  声明每个服务运行的容器数量

- 期望状态协调

  manager节点会监视集群状态,随时调整当前状态于期望状态之间的差异

- 多主机网络

  可以为服务指定overlay网络。当初始化或更新应用程序时,Swarm manager自动为overlay网络上的容器分配IP地址

- 服务发现

  为集群中的每个服务分配唯一的DNS记录和负载均衡VIP,通过swarm内置的DNS服务器查询集群中的每个运行的容器

- 负载均衡

  实现服务副本的负载均衡,提供入口验证。也可以将服务入口暴露给外部的负载均衡器再次负载均衡

- 安全传输

  每个节点使用TLS相互验证和加密进行通信

- 滚动更新

  升级服务时逐步将应用更新到节点,并支持任务回滚

> 工作模式



![image-20210819205355841](https://lyne-bucket.oss-cn-shanghai.aliyuncs.com/notes/202207231604843.png)

Manager:管理节点

​    集群中管理节点至少三个。

Worker:工作节点

​    

Raft consensus group:一致性算法

​    Raft协议:保证大多数节点存货才可以用,集群至少大于三台

​        双主双从模式,当一台管理节点宕机,另一台无法使用

​        三主一从,当存活管理节点小于两台时,最后一台无法使用 



> 概念

*Swarm:*

​    集群的管理和编号。docker 初始化一个swarm集群,其他节点可以以管理者、工作者身份加入

*Node:*

​    docker节点。多个节点构成一个网络集群

*Service:*

​    任务,在工作节点或者管理节点中运行。是核心

*Task:*

​    容器内的命令,是细节任务

![image-20210820214140988](https://lyne-bucket.oss-cn-shanghai.aliyuncs.com/notes/202207231604982.png)



*PublishMode:*

​    网络模式

​    Swarm

​    Overlay:跨主机通信,会自动寻找服务器

​    Ingress:特殊的Overlay网络,支持负载均衡、IPVS、虚拟网络VIP。。。



> 指令

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

[root@centos7-1 /]# docker swarm init --help

Usage: docker swarm init [OPTIONS]

Initialize a swarm

Options:

  --advertise-addr string                  Advertised address (format: <ip|interface>[:port])
  --autolock                               Enable manager autolocking (requiring an unlock key to start a stopped manager)
  --availability string                    Availability of the node ("active"|"pause"|"drain") (default "active")
  --cert-expiry duration                   Validity period for node certificates (ns|us|ms|s|m|h) (default 2160h0m0s)
  --data-path-addr string                  Address or interface to use for data path traffic (format: <ip|interface>)
  --data-path-port uint32                  Port number to use for data path traffic (1024 - 49151). If no value is set or is set to 0, the default port (4789) is used.
  --default-addr-pool ipNetSlice           default address pool in CIDR format (default [])
  --default-addr-pool-mask-length uint32   default address pool subnet mask length (default 24)
  --dispatcher-heartbeat duration          Dispatcher heartbeat period (ns|us|ms|s|m|h) (default 5s)
  --external-ca external-ca                Specifications of one or more certificate signing endpoints
  --force-new-cluster                      Force create a new cluster from current state
  --listen-addr node-addr                  Listen address (format: <ip|interface>[:port]) (default 0.0.0.0:2377)
  --max-snapshots uint                     Number of additional Raft snapshots to retain
  --snapshot-interval uint                 Number of log entries between Raft snapshots (default 10000)
  --task-history-limit int                 Task history retention limit (default 5)

> 防火墙操作:

firewall-cmd --zone=public --add-port=[端口]/tcp --permanent # 开放端口
irewall-cmd --zone=public --remove-port=[指定端口]/tcp --permanent # 关闭端口
firewall-cmd --reload # 端口立即生效
firewall-cmd --zone=public --list-ports # 查询已开放端口

systemctl stop firewalld.service # 关闭防火墙
systemctl start firewalld.service # 打开防火墙
systemctl restart firewalld.service # 重启防火墙
systemctl status firewalld.service # 查看防火墙状态






> 创建集群

docker swarm init --advertise-addr 192.168.3.27 # 在私网加入管理节点
To add a worker to this swarm, run the following command:

    # 加入成为工作节点 需要开放2377端口
docker swarm join --token SWMTKN-1-2cm38dahiwio3vl9a4vbdctzvgv5t6hv2ze638z1t05p3v60rx-58o0tu2yz733u4gp7wtwyzw95 192.168.3.27:2377 

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

初始化主节点 管理节点

docker swarm join

获取令牌

docker swarm join-token manager
docker swarm join-token worker

工作节点加入集群 # 主节点需要开放2377端口

docker swarm join --token SWMTKN-1-2cm38dahiwio3vl9a4vbdctzvgv5t6hv2ze638z1t05p3v60rx-58o0tu2yz733u4gp7wtwyzw95 192.168.3.27:2377

管理节点加入集群:加入节点需要开放2377端口

docker swarm join --token SWMTKN-1-2cm38dahiwio3vl9a4vbdctzvgv5t6hv2ze638z1t05p3v60rx-5ezujplcqx5lcdfc59crgmzb8 192.168.3.27:2377

ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
icg03ybbfftj6r6omr8q8t6zk Unknown Active
mb8rjmgh4x9wcqf9bbzlzou5r * centos7-1 Ready Active Leader 20.10.8
q63rz7j75y6upetw8u3cjz56a centos-2 Ready Active 20.10.8
sp2ok9x8mhnwz6kq5aibxkacl centos-3 Ready Active 20.10.8
mqxgheeky8qhvsum1cp2kr10g centos-4 Ready Active Reachable 20.10.8


Leader:主节点 管理节点

Reachable: 管理节点

> 使用服务

docker swarm 可以实现灰度发布(金丝雀发布)

[root@centos7-1 /]# docker service

Usage: docker service COMMAND

Manage services

Commands:
create Create a new service
inspect Display detailed information on one or more services
logs Fetch the logs of a service or task
ls List services
ps List the tasks of one or more services
rm Remove one or more services
rollback Revert changes to a service's configuration
scale Scale one or multiple replicated services


创建服务

​    指令近似于docker run...;使用docker service启动,具有**扩缩容器,滚动更新**功能

docker service create -p 8888:80 --name my-nginx nginx # 在副本中创建一个nginx 只有一个节点在运行服务
docker service create --mode global --name my-nginx nginx # 在全局中创建一个nginx
docker service ps my-nginx # 查看服务状态
docker service ls # 查看服务
docker service inspect my-nginx # 查看服务配置信息

更新副本数

docker service update --replicas 3 my-nginx # 扩充至三台节点运行服务
docker service scale my-nginx=5 # 扩充至四台节点运行服务

docker service rm my-nginx # 移除一个服务


更好的管理平台如`k8s`



## 其他指令



> Docker Stack

在集群下部署项目

单机部署

docker-compose up -d docker-compose.yml

集群部署

docker stack deploy docker-stack.yml

配置文件结构与docker-compose相似


> Docker Secret 

docker的安全管理

Secret :用户名密码、SSH密钥、TLS认证等需要安全保护的数据

Usage: docker secret COMMAND

Manage Docker secrets

Commands:
create Create a secret from a file or STDIN as content
inspect Display detailed information on one or more secrets
ls List secrets
rm Remove one or more secrets


> Docker Config

关于docker的统一配置信息,

1. docker配置文件储存分为两种:
   - 加密储存
   - 不加密储存
2. Docker配置仅适用于集群服务,不适用于独立容器

Usage: docker config COMMAND

Manage Docker configs

Commands:
create Create a config from a file or STDIN
inspect Display detailed information on one or more configs
ls List configs
rm Remove one or more configs




> 云原生

当集群数量超过十台时,建议切换到k8s平台进行管理容器,

需要掌握技术:Go语言:并发语言
hidewnd

hidewnd

Just So So ...

留下你的评论

快留下你的小秘密吧