目录
Docker
1、概念
2、架构图
3、安装
4、Docker怎么工作的?
5、Docker常用命令
帮助命令
镜像命令
1、查看镜像
2、帮助命令
3、搜索镜像
4、拉取镜像
5、删除镜像
容器命令
1、启动
2、查看运行的容器
3、删除容器
4、启动&停止
其他命令
1、后台启动容器
2、查看日志
3、查看容器内的进程信息
4、查看镜像的元数据
5、进入当前正在运行的容器
方式一
方式二
6、从容器内拷贝文件到主机上
6、小结
7、Docker安装Nginx
1、搜索镜像
2、下载镜像
3、运行镜像
4、测试
停止
流程
思考
8、Docker安装Tomcat
1、下载并启动
2、测试&问题
3、解决问题
4、再测试
思考
9、部署es&kibana
1、启动
2、查看内存状态
3、停掉
4、增加内存限制
5、测试
思考
10、可视化
1、什么是portainer?
2、测试
11、镜像
1、是什么?
2、怎么获得?
2.镜像加载原理
3、镜像层&容器层
4、提交自己的镜像
1、启动
2、进入并拷贝
3、提交镜像
12、Docker理念
持久化
同步操作
13、容器数据卷(Volume)
同步文件
1、挂载 -v
2、测试
3、反向测试
安装MySQL
1、下载
2、测试连接
具名&匿名挂载
1、匿名挂载
2、具名挂载
3、卷路径
4、判断是哪种挂载?
初识DockerFile
1、构建自己的镜像
2、匿名挂载同步查看
数据卷容器
1、容器挂载
2、删除测试
多个MySQL实现数据共享
结论
再见DockerFile
构建步骤
构建过程
DockerFile指令
实战测试
1、编写DockerFile
2、测试
查看构建历史
CMD&ENTRYPOINT
1、测试CMD
2、测试ENTRYPOINT
Tomcat镜像
Dockerfile
运行&挂载
测试
主机修改tomcat
外网访问
catalina.out
发布自己的镜像
DockerHub
阿里云
Docker流程
14、Docker网络
1、清空环境
2、查看地址
3、问题
1、启动容器并查ip
2、ping测试
启动容器后我们再次测试 ip a
再启动一个tomcat测试
绘制网络模型图
3、容器互联--link
4、自定义网络
网络模式
1、清理环境
2、创建我们自己的网络
3、启动测试我们自己的网络
4、网络连通
15、Redis集群部署实战
1、redis集群的搭建
2、停掉主机&获取值
3、查看集群节点信息
16、打包镜像
1、打包项目
2、编写Dockerfile
3、构建镜像
4、测试访问
本地测试
外网访问
Docker
1、概念
Docker核心思想:隔离,每个箱子是隔离的,打包装箱。
虚拟机技术缺点
1、资源占用多
2、冗余步骤多
3、启动慢
容器技术
容器化技术不是模拟的一个完整的操作系统。
比较Docker和虚拟机技术的不同:
-
传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件。
-
容器内的应用直接运行在宿主机,容器是没有自己内核的,也没有虚拟我们的硬件,所以就轻便了。
-
每个容器间是相互隔离的,每个容器内都有一个属于自己的文件系统,互不影响。
优点:
2、架构图
镜像(image):【类】
docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,Tomcat镜像-->run-->tomcat1容器(提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。
容器(container):【对象】
Docker利用容器技术,独立运行一个或者一个组应用,通过镜像来创建。目前可以把这个容器理解为就是一个简易的Linux系统。
仓库(repository):存放镜像的地方。分为共有仓库和私有仓库。
3、安装
环境准备:
1、保证系统内核在3.10以上
uname -r
我的版本:3.10.0-1160.el7.x86_64
2、查看镜像是否是centos7
cat /etc/os-release
3、进入帮助文档
Get Docker | Docker Docs
开始
1、旧版本的 Docker
yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine
2、需要的安装包
yum install -y yum-utils
3、\textcolor{red}{设置镜像仓库} ,解决下载慢
yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
4、更新软件包索引
yum makecache fast
5、安装docker引擎(ce 社区版)
yum install docker-ce docker-ce-cli containerd.io
6、启动docker
systemctl start docker
7、通过版本号查看是否启动成功
docker version
8、测试运行
docker run hello-world
9、查看拉取的镜像
docker images
附:怎么卸载引擎?
1、卸载依赖 yum remove docker-ce docker-ce-cli containerd.io 2、删除资源 rm -rf /var/lib/docker /var/lib/docker 这个是docker的默认工作路径。
4、Docker怎么工作的?
Docker是一个Client-Server结构的系统,Docker的守护进程运行在主机上,通过Socket从客户端访问!
DockerServer接收到Docker-Client的指令,就会执行这个命令!
Docker为什么比VM快?
1、Docker有着比虚拟机更少的抽象层。
2、Docker利用的是宿主机的内核,vm 需要 guest os
新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导。虚拟机是加载 guest os ,分钟级别的,而docker是利用宿主机的操作系统,省略了这个复杂的过程,秒级。
5、Docker常用命令
docker | Docker Docs
镜像就像手机中APP安装包,容器就像已安装的APP应用
帮助命令
1、查看版本 docker version 2、查看信息(镜像和容器的数量等) docker info 3、查看命令 docker 命令 --help
镜像命令
1、查看镜像
1、查看本地主机上所有的镜像 [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest feb5d9fea6a5 4 weeks ago 13.3kB REPOSITORY 镜像的仓库源 TAG 镜像的标签 IMAGE ID 镜像的id CREATED 镜像的创建时间 SIZE 镜像的大小 Options(选项): -a, --all # 列出所有的镜像 -q, --quiet # 只显示镜像的id
2、帮助命令
docker images --help
3、搜索镜像
搜索镜像 [root@localhost ~]# docker search mysql NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 11593 mariadb MariaDB Server is a high performing open sou… 4409 mysql/mysql-server Optimized MySQL Server Docker images. Create… 857 STARS:收藏量 --filter=STARS=3000 搜索出来的镜像就是收藏量大于3000的。
过滤搜索镜像:
4、拉取镜像
下载镜像 docker pull 镜像名[:tag] # 如果不写tag,默认就是最新版本
解决下载镜像慢!
##使用阿里云镜像加速器 [root@localhost ~]# mkdir -p /etc/docker [root@localhost ~]# tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://9cpn8tt6.mirror.aliyuncs.com"] } EOF [root@localhost ~]# systemctl daemon-reload [root@localhost ~]# systemctl restart docker
指定版本下载:
docker pull mysql:5.7
查看下载的镜像:
5、删除镜像
删除镜像:
rm:删除 i:images -f:强制删除 后面可以指定id来删除
docker rmi -f 容器id #删除指定的容器 docker rmi -f 容器id 容器id 容器id #删除多个容器 docker rmi -f $(docker images -aq) #删除全部的容器
容器命令
前提:必须有镜像才能创建容器,我们来下载一个centos镜像来测试学习。
docker pull centos
1、启动
docker run [可选参数] image /bin/bash # 参数说明 --name="Name" 容器名称 Tomcat01 Tomcat02 用来区分容器 -d 后台方式运行 -it 使用交互方式(需要给定控制台)运行,进入容器查看内容 -p 指定容器的端口(四种方式) -p ip:主机端口:容器端口 -p 主机端口:容器端口(常用) -p 容器端口 -p 随机指定端口
通过启动镜像进入容器:
/bin/bash:这个是指定的控制台
docker run -it centos /bin/bash
查看容器内的centos并退出:
exit # 从容器中退回主机 Ctrl + P + Q # 容器不停止退回主机
2、查看运行的容器
1、查看运行中的容器 docker ps 2、查看运行过的容器 docker ps -a 3、查看最近运行的容器 docker ps -a -n=1 4、查看当前所有容器的编号 docker ps -aq
3、删除容器
docker rm 容器id # 删除指定的容器 ,不能删除正在运行的容器,如果要强制删除,rm -f docker rm -f $(docker ps -aq) # 删除所有的容器 docker ps -a -q|xargs docker rm #删除所有的容器
xargs 作用:将上个命令的输出作为参数传给 docker rm 这个命令
4、启动&停止
注意:这里跟之前的 docker run [可选参数] image /bin/bash 不同,之前是第一次,没有容器id。
\textcolor{red}{启动容器后,还是在主机,并没有进入容器} !
docker start 容器id # 启动容器 docker restart 容器id # 重启容器 docker stop 容器id # 停止当前正在运行的容器 docker kill 容器id # 强制停止当前容器
其他命令
1、后台启动容器
# 命令docker run -d 镜像名 docker run -d centos
出现问题:
我们使用命令 docker ps 后,发现 centos 停止了。
\textcolor{blue}{常见的坑} :docker 容器使用后台运行,就必须要有一个前台进程,因为docker发现没有应用,就会自动停止。
例如安装Nginx:容器启动后,docker发现自己没有提供服务,就会立刻停止,就是没有程序了。
2、查看日志
# 自己编写一段shell脚本 docker run -d centos /bin/sh -c "while true;do echo giegie;sleep 1;done" # 显示日志 --tf # 显示日志 f:跟踪日志(实时显示) t:时间戳(timestamps) --tail number # 要显示的尾部日志条数 [root@localhost ~]# docker logs -tf --tail 10 4b121dd5bc49
3、查看容器内的进程信息
[root@localhost ~]# docker top 4b121dd5bc49 UID PID PPID C STIME TTY TIME CMD root 70910 70890 0 20:52 ? 00:00:00 /bin/sh -c while true;do echo giegie;sleep 1;done root 73560 70910 0 21:14 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
UID:用户id
PID:当前进程id
PPID:父进程id
4、查看镜像的元数据
docker inspect 容器id
5、进入当前正在运行的容器
我们通常使用的容器是由后台方式运行的,所以需要进入容器内来修改一些配置。
方式一
docker exec:\textcolor{red}{进入容器后开启一个新的终端,可以在里面操作(常用)} 。
# exec -it 前后台交互执行 docker exec -it 容器id /bin/bash
方式二
docker attach:\textcolor{red}{进入容器正在执行的终端,不会启动新的进程} 。
docker attach 容器id
6、从容器内拷贝文件到主机上
拷贝是一个手动过程,未来我们使用 -v 卷 的技术,可以实现。
docker cp 容器id:容器内路径 目的的主机路径
6、小结
7、Docker安装Nginx
1、搜索镜像
docker search nginx
2、下载镜像
docker pull nginx
3、运行镜像
# 先查看镜像 docker images # 取别名后运行 docker run -d --name nginx01 -p 3344:80 nginx
4、测试
1、本地测试
curl localhost:3344
2、外网测试(通过互联网)
停止
流程
思考
我们每次改动Nginx配置文件,都需要进入容器内部?这就十分的麻烦,我们通过在容器外部提供一个映射路径,达到在容器外部修改文件,容器内部就可以自动修改。 -v 数据卷!
8、Docker安装Tomcat
我们之前的启动都是后台,停止容器之后,容器还是可以查到的
# 官方的使用,下载下来,运行后,就删除容器了(镜像还在) docker run -it --rm tomcat:9.0
1、下载并启动
# 下载最新的Tomcat docker pull tomcat # 通过虚拟机端口3355映射内部tomcat端口8080,启动tomcat镜像来启动tomcat容器,取名为tomcat01 docker run -d -p 3355:8080 --name tomcat01 tomcat
2、测试&问题
首先进入网站测试,404。之后我们进入容器:
docker exec -it tomcat01 /bin/sh
进入容器内发现问题:
1、Linux命令少了。
2、没有webapps。
原因:阿里云镜像的原因,默认是最小的镜像,所有不必要的都剔除出去了。它是保证最小的可运行环境。
3、解决问题
将webapps.dist的内容全部拷贝到webapps里面。
cp -r webapps.dist/* webapps
4、再测试
思考
我们以后部署项目,每次都要进入容器,十分麻烦。我们要是可以在容器外提供一个映射路径,webapps,我们在外部放置项目,就自动同步到内部就好了。
9、部署es&kibana
es:暴露的端口多,而且十分耗内存,它的数据一般需要放置到安全目录,挂载。
官网启动弹性搜索(elasticsearch)
# --net somenetwork:网络配置,暂时不需要 docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:tag
1、启动
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
CPU资源有限,所以可能会卡。
2、查看内存状态
docker stats
3、停掉
4、增加内存限制
# 修改配置文件 -e 环境配置修改 docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
5、测试
思考
使用kibana怎么用网络连接到es?
10、可视化
portainer和Rancher(CI/CD)
1、什么是portainer?
Docker图形化界面管理工具!提供一个后台面板供我们操作。
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
2、测试
外网测试:
http://192.168.85.129:8088/
内网测试:
curl localhost:8088
11、镜像
1、是什么?
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、环境变量、配置文件。
所有的应用,直接打包docker镜像,就可以直接跑起来!
2、怎么获得?
1、从远程仓库下载
2、从朋友拷贝过来
3、自己制作DockerFile
#####
1、UnionFS
2.镜像加载原理
bootfs(文件加载系统):就像我们启动电脑->加载->界面,界面加载完成后,不需要加载了。
阉割版
资源复用
3、镜像层&容器层
4、提交自己的镜像
docker commit 提交容器成为一个新的副本
# 命令和git原理类似 docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
1、启动
# 启动一个默认的tomcat docker run -it -p 8080:8080 tomcat
2、进入并拷贝
# 发现这个默认的tomcat是没有webapps应用,镜像的原因,官方的镜像默认webapps下面是没有文件的!我们自行拷贝文件。 注意:这里新开了一个shell,之前的tomcat不要关闭了。
3、提交镜像
# 将我们操作过的容器通过commit提交为一个镜像,我们以后就使用这个我们修改过的镜像即可。 docker commit -a="gay" -m="add webapps app" 709df7e3e649 tomcat02:1.0
提交容器id后,在镜像中能看到新的镜像。也就是当前容器的状态!
类似于虚拟机里面的快照,可以回滚。
12、Docker理念
将应用和环境打包成一个镜像。
持久化
如果数据都在容器中,那么我们容器删除,数据就会丢失。
\textcolor{red}{需求:数据可以持久化} 。
MySQL的容器删了,删库跑路?
\textcolor{red}{需求:MySQL的数据可以存储在本地} 。
容器之间可以有一个数据共享的技术,Docker容器中产生的数据,同步到本地!这就是卷技术,\textcolor{red}{目录的挂载} ,将我们容器内的目录挂载到Linux虚拟机上面。
同步操作
13、容器数据卷(Volume)
容器的\textcolor{red}{持久化} 和\textcolor{red}{同步操作} ,容器间也是可以数据共享的。
方式一
同步文件
1、挂载 -v
# 直接使用命令来挂载 -v 通过主机目录映射容器内目录 docker run -it -v 主机目录:容器内目录 镜像 /bin/bash # 测试:挂载到主机后进入容器 [root@localhost home]# docker run -it -v /home/ceshi:/home centos /bin/bash
查看
# 在主机上查看上面的那个容器详情 docker inspect 容器id
理解成在主机上创建了一个快捷方式,那么容器没了,主机上的那个也就没啥用了,跟着没了。有点不同的是,它文件内容是双向绑定的!
2、测试
在容器内建一个文件,测试主机上是否也生成一个对应的文件
3、反向测试
在主机内修改文件,已经退出的容器依旧可以获取到文件内容!
# exit 退出并停止容器 # ctrl + p + q 退出不会停止容器
好处:\textcolor{red}{我们以后修改只需要在本地修改即可,容器内会自动同步} !
安装MySQL
1、下载
# 获取镜像 [root@localhost home]# docker pull mysql:5.7 # 运行容器,需要做数据挂载 # -d:后台运行 -p:端口映射 -v:卷挂载 -e:环境配置 --name:容器别名 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
2、测试连接
本地使用Navicat连接
本地新建一个数据库,去Linux上面查看
假设我们将主机上的容器删除,我们挂载到本地的数据卷依旧存在,这就实现了容器的持久化功能。
相当于只删除了一个快捷方式而已。
具名&匿名挂载
1、匿名挂载
# 匿名挂载 -v 容器内路径! -P 随机映射端口(注:p是大写的) docker run -d -P --name nginx01 -v /etc/nginx nginx # 查看所有的volume的情况 docker volume ls
2、具名挂载
# 具名挂载 -v 卷名:容器内路径 区别之前我们是: -v /xx/xx:/xx/xx docker run -d -P --name nginxginx02 -v juming-nginx:/etc/nginx nginx # 查看一下这个卷 docker volume inspect juming-nginx
3、卷路径
所有的docker容器内的卷,没有指定目录的情况下都是在
/var/lib/docker/volumes/xxxx/_data
4、判断是哪种挂载?
# 如何确定是具名挂载还是匿名挂载,还是指定路径挂载? # 1、匿名挂载 -v 容器内路径 # 2、具名挂载 -v 卷名:容器内路径 # 3、指定路径挂载 -v /宿主机路径:容器内路径 拓展: # 通过 -v 容器内路径:ro rw 改变读写权限 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作的。 ro: readonly #只读 rw: readwrite #可读可写,默认是这个 # 一旦设置了容器权限,那么容器对我们挂载出来的内容就有限定了。 docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
初识DockerFile
方式二
DockerFile就是用来构建docker镜像的构建文件!命令脚本!
通过这个脚本可以生成镜像,镜像是一层一层的,所以脚本是一个一个的命令,每个命令都是一层。
1、构建自己的镜像
# 创建一个dockerfile文件,名字可以随机,建议DockerFile [root@localhost docker-test-volume]# cat dockerfile1 FROM centos # -f:文件的地址 -t:生成的镜像名 构建,在哪里呢?名字呢? [root@localhost docker-test-volume]# docker build -f /home/docker-test-volume/dockerfile1 -t chenjun/centos:1.0 . # 文件中内容,注意VOLUME之后要有个空格。指令(大写)参数,这里的每个命令,就是镜像的一层,这种是匿名挂载 FROM centos VOLUME ["volume01","volume02"] CMD echo "----end----" CMD /bin/bash
将chenjun/contos:1.0挂载到cenos(即FROM centos)
2、匿名挂载同步查看
数据卷容器
1、容器挂载
通过我们刚才写的自己的镜像来启动三个容器 docker run -it --name docker01 容器id或者自己取的容器名 # --volumes-fom:将docker02挂载到docker01上面 docker run -it --name docker02 --volumes-fom docker01 容器id或者自己取的容器名
docker03挂载到docker01上面
2、删除测试
哪怕你删除了docker01,其他两个不会收到影响, --volumes-fom 类似于备份一样。他们都是挂载到宿主机上面了!
区别于之前的挂载,那是一种类似创建快捷方式(双向、共享),!
注意:容器需要先启动,你才能通过 exec -it 或者 attach 进入。
多个MySQL实现数据共享
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 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 mysql:5.7
结论
容器之间配置信息的传递,数据卷容器的声明周期一直持续到没有容器使用为止。
但是一旦你持久化到了本地(-v),这个时候,本地的数据是不会删除的。
再见DockerFile
DockerFile就是用来构建docker镜像的构建文件!命令脚本!
构建步骤
-
1、编写一个DockerFile文件
-
2、docker build 构建成为一个镜像
-
3、docker run 运行镜像
-
4、docker pull 发布镜像(DockerHub、阿里云镜像仓库!)
很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像。
构建过程
-
1、每个保留关键字(指令)都必须是大写字母
-
2、从上到下的顺序执行
-
3、# 表示注释
-
4、每一个指令都会创建提交一个新的镜像层,并提交!
DockerFile是面向开发的,我们以后需要发布项目,做镜像,就需要编写DockerFile文件。Docker镜像逐渐成为企业交付的标准。
DockerFile:构建文件,定义了一切的步骤,源代码。
DockerImages:通过DockerFile构建生成的镜像,最终发布和运行的产品。
Docker容器:容器就是镜像运行起来提供服务器。
DockerFile指令
通过DockerFile指令,我们可以自己写镜像!
FROM # 基础镜像,一切从这里构建 centos MAINTAINER # 镜像是谁写的,姓名+邮箱 RUN # 镜像构建时需要运行的命令 ADD # 步骤:tomcat镜像,这个tomcat压缩包,添加内容 WORKDIR # 镜像的工作目录 例如:/bin/bash VOLUME # 挂载的目录 EXPOSE # 暴露端口配置 CMD # 指定这个容器启动时需要运行的命令,只有最后一个会生效,可被替代。 ENTERYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令 ONBUILD # 当构建一个被继承DockerFile时,就会运行ONBUILD的指令,触发指令。 COPY # 类似ADD,将我们文件拷贝到镜像中 ENV # 构建的时候设置环境变量
实战测试
1、编写DockerFile
# 编写一个自己的DockerFile文件 echo:输出 在原有的centos上写自己的镜像。 FROM centos MAINTAINER chenjun<1318593513@qq.com> ENV MYPATH /usr/local WORKDIR $MYPATH RUN yum install -y vim RUN yum install -y net-tools EXPOSE 80 CMD echo $MYPATH CMD echo "----end----" CMD /bin/bash # 构建 -f:DockerFile文件路径 -t:镜像名:[tag] docker build -f mydockerfile-centos -t mycentos:0.1 .
原本是没有vim命令的,现在我们给他装上。
2、测试
查看构建历史
这个查看历史可以方便我们查看别的镜像是怎么构建的!!!
[root@localhost docker-file]# docker history 镜像id
CMD&ENTRYPOINT
CMD # 指定这个容器启动时需要运行的命令,只有最后一个会生效,可被替代。 ENTERYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
1、测试CMD
vim dockerfile-cmd-test # 建文件 FROM centos CMD ["ls","-a"] # 构建DockerFile,即自己的镜像 docker build -f dockerfile-cmd-test -t cmdtest . # 运行,这里的镜像没有版本号,所以不用加 docker run -it cmdtest
替换,不可追加!
[root@localhost docker-file]# docker run -it cmdtest -l docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "-l": executable file not found in $PATH: unknown. ERRO[0000] error waiting for container: context canceled # cmd的情况下,-l 替换了CMD["ls","-a"]命令,-l不是命令,所以报错了。
2、测试ENTRYPOINT
可追加!
vim dockerfile-cmd-entrypoint # 建文件 FROM centos ENTRYPOINT ["ls","-a"] # 构建DockerFile,即自己的镜像 docker build -f dockerfile-cmd-entrypoint -t entrypoint-test .
Tomcat镜像
-
1、准备镜像文件 tomcat 压缩包,jdk 的压缩包。
-
2、编写DockerFile文件,官方命名\textcolor{red}{Dockerfile} ,build会自动寻找这个文件,就不用 -f 去指定了。
-
3、构建生成的目标镜像 docker build -t diytomcat . 这个 diytomcat 就是我们的镜像!
Dockerfile
FROM centos MAINTAINER chenjun<1318593513@qq.com> COPY readme.txt /usr/local/readme.txt ADD jdk-8u11-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-9.0.22.tar.gz /usr/local/ RUN yum install -y vim ENV MYPATH /usr/local WORKDIR $MYPATH ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk1.8.0_11 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.22 ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.22 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-9.0.22/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.22/bin/logs/catalina.out
运行&挂载
[root@localhost tomcat]# docker run -d -p 9090:8080 --name chenjuntomcat -v /home/chenjun/build/tomcat/test://usr/local/apache-tomcat-9.0.22/webapps/test -v /home/chenjun/build/tomcat/tomcatlogs:/usr/local/apache-tomcat-9.0.22/logs diytomcat
测试
主机修改tomcat
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> </web-app>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>hello. xiaofan</title> </head> <body> Hello World!<br/> <% System.out.println("-----my test web logs------"); %> </body> </html>
外网访问
catalina.out
[root@localhost tomcatlogs]# pwd /home/chenjun/build/tomcat/tomcatlogs # 查看多少人访问了我们的这个服务器 [root@localhost tomcatlogs]# cat catalina.out
发布自己的镜像
DockerHub
-
1、地址:https://hub.docker.com/ 注册自己的账号
-
2、登录:docker login -u jc110
-
3、标签:docker tag 镜像id jc110/tomcat:1.0
-
4、推送:docker push jc110/tomcat:1.0
DockerHub
阿里云
阿里云镜像服务
-
1、登录阿里云
-
2、找到容器镜像服务
-
3、创建命名空间
-
4、创建容器镜像
-
5、docker登录后推送
$ docker login --username=jc_s**** registry.cn-hangzhou.aliyuncs.com $ docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/gay/gaytest:[镜像版本号] $ docker push registry.cn-hangzhou.aliyuncs.com/gay/gaytest:[镜像版本号]
报错:
Error response from daemon: Get "https://registry.cn-hangzhou.aliyuncs.com/v2/": unauthorized: authentication required
解决:
登录
docker login --username=jc_study registry.cn-hangzhou.aliyuncs.com
查看
Docker流程
docker save保存的是镜像(image),docker export保存的是容器(container)。
docker load用来载入镜像包,docker import用来载入容器包,但两者都会恢复为镜像。
14、Docker网络
1、清空环境
# 我们先删除所有的容器和镜像 # 强制删除所有的容器 [root@localhost ~]# docker rm -f $(docker ps -aq) # 强制删除所有的镜像 [root@localhost ~]# docker rmi -f $(docker images -aq)
2、查看地址
# 查看地址 ip a 或者 ip addr 或者 ifconfig [root@localhost ~]# ip a
3、问题
docker是如何处理容器网络访问的?
1、启动容器并查ip
# 拉取并通过后台运行tomcat镜像来启动容器 [root@localhost ~]# docker run -d -P --name tomcat01 tomcat # 查看容器的内部网络地址 ip addr [root@localhost ~]# docker exec -it tomcat01 ip addr
遇到问题:
# docker exec -it tomcat01 ip addr错误docker没有ip指令 OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "ip": executable file not found in $PATH: unknown
解决问题:
# 进入容器执行 apt-get update & apt-get install -y iproute2 root@93989b839391:/usr/local/tomcat# apt-get update & apt-get install -y iproute2
# 发现容器启动的时候会得到一个docker分配的 eth0@if97 的ip地址
2、ping测试
# Linux虚拟机ping通docker容器内部 [root@localhost ~]# ping 容器ip
原理
172.17.0.1 这个是docker给我们的主机的ip
172.17.0.2 这个是docker给我们的容器(tomcat01)的ip
我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0桥接模式,使用的技术是 veth-pair 技术!
启动容器后我们再次测试 ip a
97: eth0@if96
容器内 ip addr
96: eth0@if97
再启动一个tomcat测试
99: vethd82c62d@if98
进入容器后 ip a
172.17.0.2 这个是docker给我们的容器(tomcat02)的ip
98: eth0@if99
我们发现这个容器带来网卡,都是一对一对的
veth-pair就是一对的虚拟机接口,他们都是成对出现的,一端连着协议,一端彼此相连。(veth意思是virtual ethernet,虚拟以太网连接)
正因为这个特性,veth-pair 充当一个桥梁,连接各种 虚拟网络设备的
OpenStac,Docker容器之间的连接,OVS的连接,都是使用veth-pair
tomcat01和tomcat02 都在同一个网段,所以它两都是可以相互ping通的,即:容器和容器之间是可以相互ping通的!
docker exec -it tomcat02 ping 172.17.0.2
绘制网络模型图
结论:tomcat01和tomcat02 是共用的一个路由器,docker0。
所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用ip。
小结
Docker使用的是Linux的桥接,宿主机中是一个Docker容器的网桥 docker0 。
Docker中所有的网络接口都是虚拟的,虚拟的转发效率高!(内网传递文件,很快。)
只要容器停止/删除,对应的网桥一对就没有了。
255.255.0.1/16
可用主机数:2 的16次方 -2 (减去网关和广播)= 65 534
255.255.255.255
11111111.11111111.11111111.11111111
前16个叫网络位,后16个是主机位。与或算法
思考
我们编写微服务的时候需要绑定数据库,database url=ip:,项目不重启,数据库ip换掉了,我们怎么处理这个问题?可以用名字来进行容器的访问。
这里启动不同的容器ip都不同,这怎搞?
解决:类似springcloud的feign去Nacos找服务名即可。
3、容器互联--link
# 以交互方式进入正在运行的容器 tomcat02 [root@localhost ~]# docker exec -it tomcat02 /bin/bash # 发现 tomcat02的 ping 命令无法使用 root@db1ab920ec45:/usr/local/tomcat# ping tomcat01 # 解决 apt install iputils-ping # 如果执行错误,先执行这个: apt-get update root@db1ab920ec45:/usr/local/tomcat# apt install iputils-ping
tomcat02去ping通tomcat01测试
# 出现问题 root@db1ab920ec45:/usr/local/tomcat# ping tomcat01 ping: tomcat01: Name or service not known # 怎么解决? [root@localhost ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat # 出现问题 OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "ping": executable file not found in $PATH: unknown # 怎么解决? root@dfdd58783733:/usr/local/tomcat# apt-get update & apt-get install -y iproute2 # 出现问题 bash: ping: command not found # 怎么解决? root@dfdd58783733:/usr/local/tomcat# apt install iputils-ping # 如果执行错误,先执行这个: apt-get update
之前我们是通过ip去ping通的,现在我们link过后直接通过服务名去ping通!
# 列举网络 [root@localhost ~]# docker network ls # 查看网络详情 [root@localhost ~]# docker network inspect 2704ec4445bc
之前我们用tomcat03去连接tomcat02
docker run -d -P --name tomcat03 --link tomcat02 tomcat
# 查看host配置,在这里原理发现! [root@localhost ~]# docker exec -it tomcat03 cat /etc/hosts
--link 就是我们在 hosts 配置中增加了一个 172.17.0.3 tomcat02 db1ab920ec45,但是tomcat02却没有绑定tomcat01。
我们现在已经不建议使用--link了。自定义网络,不使用docker0.
docker0的问题:他不支持容器名连接访问。
4、自定义网络
# 查看所有的docker网络 [root@localhost ~]# docker network ls
网络模式
bridge:桥接 docker 搭桥(默认,自己架构也使用这个)
host:和宿主机共享网络
none: 不配置网络
container:容器内网络连通(用的少,局限很大)
测试
1、清理环境
2、创建我们自己的网络
# 我们直接启动命令 --net bridge ,而这个是我们的docker0 # 平常写法 [root@localhost ~]# docker run -d -P --name tomcat01 # 相当于下面这种默认的 [root@localhost ~]# docker run -d -P --name tomcat01 --net bridge tomcat # docker0特点:默认的,域名不能访问,--link可以打通连接。 # 我们可以自定义一个网络 # --driver bridge # --subnet 192.168.0.0/16 可以支持255*255个网络 192.168.0.2 ~ 192.168.255.254 # --gateway 192.168.0.1 [root@localhost ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
查看我们自己配置的网络的详情
[root@localhost ~]# docker network inspect mynet
3、启动测试我们自己的网络
[root@localhost ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat [root@localhost ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat [root@localhost ~]# docker network inspect mynet
# 再次测试两个容器的ping连接,可以成功 docker exec -it tomcat-net-01 ping 192.168.0.3
我们自定义的网络docker都已经帮我们维护好了对应的关系,推荐平时这样使用网络!
好处:不同的集群使用不同的网络,保证集群是安全和健康的。
4、网络连通
# 将tomcat01和mynet连通 docker network connect mynet tomcat01 # 连通之后就是将tomcat01 放到了mynet网路下 # 一个容器两个ip地址: # 例如:阿里云服务器,公网ip,私网ip # tomcat01容器去ping我们自己的网络 docker exec -it tomcat01 ping tomcat-net-01
结论:假设我们需要跨网络操作别人,就需要使用 docker network connect 连通!
15、Redis集群部署实战
# 创建网卡 docker network create redis --subnet 172.38.0.0/16 # 通过脚本创建六个redis配置 for port in $(seq 1 6); \ do \ mkdir -p /mydata/redis/node-${port}/conf touch /mydata/redis/node-${port}/conf/redis.conf cat << EOF >/mydata/redis/node-${port}/conf/redis.conf port 6379 bind 0.0.0.0 cluster-enabled yes cluster-config-file nodes.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 # 创建结点1 docker run -p 6371:6379 -p 16371:16379 --name redis-1 \ -v /mydata/redis/node-1/data:/data \ -v /mydata/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 #创建结点2 docker run -p 6372:6379 -p 16372:16379 --name redis-2 \ -v /mydata/redis/node-2/data:/data \ -v /mydata/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 #创建结点3 docker run -p 6373:6379 -p 16373:16379 --name redis-3 \ -v /mydata/redis/node-3/data:/data \ -v /mydata/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 #创建结点4 docker run -p 6374:6379 -p 16374:16379 --name redis-4 \ -v /mydata/redis/node-4/data:/data \ -v /mydata/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 #创建结点5 docker run -p 6375:6379 -p 16375:16379 --name redis-5 \ -v /mydata/redis/node-5/data:/data \ -v /mydata/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 #创建结点6 docker run -p 6376:6379 -p 16376:16379 --name redis-6 \ -v /mydata/redis/node-6/data:/data \ -v /mydata/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 # 创建集群 [root@iZ2zeg4ytp0whqtmxbsqiiZ ~]# docker exec -it redis-1 /bin/sh /data # ls appendonly.aof nodes.conf /data # 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
1、redis集群的搭建
2、停掉主机&获取值
3、查看集群节点信息
16、打包镜像
Springboot微服务打包Docker镜像
-
1、架构springboot项目
-
2、打包应用
-
3、编写DockerFile
-
4、构建镜像
-
5、发布运行
1、打包项目
打开 demo-0.0.1-SNAPSHOT.jar 的文件位置,然后cmd
java -jar demo-0.0.1-SNAPSHOT.jar
下载docker插件
2、编写Dockerfile
FROM java:8 COPY *.jar /app.jar CMD ["--server.port=8080"] EXPOSE 8080 ENTRYPOINT ["java", "-jar", "/app.jar"]
3、构建镜像
4、测试访问
本地测试
使用了Docker之后,给别人交付的就是一个镜像就可以了!!!
外网访问
关闭防火墙
systemctl stop firewalld
开机自动关闭防火墙
systemctl disable firewalld