我们写的代码会涉及到到好几个环境
开发环境
测试环境
生产环境
在不同环境跑代码,可能会导致代码“水土不服”的问题,如何解决软件跨环境问题,docker就由此而生。
Docker是一个基于Go语言实现的开源的应用容器引擎,诞生于2013年初。Docker可以让开发者打包他们的应用以及依赖包到个轻量级、可移植的容器中,然后发布到任何流行的Linux机器上。容器之间是完全使用沙箱机制,相互隔离并且容器性能开销极低。官网https://www.docker.com。
Docker是一个C/S模式的架构,后端是一个松耦合架构, 众多模块各司其职,互不影响。
运行的基本流程为:
安装教程
不同系统有不同安装教程。
注意: 配置镜像源时候选择国内的镜像源
docker run hello-world
systemctl start docker
systemctl stop docker
systemctl restart docker
systemctl status docker
systemctl enable docker
docker info
docker stats
docker -help
docker 具体命令 --help
docker images
:列出本地主机上的镜像。
-a
:列出本地所有的镜像(含历史映像层)-q
:只显示镜像IDREPOSITORY:TAG
定义不同镜像,不写默认镜像:latest
表示最新版本。docker search
:某个xxx镜像名字。
--limit
:只列出N个镜像,默认25个docker pull
:某个xxx镜像名字。
docker pull image
:拉取最新版本的镜像。docker pull image:TAG
:拉取指定tag版本的镜像。docker system df
:查看镜像/容器/数据卷所占的空间。docker rmi 某个xxx镜像名字/ID
:删除此镜像。
-f
:强制删除。(在镜像被使用的情况下)删除多个镜像
:docker rmi 某个xxx镜像1名字/ID 某个xxx镜像2名字/ID ....
删除全部
: docker rmi $(docker images -qa)
docker save -o <压缩包文件名.tar> <镜像名>
:导出镜像到压缩包。
-o
:指定导出镜像的输出文件路径和名称。-q
:静默模式,只输出导出镜像的文件路径和名称。-t
:指定要导出的镜像的名称。docker save 镜像名:tag | gzip > 文件名.tar.gz
docker load -i <压缩包文件名.tar>
:导入压缩包为镜像。
-t
: 自定义名称 docker load -i <压缩包文件名.tar> -t 自定义名称
-i
:指定要导入的镜像文件路径和名称。-q
:静默模式,只输出导入镜像的 ID。--input-format
:指定导入镜像的格式,默认为 “docker”。Docker镜像的自动构建和非自动构建有以下区别:
关于两者的区别,以下是一些主要考虑因素:
自动构建适合需要实时构建和部署的场景,尤其是对于持续集成和持续交付的需求;而非自动构建则适用于不需要频繁构建和部署的场景,或者只需进行间断性的镜像构建。
仓库名、标签都是
的镜像,俗称虚悬镜像dangling image
一般没啥太大用处,删掉就行。
新建+启动容器(docker run --help
)
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
docker run - it ubuntu /bin/bash
: 以交互模式启动一个容器,在容器内执行/bin/bash
命令。docker run - it ubuntu bash
: 以交互模式启动一个容器,在容器内执行bash
命令。列出当前所有正在运行的容器
docker ps [OPTIONS]
-a
:列出当前所有正在运行的容器 + 历史上运行过的。-|
:显示最近创建的容器。-n n
:显示最近n个创建的容器。-q
:静默模式,只显示容器编号。退出容器
exit
: run进去容器,exit退出, 容器停止。ctrl+p+q
: run进去容器,ctr1+p+q退出, 容器不停止。启动已停止运行的容器 :docker start容器ID/容器名
重启容器 : docker restart容器ID/容器名
停止容器 : docker stop容器ID/容器名
强制停止容器 : docker kill容器ID/容器名
删除已停止的容器
docker rm 容器ID/名称
docker rm -f $(docker ps -a -q)
docker ps-a -q| xargs docker rm
-f
:强制删除。重要内容
守护式容器
docker run -d centos
执行,然后docker ps -a
进行查看,会发现容器已经退出很重要的要说明的一点,**Docker容器后台运行,就必须有一个前台进程,容器运行的命令如果不是那些一直挂起的命令(比如运行top无识别结果,就是会自动退出的)。查看容器ID :docker logs 容器ID/名字
查看容器内运行进程: docker top 容器ID/名字
查看容器内部细节: docker inspect 容器ID/名字
进入正在运行的容器并以命令行交互
docker exec -it 容器ID/名称 bashShell
docker attach 容器ID/名称
attach
:直接进入容器启动命令的终端,不会启动新的进程,用exit退出,会导致容器的停止。exec
:是在容器中打开新的终端,并且可以启动新的进程,用exit退出,不会导致容器的停止。从容器内拷贝文件到主机上(容器 --> 主机)
docker cp 容器ID:容器内路径 目的主机路径
导入导出容器
export
导出容器的内容流作为一个tar归档文件[对应import命令]
docker export ddb1ae909a66 > xxxx. tar
import
从tar包中的内容创建一个新的文件系统再导入为镜像[对应export]
cat文件名.tar | docker import - 镜像用户/镜像名:镜像版本号
ip:hostport:containerport #指定ip、指定宿主机port、指定容器port
ip::containerport #指定ip、未指定宿主机port(随机)、指定容器port
hostport:containerport #未指定ip、指定宿主机port、指定容器port
docker port container_ID
结果
80/tcp -> 0.0.0.0:800
是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),这个打包好的运行环境就是image镜像文件。只有通过这个镜像文件才能生成Docker容器实例(类似Java中new出来 一个对象)。
在下载的过程中,注意到docker的镜像是在一层一层的在下载。
Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual
filesystem)。Union 文件系统是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镜像层都是只读的,容器层是可写的当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层“。
当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层” 之下的都叫“镜像层”。所有对容器的改动,无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。
docker commit
提交容器副本使之成为一个新的镜像
docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名/版本号]
Docker Registry是官方提供的工具,可以用于构建私有镜像仓库。
docker pull registry
默认情况,仓库被创建在容器的var/lib/registry
目录下,建议自行用容器卷映射,方便于宿主机联调
docker run -d -p 5000:5000 -v /xxx/xxx/:/tmp/registry --privileged=true registry
curl -XGET 本地服务器ip:5000/v2/_catalog
docker tag 镜像:Tag Host:Port/Repository:Tag
docker tag xxx:1.2 ip:端口/xxx:1.2
/etc/docker/daemon.json
配置文件增加下面那条配置。docker默认不允许http方式推送镜像,通过此配置选项来取消这个限制。修改完后重启docker。docker push ip:端口/xxx:1.2
--privileged = true
原因: docker 挂在主机目录访问 出现 cannot open directory .:Permission denied
,在挂在目录后面加一个--privileged = true
。
容器数据卷,卷就是目录或者文件,存在于一个或者多个容器中,但不属于联合文件系统,因此能绕过Union File System提供一些用于持续存储或者共享数据的特性。设计的目的就是用于数据的持久化,其完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。
可以将容器中的 数据备份+ 持久化 到本地的宿主机中
docker run -it --privileged=true -v /宿主机绝对路径:/容器内目录 镜像名
docker inspect 容器ID
docker run -it --privileged=true -v /宿主机绝对路径:/容器内目录:rw 镜像名
设置可读写(不写默认就是)。
docker run -it --privileged=true -v /宿主机绝对路径:/容器内目录:ro 镜像名
read only设置只读,容器内只能读不能写。
docker run -it --privileged=true -v /宿主机绝对路径:/容器内目录 --name u1 镜像名
docker run -it --privileged=true -volumes-from u1 --name u2 镜像名
继承关系只是继承挂载路径和其规则,u1删除了并不影响u2。
docker run -d -p 8080:8080 tomcat
webapps.dist
改成webapps
docker pull billygoo/tomcat8-jdk8
docker run -d -p 8080:8080 --name 容器名字 billygoo/tomcat8-jdk8
docker run -d -p 3306:3306 --name=mysql --privileged=true -v /xxx/mysql/log:/var/log/mysql -v /xxx/mysql/data:/var/lib/mysql -v /xxxx/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
/xxxx/mysql/conf
下 新建my.cof[client]
default_character_set=utf8
[mysqld]
collation_server = utf8_general_ci
character_set_server = utf8
SHOW VARIABLES LIKE 'character%'
,检查是否全是utf8redis.conf
,放到对应的数据卷下。注释掉配置文件中的 # bind 127.0.0.1
daemonize no
改为 daemonize yes
,因为该配置和docker run
中的-d
命令冲突,导致容器一直启动失败。appendonly yes
。(可选)docker run -d -p 6379:6379 --name=redis --privileged=true -v /xxxx/redis/redis.conf:/etc/redis/redis.conf -v /xxxx/redis/data:/data redis:6.0.8 redis-server /etc/redis/redis.conf
docker run -d -p 3307:3306 --name mysql-master -v /xxx/mysql-master/log:/var/log/mysql -v /xxx/mysql-master/data:/var/lib/mysql -v /xxxx/mysql-master/conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=root mysql:5.7
/xxxx/mysql-master/conf
目录下新建my.cnf
cd /xxxx/mysql-master/conf
vim my.cnf
将下面配置写进去
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=101
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
## 开启二进制日志功能
log-bin=mall-mysql-bin
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致。
slave_skip_errors=1062
docker restart mysql-master
mysql-master
容器docker exec -it mysql-master /bin/bash
mysql -uroot -proot
master
容器实例内创建数据同步用户CREATE USER 'slave'@'%' IDENTIFIED BY '123456' #建立用户
GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'slave'@'%' # 授权
docker run -d -p 3307:3306 --name mysql-slave -v /xxx/mysql-slave/log:/var/log/mysql -v /xxx/mysql-slave/data:/var/lib/mysql -v /xxxx/mysql-slave/conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=root mysql:5.7
/xxxx/mysql-slave/conf
目录下新建my.cnf
cd /xxxx/mysql-slave/conf
vim my.cnf
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=102
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
## 开启二进制日志功能
log-bin=mall-mysql-slave1-bin
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致。
slave_skip_errors=1062
## relay_log配置中继日志
relay_log=mall-mysql-relay-bin
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1
## slave设置为只读(具有super权限的用户除外)
read_only=1
docker restart mysql-slave
进入主机实例内部,执行
show master status
mysql-slave
容器docker exec -it mysql-slave /bin/bash
mysql -uroot -proot
change master to master_host ='宿主机IP‘, master_user='slave',master_password='123456',master_port=3307,master_log_file='mall-mysql-bin.000001',master_log_pos=617,master_connect_retry=30;
参数说明:
1. master_host
:主数据库IP地址。
2. master_port
:主数据库运行端口。
3. master_user
:在主数据库创建的用于同步数据的用户账号。
4. master_password
:在主数据库创建的用于同步数据的用户密码。
5. master_log_file
:指定从数据库要复制的日志文件,通过查看主数据库的状态,获取File参数。
6. master_log_pos
:指定从数据库从哪个位置开始复制数据,通过查看主数据的状态,获取position参数
7. master_connect_retry
:连续失败的重试时间间隔,单位是秒。
show slave status \G;
start slave
show slave status \G;
哈希槽分区进行亿级数据存储。
hash(key)%N
个机器台数,计算出哈希值,决定数据映射到哪个节点上。背景
一致性算法在1997年由麻省理工学院中提出的,为了解决分布式缓存数据变动和映射问题(某个机器宕机,分母改变,自然取余会出现问题)
步骤
一致性哈希环的创建
哈希取余分区
是对节点(服务器)的数量进行取模。而一致性Hash算法是对 232 取模。一致性Hash算法将整个哈希值空间组成一个虚拟的圆环,如假设某哈希函数H的值空间为0 – 232-1(哈希值是一个32位无符号整形)。服务器IP节点映射
key落到服务器的落键规则
优点
缺点
slot = CRC16(key) % 16384
。以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,数据移动问题就解决了。@Test
public void test(){
System.out.println(SlotHash.getSlot("A"));//6373
System.out.println(SlotHash.getSlot("B"));//10374
System.out.println(SlotHash.getSlot("C"));//14503
System.out.println(SlotHash.getSlot("hello"));//866
}
--net host
:使用宿主机的IP和端口(默认)--cluster-enabled
:集群开关--appendonly
: 持久化开关docker run -d --name redis-node-1 --net host --privileged=true -v /data/redis/share/redis-node-1:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381
docker run -d --name redis-node-2 --net host --privileged=true -v /data/redis/share/redis-node-2:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6382
docker run -d --name redis-node-3 --net host --privileged=true -v /data/redis/share/redis-node-3:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6383
docker run -d --name redis-node-4 --net host --privileged=true -v /data/redis/share/redis-node-4:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6384
docker run -d --name redis-node-5 --net host --privileged=true -v /data/redis/share/redis-node-5:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6385
docker run -d --name redis-node-6 --net host --privileged=true -v /data/redis/share/redis-node-6:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6386
docker exec -it redis-node-1 /bin/bash
执行下面命令
redis-cli --cluster create ip:6381 ip:6382 ip:6383 ip:6384 ip:6385 ip:6386 --cluster-replicas 1
--cluster create
:构建集群
--cluster-replicas 1
:表示为每个master创建一个slave
redis-cli -p 6381
cluster info
cluster nodes
cluster info
:查看集群信息
cluster nodes
:查看集群节点
集群信息
节点信息
注意:主从关系是redis集群自动设置,每次设置不一定一样。
docker exec -it redis-node-1 /bin/bash
当用单机版命令redis-cli -p 6381
连接redis时,出现存储错误,哈希槽值大于6381的值。
故:集群环境下不能使用单机命令连接redis,要是用 redis-cli -p 6381 -c
命令连接(-c是优化路由,集群环境连接)
redis-cli --cluster check ip:6381
docker stop redis-node-1
docker exec -it redis-node-2 /bin/bash
redis-cli -p 6382 -c
cluster nodes
docker start redis-node-1
docker exec -it redis-node-1 /bin/bash
redis-cli -p 6381 -c
cluster nodes
docker start redis-node-1
docker stop redis-node-4
docker start redis-node-4
cluster nodes
docker run -d --name redis-node-7 --net host --privileged=true -v /data/redis/share/redis-node-7:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6387
docker run -d --name redis-node-8 --net host --privileged=true -v /data/redis/share/redis-node-8:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6388
docker exec -it redis-node-7 /bin/bash
reids-cli --cluster add-node ip:6387 ip:6381
--cluster add-node ip:6387 ip:6381
:6387是新增的master节点,6381是原来集群节点里面的“领路节点”redis-cli --cluster check ip:6381
redis-cli --cluster reshard ip:6381
redis-cli --cluster check ip:6381
redis-cli --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新主机节点ID
redis-cli --cluster check ip:6381
redis-cli --cluster del-node ip:6388 主节点ID
。redis-cli --cluster reshard ip:6381
redis-cli --cluster check ip:6381
redis-cli --cluster del-node ip:63878 主节点ID
。是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。
官网
docker build
命令构建镜像docker run
依镜像运行容器实例#
表示注释。docker commit
的操作提交一个新的镜像层。dockerfile
中的下一条指令直到所有指令都执行完成。FROM
:基础镜像,当前新镜像是基于哪个镜像,指定一个已经存在的镜像作为模版,DockerFile的第一条命令必须是FROMMAINTAINER
:镜像维护者的姓名和邮箱地址RUN
:容器构建时需要运行的命令,RUN是在docker build
时运行的
RUN <命令行指令>
等同于在终端操作 shell命令。例如RUN yum -y install vim
。RUN ["可执行文件","参数1","参数2"]
。例如RUN ["./test.php","dev","offline"]
等价于 RUN ./test.php dev offline
。EXPOSE
:当前容器对外暴露出的端口。WORKDIR
:指定 在创建容器后,终端默认登录进来的工作目录,一个落脚点。USER
:该用户以什么样的用户去执行,如果不指定,默认ROOT。ENV
:用来在构建镜像的过程中设置环境变量。
ENV MY_PATH /usr/mytest
这个环境变量可以在后续的任何RUN指令中使用,相当于命令前面指定了环境变量前缀,也可以在其他指令中直接使用这些环境变量。如 WORKDIR $MY_PATH
ADD
:将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包。COPY
: 类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中<源路径>
的文件/目录复制到新的一层镜像内的<目标路径>
COPY src dest
COPY ["src","dest"]
:源文件或者源目录。
:容器内的指定路径,该路径不用事先建好,路径不存在会创建。VOLUME
:容器卷,用于数据保存和持久化工作。CMD
:指定容器启动后干的事。命令格式与RUN相似。
ENTRYPOINT
指令后,用CMD
指定具体的参数。ENTRYPOINT
: 指定一个容器启动时要运行的命令。类似于cmd指令,但是ENTRYPOINT不会被docker run后面的命令覆盖,而且类似于CMD命令行参数送给ENTRYPOINT指令指定的程序。
Entrypoint和Cmd都是用于指定容器启动时要运行的命令,主要区别在于它们的作用和使用方式。
Entrypoint是指定容器启动时要执行的可执行文件或脚本,并且该命令在运行容器时不能被覆盖。Entrypoint可以看作是容器的默认执行命令,它会在运行容器时自动执行。如果在运行容器时指定了其他命令,则这些命令将作为Entrypoint命令的参数传递给容器。例如,在Dockerfile中指定Entrypoint为一个可执行文件,如下所示:ENTRYPOINT ["./app"]
。在运行容器时可以使用以下命令:docker run myapp arg1 arg2
,这样将运行容器,自动执行Entrypoint命令"./app",并将"arg1"和"arg2"作为参数传递给它。
Cmd是指定容器启动时要执行的默认命令或参数。它可以被覆盖,如果在运行容器时指定了其他命令,则这些命令将替换掉Cmd命令。例如,在Dockerfile中指定Cmd为一个默认参数,如下所示:CMD ["--port","80"]
。在运行容器时可以使用以下命令:docker run myapp --port 8080
,这样将运行容器,并使用"–port 8080"替换掉默认的Cmd命令参数"–port 80"。
#基础镜像,继承于centos
FROM centos
#指定作者
MAINTAINER xxx<[email protected]>
#指定目录
ENV MYPATH /usr/local
#进入命令
WORKDIR $MYPATH
#安装vim编辑器
RUN yum -y install vim
#按装ifconfig命令查看网络IP
RUN yum -y install net-tools
#安装java8及lib库
#gcc的一个加强安装包
RUN yum -y install glibc.i686
#创建一个目录
RUN mkdir /usr/local/java
#ADD是相对路径jar,把jdk-8u171-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerile文件在同一位置
ADD jdk-8u171-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_171
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH
EXPOSE 80
CMD echo $MYPATH
CMD echo "success-------ok"
CMD /bin/bash
在Dockerfile目录下,输入命令。
docker build -t 新镜像名字:TAG .
仓库名、标签都是
的镜像,俗称dangling image(虚悬镜像)。
建议删除,这个东西并没有什么用。
from ubuntu
docker build .
docker image ls -f dangling=true
docker image prune
#基础镜像使用java
FROM java:8
#作者
MAINTAINER xxxxx
# VOLUME指定临时文件目录为/tmp,在主机 /var/lib/docker 目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp
#将jar包添加到容器中并更名为xxx_docker. jar
ADD docke_boot-0.0.1-SNAPSHOT.jar xxx_docker.jar
#运行jar包
RUN bash .C 'touch/zzy_docker.jar'
ENTRYPOINT ["java","-jar","/xxx_docker.jar"]
#暴露8080端口作为微服务
EXPOSE 8080
docker build -t xxx_docker.jar .
curl 127.0.0.1:8080/test/test1
systemctl stop firewalld
systemctl restart docker
virbr0
网卡(virbr0网卡:它还有一个固定的默认IP地址192 168.122.1),是做虚拟机网桥的使用的,其作用是为连接其上的虚机网卡提供NAT访问外网的功能。产生了个名为docker0的虚拟网桥,通过此网桥与宿主机或者容器间进行通信。
命令docker network COMMAND
查询网络相关命令
docker network ls
:查看网络模式docker network connect
:连接docker network create
:创建网络模式docker network disconnect
:中断docker network prune
:删除所有无效网络docker network rm xxx网络名称
:删除网络模式docker network inspect xxx网络名称
:查看网络数据源bridge
:为每一个容器分配、设置IP等,并将容器连接到一个docker0,虛拟网桥,默认为该模式。使用--network bridge
指定(默认使用dicker0)。host
:容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。使用--network host
指定。none
:容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair
和网桥连接,IP等。使用--network none
指定。container
:新创建的容器不会创建自己的网卡和配置自己的IP,而是和一个指定的容器共享IP端口范围。使用--network container:NAME或者容器ID
指定。-p
或--publish
参数指定端口映射规则时,Docker会将容器内部的端口映射到宿主机上的一个随机端口或指定的端口上。docker inspect u1 | tail -n 20
docker inspect u2 | tail -n 20
当删除U2后,再创建U3时,U3的IP和删除前的U2一样。所以,底层的网络是会变动的,当写死IP后,万一服务器宕机或者被删,会造成很严重后果。 所以,需要通过网络规划好网络服务。
Docker服务默认会创建一个docker0网桥(其上有一个docker0
内部接口),该桥接网络的名称为docker0
,它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。Docker默认指定了docker0
接口的IP地址和子网掩码,让主机和容器之间可以通过网桥相互通信。
#查看bridge网络的详细信息,并通过grep获取名称项
docker network inspect bridge | grep name
ifconfig | grep docker
ip addr # 查看网络
docker0
),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP
,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP
直接通信。docker run
的时候,没有指定network
的话默认使用的网桥模式就是bridge
,使用的就是docker0
。在宿主机ifconfg
,就可以看到docker0
和自己create
的network
,eth0
,eth1
,eth2
…代表网卡一,网卡二,网卡三… lo
代表127.0.0.1
,即localhost
, inet addr
用来表示网卡的IP地址。docker0
创建一 对对等虚拟设备接口一个叫veth
,另一个叫eth0
,成对匹配。
docker0
,类似一个交换机有一堆接口,每个接口叫veth
,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair
) ;eth0
;docker0
上面的每个veth
匹配某个容器实例内部的eth0
,两两配对,一一匹配。23的veth
对应22的etho
ip addr # 查看网络
2. 容器查看网络,发现有个22的etho
对应23的veth
ip addr # 查看网络
直接使用宿主机的IP地址与外界进行通信,不再需要额外进行NAT转换。
网络信息:docker inspect 容器名(host网络模式)
容器将不会获得一个独立的Network Namespace
,而是和宿主机共用一个Network Namespace
。容器将不会虚拟出自己的网卡而是使用宿主机的IP和端口。
docker run -d -p 8083:8080 --network host --name tomcat83 test/tomcat8-jdk8
--network=hos
t或-net=host
,如果还指定了-p
映射端口,那这个时候就会有此警告,-p
设置的参数将不会起到任何作用,端口号会以主机端口号为主,重复时则递增。--network=bridge
。禁用网络功能,只有Io
标识(就是127.0.0.1
表示本地回环)。
Docker
容器添加网卡、配置IP等。查看网络信息:docker inspect 容器名
容器内部查看网络信息:ip addr
新创建的容器不会创建自己的网卡和配置自己的IP, 而是和一个指定的容器共享IP、 端口范围等。
新建的容器和己经存在的一个容器共享一个网络ip配置 而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样。两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。
docker run -d -p 8085:8080 --name tomcat85 xxx/tomcat8-jdk8
docker run -d -p 8086:8080 --network container:tomcat85 --name tomcat86 xxx/tomcat8-jdk8
报错:
原因:相当于tomcat86
和tomcat85
公用同一个ip同-一个端口,导致端口冲突。
docker run -it --name alpine1 alpine /bin/sh
docker run -it --network container:alpine1 --name alpine2 alpine /bin/sh
docker run -d -p 8081:8080 --name tomcat81 xxx/tomcat8-jdk8
docker run -d -p 8082:8080 --name tomcat82 xxx/tomcat8-jdk8
成功启动并用docker exec
进入各自容器实例内部
tomcat81:
tomcat82:
在tomcat82 ping
tomcat81的ip或者tomcat81 ping
tomcat82的ip,没有任何问题。
在tomcat81
和tomcat82
直接ping对方服务名,报错
自定义桥接网络,自定义网络默认使用的是桥接网络bridge
docker network create my_network
docker run -d -p 8081:8080 --network my_network --name tomcat81 xxx/tomcat8-jdk8
docker run -d -p 8082:8080 --network my_network --name tomcat82 xxx/tomcat8-jdk8
自定义网络本身就维护好了主机名和ip的对应关系(ip和域名都能通)
docker启动的容器服务均无法访问,容器启动后浏览器访问一直提示网络连接错误。
启动容器时有以下提示
WARNING: IPv4 forwarding is disabled. Networking will not work.
在sysctl.conf文件中追加以下
# 1代表启用
net.ipv4.ip_forward=1
然后使用以下命令重启服务器网络
systemctl restart network
再次通过浏览器访问docker容器相关服务,一切正常
没有开启转发,网桥配置完后,需要开启转发,不然容器启动后,就会没有网络
Compose是Docker公司推出的一个工具软件,可以管理多个Docker容器组成个应用。你需要定义一个YAML格式的配置文件docker-compose.yml
,写好多个容器之间的调用关系。然后,只要一个命令, 就能同时启动关闭这些容器。
指的是docker-compose.yml
docker-compose.yml
文件中定义。官方介绍文档
下载地址
centos安装
curl -L https://github.com/docker/compose/releases/download/v2.14.1/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
# 或者:
curl -L http://mirror.azure.cn/docker-toolbox/linux/compose/v2.14.1/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
# 卸载
sudo rm /usr/1oca1/bin/docker-compose
ubuntu安装
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose.yml
定义一个完整业务单元,安排好整体应用中的各个容器服务。docker-compose up
命令来启动并运行整个应用程序,完成一键部署上线。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
:展示当前docke-compose编排过的容器进程。
docker-compose logs yml里面的服务id
:查看容器输出日志。
dokcer-compose config
:检查配置。
dokcer-compose config -q
:检查配置,有问题才有输出。
docker-compose restart
:重启服务。
docker-compose start
:启动服务。
docker-compose stop
:停止服务。
可以用来设置容器环境变量。它可以用于配置应用程序所需的各种环境变量,如数据库连接字符串、API密钥等。通过在docker-compose.yml
文件中使用environment
选项,您可以将键值对形式的环境变量添加到容器中。
version: '3'
services:
my-app:
image: my-image
environment:
- DATABASE_URL=mysql://user:password@db:3306/mydb
- API_KEY=abc123
用于在容器启动时运行特定的命令。您可以使用command
选项来覆盖Docker
镜像中定义的默认命令。这在需要在容器启动时运行特定的脚本或命令时非常有用。
version: '3'
services:
my-app:
image: my-image
command: python script.py
类似于command
选项,用于定义容器启动时运行的命令或脚本。不同之处在于entrypoint
的值会被作为容器的默认入口点,在其后面可以附加命令参数。与command
选项不同,entrypoint
选项一般用于定义服务所需的主要命令,而command
选项用于提供额外的参数。
version: '3'
services:
my-app:
image: my-image
entrypoint: ["python", "app.py"]
environment
选项适用于需要将环境变量传递给应用程序的情况,例如配置数据库连接字符串或设置API密钥。command
选项适用于覆盖Docker镜像中默认的启动命令,例如运行特定的脚本或指定不同的启动参数。entrypoint
选项适用于定义容器的默认入口点,在其后可以添加命令参数,例如指定要运行的主要应用程序和其它参数。#基础镜像使用java
FROM java:8
#作者
MAINTAINER xxx
# VOLUME指定临时文件目录为/tmp, 在主机 /var/ib/docker 月录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp
#将jar包添加到容器中并更名为zzyy_ dockerjar
ADD docker_boot-0.0.1-SNAPSHOT.jar xxx_docker.jar
#运行jar包
RUN bash -c 'touch xxx_docker.jar'
ENTRYPOINT ["ava","jar","xxx_docker.jar"]
#暴露8080端口作为微服务
EXPOSE 8080
docker build -t xxx_docker:1.6
1.创建数据库实例,并且创建数据表
docker run - P 3306:3306 --name mysql57 --privileged=true -v /xxx/mysgl/conf:/etc/mysql/conf.d -v /xxx/mysql/logs:/logs -v /xxx/mysql/data:/var/lib/mysql -e MYSQL_R0OT_PASSWORD=123456 -d mysql:5.7
docker run -p 6379:6379 --name redis608 --privileged=true -v /app/redis/redis.conf:/etc/redis/redis.conf -v /app/redis/data:/data -d redis:6.0.8 redis-server /etc/redis/redis.conf
docker run -d -p 8080:8080 xxx_docker
version: "3" #compose版本号
services: #服务容器实例,下面写服务名
microService: # 服务名 自定义即可
image: xxx_docker:1.6 # 镜像名:版本号,还可以用build构建
container_name: ms01 # 容器名 --name 不加容器名会在显示的时候自动加前后缀 当前目录_服务名_数字标号
ports: # 端口映射 -p
- "8080:8080"
volumes: # 容器数据卷 -v
- /app/microSerice:/data
networks: #网络选择 --network
- xx_net # 最底下有定义
depends_on: # 依赖项,依赖于下面的项目 项目名即服务名
- redis
- mysql
redis:
image: redis:6.0.8
#container_name: redis # 容器名 --name 不加容器名会在显示的时候自动加前后缀 当前目录_redis_1
ports:
- "6379:6379"
volumes:
- /app/redis/data:/data
networks:
- xxx_net
command: redis-server /etc/redis/redis.conf
mysql:
image: mysq:5.7
#container_name: redis # 容器名 --name 不加容器名会在显示的时候自动加前后缀 当前目录_redis_1
networks:
- xxx_net
ports:
- "3306:3306"
environment: # 环境配置
MYSQL_ROOT_PASSWORD: '123456'
# MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
# MYSQL_DATABASE: 'db2021"
# MYSQL_USER: "root"
# MYSQL_PASSWORD: "123456"
volumes:
- $PWD/mysql/db:/var/lib/mysql
- $PWD/mysql/conf:/etc/mysql/conf
- $PWD/mysql/init:/docker-entrypoint-initdb.d
command: --default-authentication-plugin=mysql_native_password #解决外部无法访问问题
networks:
xx_net: #网络模式名字,查看显示的时候会在前面添加前缀 当前目录_xx_net
spring:
datasource:0
url: jdbc:mysql://mysql:3306/db2021?useUnicode=true&characterEncoding=utf-8&useSSL-false
#url: jdbc:mysql://192.168.111.168:3306/db2021?useUnicode=true&characterEncoding=utf-8&useSSL-false
redis:
#host:192.168.111.168
host:redis
docker build -t xxx_docker:1.6
dokcer-compose config -q
命令,检查docker-compose
语法是否有问题,没输出则没问题。docker-compose up -d
命令docker-compose stop
Portainer是一款轻量级的应用,它提供了图形化界面,用于方便地管理Docker环境,包括单机环境和集群环境。
官网
linux安装地址
docker run -d -p 8000:8000 -p 9000:9000 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v xxx/xxx/portainer_data:/data portainer/portainer
-v /var/run/docker.sock:/var/run/docker.sock
运行Docker的目录映射,必须要有才能用Portainer操作Docker命令
CAdvisor监控收集
+ InfluxDB存储数据
+ Granfana展示图表
version: '3.1'
volumes:
grafana_data: {}
services:
influxdb:
image: tutum/influxdb:0.9
restart: always
environment:
- PRE_CREATE_DB=cadvisor
ports:
- "8083:8083"
- "8086:8086"
volumes:
- ./data/influxdb:/data
cadvisor:
image: google/cadvisor
links:
- influxdb:influxsrv
command: -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influxsrv:8086
restart: always
ports:
- "8082:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
grafana:
user: "104"
image: grafana/grafana
restart: always
links:
- influxdb:influxsrv
ports:
- "3001:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- HTTP_USER=admin
- HTTP_PASS=admin
- INFLUXDB_HOST=influxsrv
- INFLUXDB_PORT=8086
- INFLUXDB_NAME=cadvisor
- INFLUXDB_USER=root
- INFLUXDB_PASS=root
-storage_driver相关参数:
-storage_driver driver
要使用的存储驱动程序。数据总是短时缓存在内存中,这控制了将数据推送到本地缓存之外的位置。空意味着没有。选项包括:<empty>,bigquery,elasticsearch,influxdb,kafka,redis,statsd,stdout
-storage_driver_buffer_duration duration
存储驱动程序中的写操作将在此期间进行缓冲,并作为单个事务提交给非内存后端(默认为1m0s)
-storage_driver_db string
数据库名称(默认为“ cadvisor”)
-storage_driver_es_enable_sniffer
默认情况下,ElasticSearch使用嗅探过程自动查找集群中的所有节点
-storage_driver_es_host string
ElasticSearch主机:端口(默认为“ http:// localhost:9200”)
-storage_driver_es_index string
ElasticSearch索引名称(默认为“cadvisor”)
-storage_driver_es_type string
ElasticSearch类型名称(默认为“ stats”)
-storage_driver_host string
数据库主机:端口(默认为“ localhost:8086”)
-storage_driver_influxdb_retention_policy string
保留政策
-storage_driver_kafka_broker_list string
kafka经纪人csv(默认为“ localhost:9092”)
-storage_driver_kafka_ssl_ca string
TLS客户端身份验证的可选证书颁发机构文件
-storage_driver_kafka_ssl_cert string
TLS客户端身份验证的可选证书文件
-storage_driver_kafka_ssl_key string
TLS客户端身份验证的可选密钥文件
-storage_driver_kafka_ssl_verify
验证ssl证书链(默认为true)
-storage_driver_kafka_topic string
kafka主题(默认为“统计信息”)
-storage_driver_password string
数据库密码(默认为“ root”)
-storage_driver_secure
与数据库使用安全连接
-storage_driver_table string
表名(默认为“统计信息”)
-storage_driver_user string
数据库用户名(默认为“ root”)
-storage_duration duration
保存数据的时间(默认值:2分钟)
docker-compose config -q
没有输出则正确
docker-compose up -d
docker-compose up
docker ps
cadivisor报如下错
去官网(或者CSDN加速的镜像官网)看发现官网给的是gcr.io/cadvisor/cadvisor:$VERSION
镜像,但是镜像拉不下来,可以挂梯子试试。
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.44.0
#image: google/cadvisor:latest
links:
- influxdb:influxsrv
command: -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influxsrv:8086
restart: always
ports:
- "8081:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro