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
镜像加速
使用阿里云的镜像加速器,阿里云服务器内使用
常用命令
帮助命令
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
...
部署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等等。
分层镜像
所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于Ubuntu Linux16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。
特点
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
构建流程:
- 编写一个dockerfile文件
- docker build构建成为一个镜像
- docker run运行镜像
- docker push发布镜像
发布地址:
- DockerHub
- 阿里云镜像仓库
DockerFile文件
关键字全大写
FROM # 基础镜像源
MAINTAINER # 镜像作者信息 格式:名字<邮箱>
RUN # 镜像构建的时候需要运行的命令
ADD # 镜像构建的步骤 添加内容 如tomcat压缩包(自动解压) 格式:文件名 容器内文件地址
WORKDIR # 镜像的工作目录
VOLUME # 卷挂载目录
EXPOSE # 保留暴露配置
CMD # 指定容器启动的时候需要运行的命令 CMD命令都运行,但只有最后一条CMD命令生效,可被替代
ENTRYPOINT # 指定容器启动的时候需要运行的命令 可以追加命令
ENV # 构建时设置环境变量 如:JAVA_HOME、CLASS_PATH 格式:变量名 变量信息
COPY # 类似于ADD 将宿主机文件拷贝到镜像中 格式:文件名 容器内文件地址
ENTRYPOINT与CMD区别:docker run时进行追加命令时CMD后需要全命令;ENTRYPOINT不需要
最基层镜像:scratch 大多数官方镜像的基础镜像源是这个
每一条指令可以理解为是一层镜像
自定义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镜像到阿里云
- 登录阿里云Docker Registry
$ docker login --username=hid**** registry.cn-shanghai.aliyuncs.com
用于登录的用户名为阿里云账号全名,密码为开通服务时设置的密码。
您可以在访问凭证页面修改凭证密码。
- 从Registry中拉取镜像
$ docker pull registry.cn-shanghai.aliyuncs.com/hidewnd/hidewnds_tudy:[镜像版本号]
- 将镜像推送到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:[镜像版本号]
- 示例
使用"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
概念
每当启动一个docker容器时,docker就会给docker容器分配一个IP。就会有有一个默认网卡docker0
每个docker容器会生成一对网桥
docker0:桥接模式,使用evth-pair技术。
evth-pair:一对虚拟设备接口,是成对出现,一端连着协议,一端彼此相连
evth-pair充当桥梁,连接各种虚拟网络设备
所有的容器在不指定网络的清空下,都是由docker0路由的,统一分配一个默认的可用IP,并生成一对网桥
当容器删除时,对应网桥自动删除
结论
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
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 文件配置中创建并启动所有服务。
步骤:
- Dockerfile文件定义Docker容器
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: {}
- 使用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
官网实例
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)
requirements.txt文件
flask redis
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相互验证和加密进行通信
- 滚动更新
升级服务时逐步将应用更新到节点,并支持任务回滚
> 工作模式

Manager:管理节点
集群中管理节点至少三个。
Worker:工作节点
Raft consensus group:一致性算法
Raft协议:保证大多数节点存货才可以用,集群至少大于三台
双主双从模式,当一台管理节点宕机,另一台无法使用
三主一从,当存活管理节点小于两台时,最后一台无法使用
> 概念
*Swarm:*
集群的管理和编号。docker 初始化一个swarm集群,其他节点可以以管理者、工作者身份加入
*Node:*
docker节点。多个节点构成一个网络集群
*Service:*
任务,在工作节点或者管理节点中运行。是核心
*Task:*
容器内的命令,是细节任务

*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语言:并发语言