Docker学习
本文最后更新于:3 年前
B站狂神说docker教程,SpringMVC太干了听不下去,先听会儿这个转换心情。
Docker入门
Docker为啥会出现
开发 —> 上线 , 两套环境!应用环境,应用配置!
问题:我在我都电脑上可以跑哇???
版本更新,导致服务不可用,运维裂开来。
开发即运维。
- 发布一个项目 jar + (Redis MySQL jdk ES) , 环境和项目打包,项目带上环境安装打包
- 传统:
- 传统:开发jar , 运维来做
- 现在:开发打包部署上线,一套流程完成
- Docker为上面问题提供了解决方案嗷!!!
- Docker仓库就类似于镜像,环境和内部打包好了就上线到商店里面,有需要下载下来就可以直接跑的嗷!
- 隔离是docker的核心思想,每个箱子是相互隔离的。
- docker的隔离机制可以充分利用服务器资源,端口冲突的问题也可以通过docker来解决。
- 本质:新的技术的出现都是为了解决问题。
Docker的历史
- 2010年一帮人搞了一个容器化技术,命名为Docker。为了解决类似于VMWare,太重量的东西。
- 2013年Docker开源了,Docker是真的非常好用哦!!!每一个月Docker都会更新一个版本。
- 2014年4月9日,Docker1.0发布。
- 为啥火?容器技术出现之前,使用虚拟机技术。
虚拟机:win10上装一个VMWare,子电脑,可以虚拟电脑,但是太大了笨重。
Docker:容器技术,本质上也是虚拟化技术,但是轻量级。镜像(最核心的环境),十分小巧,运行镜像就可以了。小巧。(几兆,几十兆就可以启动,秒级启动,爽啦。)
- Docker是基于go语言开发的开源项目。
docker的官方文档,这个文档超级详细,力赞。
dockerhub官网,和github是一样的,和github很像,push pull都有。
Docker能干啥
- 虚拟机技术的缺点:
- 资源占用多
- 冗余步骤多
- 启动很慢
- 容器化技术:
- 不是模拟一个完整的容器:
- 容器没有自己的内核,也没有虚拟我们的硬件,所以就轻便了。
- 每个容器相互隔离的,不影响的。
- 应用更加快速的交付和部署。
- 更加便捷的升级和扩缩容量。
- 更加简单的系统运维。
- 更高效的计算资源利用,Docker是内核级别的虚拟化嗷,可以将服务器的性能压榨到极致。
Docker的架构
- 从左到右为服务端,客户端和仓库。
镜像( image ):
- docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,tomcat -> run -> 容器。一个镜像可以创建多个容器。
容器( container ):
- Docker利用容器技术,独立运行一个或者一个组运用,通过镜像来创建。
- 启动,停止,删除,基本命令
- 目前就可以把这个容器理解为一个简易的linux系统
仓库( repository ):
- 仓库就是存放镜像的地方。
- 仓库分为公有仓库和私有仓库。
- Docker Hub 默认是国外的,要配置镜像加速的嗷!
安装Docker:
环境准备:
- Linux基础
- CentOS 7.6
- 使用Xshell连接远程服务器进行操作
- 可以在腾讯云上实操嗷!!!
安装步骤:
查看现在发行的版本:
1 |
|
帮助文档中选择对应的系统进行安装:
- 接着这里的步骤一步步往下走就好了嗷!!!
1 |
|
- 如果要安装指定版本的话,官网有教程哦:
- 当显示下面的内容的时候,docker安装成功:
- 执行docker run hello-world:
- 使用docker version查看docker版本:
- 执行docker run hello-world:
Docker run hello-world:
- 首先Unable to find image , 就是没有找到这个镜像
- 其次就去网上pull hello-world这个东西了。
- 下载完成之后再执行这个镜像,显示执行结果:
1 |
|
- 结果如下:
卸载docker:
卸载Docker Engine,CLI和Containerd软件包:
1
$ sudo yum remove docker-ce docker-ce-cli containerd.io
主机上的映像,容器,卷或自定义配置文件不会自动删除。要删除所有图像,容器和卷:
1
2$ sudo rm -rf /var/lib/docker
$ sudo rm -rf /var/lib/containerd
您必须手动删除所有已编辑的配置文件。
- 官方文档真香啊!!!
配置腾讯云加速:
适用于 Linux 操作系统实例:
执行以下命令,打开配置文件。
1
vim /etc/docker/daemon.json
切换至编辑模式,添加以下内容,并保存。
1
2
3
4
5{
"registry-mirrors": [
"https://mirror.ccs.tencentyun.com"
]
}执行以下命令,重启 Docker 即可。示例命令以 CentOS 7 为例。
1
sudo systemctl restart docker
Hello-World流程:
- 流程分析图:
底层原理:
- 怎么工作的?
- 本质上是一个C/S接口系统,Docker守护进程运行在主机上,通过socket从客户端访问。
- DockerServer接收到Docker-Client的指令,就会执行这个命令。
- 内部结构:
- 后台是一个大的Linux服务器,通过客户端去连接后台的守护进程,Docker容器在我们的范围之内。每一个小的docker容器好比是一个小的Linux虚拟机。容器内有自己的端口号,和外界隔离,外界无法访问,只有守护进程能访问。大小Linux相互隔离,因此外界大Linux要访问小的Linux,需要一些技术将其连通。
- Docker为啥比VM快?
- Docker有更少的抽象层
- Docker利用的是宿主机的内核,vm需要的是Guest OS。
- 新建一个容器的时候,不需要加载虚拟机一样的操作系统内核,避免引导,因此很快。省略了复杂的引导过程。
- 之后学命令就会很快乐,很清晰。
Docker常用命令:
docker version / info / help:
1 |
|
- 官网也可以在帮助文档中的reference找到所有的命令和列表。Docker帮助文档
- 但是官网在国外会比较慢,所以我们这里直接使用命令进行查找用法即可。
常用镜像命令:
docker images:
[root@VM-12-10-centos ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest d1165f221234 2 months ago 13.3kB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
- Repository:镜像的仓库源
- Tag:镜像的标签
- Image ID:镜像的id
- Created:镜像的创建时间
- Size:镜像的大小
- 可选项:
- -a , 列出所有镜像
- -q , 只显示id
#### docker search:
- shell中所搜镜像源头
- ```shell
[root@VM-12-10-centos ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 10903 [OK]
mariadb MariaDB Server is a high performing open sou… 4115 [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Create… 809 [OK]可选项:
–filter , 过滤器,过滤出符合条件的内容。例如
--filter=STARS=3000
,就只会显示STARS中3000以上的内容。[root@VM-12-10-centos ~]# docker search mysql --filter=STARS=3000 NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 10903 [OK] mariadb MariaDB Server is a high performing open sou… 4115 [OK]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#### docker pull:
![image-20210522180106175](https://cdn.jsdelivr.net/gh/alexanderliu-creator/cloudimg/20210522180106.png)
- 下载镜像采用分层的方式
- Digest是一个签名
- 最后是一个下载的真实地址
下面两条是等价的,你这里pull mysql实际上就是从下面这个地址去pull
- 指定版本:
- 需要是系统支持的版本,在docker hub中可以看到有哪些版本的。
- `docker pull mysql:5.7`
- 分层下载:
- 多个文件有共享的内容就不用分层进行下载了,直接可以共用哦。
#### docker rmi:
- 可以通过id或者是name来删除。
- 删除过程中也是按照层来删!!!
- `docker rmi -f name/id`,删除指定容器
- `docker rmi -f 容器id 容器id 容器id`,删除多个容器
- 这里-f表示的是强制删除的参数嗷!!!
```shell
[root@VM-12-10-centos ~]# docker rmi -f d1165f221234
Untagged: hello-world:latest
Untagged: hello-world@sha256:5122f6204b6a3596e048758cabba3c46b1c937a46b5be6225b835d091b90e46c
Deleted: sha256:d1165f2212346b2bab48cb01c1e39ee8ad1be46b87873d9ca7a4e434980a7726
批量删除(用到了linux中的技巧哦):
docker rmi -f $(docker images -aq)
,这样可以删除所有镜像。
常用容器命令:
- 有了镜像才可以创建容器,linux,下载一个centos镜像来测试学习:
1 |
|
docker run:
docker run [可选参数] image
参数说明:
- –name=”Name” 容器名字用来区分名字
- -d 后台方式运行
- -it 使用交互方式运行,进入容器查看内容
- -p 指定容器端口:
- 主机端口映射到容器端口(最常使用)
- 直接容器端口
- ip:主机端口:容器端口
- -P 随机指定端口
实际进入容器的例子:
1 |
|
- 启动并进入容器,主机名称变了兄弟,现在进入到我们的容器里面去了,容器里面和外面是两个世界。里面是一个非常非常轻量的服务器,甚至指令都不完善的。
- 从容器中退回主机:exit可以退出进入的容器。
docker ps:
- 显示正在运行的程序
- 参数大全:
- -a , 显示历史运过的容器:
1 |
|
- -n=? 显示最近创建的容器,可以给个数。
- -q 只显示容器的编号
1 |
|
- 上面这个例子可以显示全部容器的编号
退出容器:
- exit,停止并退出容器
- Ctrl + P + Q , 容器不停止同时退出容器
docker rm:
- 删除容器
docker rm 容器id
docker rm -f $(docker ps -aq)
,删除所有的容器- 运行中的容器不能够删除,如果要强制删除的话要
rm -f
docker ps -a -q|xargs docker rm
,这个也可以删除所有容器。
启动和停止容器的操作:
1 |
|
常用其他命令:
docker run -d 容器名
- 通过
docker run -d 镜像名
来后台跑起来一个容器 - 但是你发现启动完成之后,docker ps -a看不到???它自动停掉了。
- reason:
- docker是容器使用后台运行,必须要有一个前台进程,docker发现没有前台提供服务的应用,就会自动停止。
- 容器启动后,发现自己没有提供服务,就会立即停止,没有程序了。
docker logs
- 参数:
- -f:format,标准化输出。
- -t:显示时间戳。
- 还有好多…
1 |
|
- 上面这个可以显示容器内的日志,但有可能容器啥都没干,就无日志
查看进程信息
- docker top 容器id
- 会显示出容器中所有进程的id
查看镜像元数据
- docker inspect 容器id
1 |
|
- docker inspect 容器id/镜像id都可以看嗷!!!
进入正在运行的容器
1 |
|
- 区别:
- exec,进入容器后开启一个新的终端。
- attach,不会启动新的进程,直接进入正在执行的终端。
从容器内拷贝文件到主机
- 要进入容器内再拷贝出来
docker cp 容器id:/文件夹/文件 /宿主机内文件夹/文件
- 拷贝是一个手动过程,未来使用 -v 卷的技术,可以实现自动拷贝。
小结:
小作业1(部署Nginx):
Docker安装nginx
1 |
|
1 |
|
- 上面完成了nginx的下载与部署,下面进行访问测试:
1 |
|
- 端口暴露的概念图:
- 可以进入nginx容器中查看nginx相关的信息:
1 |
|
- 由于你将本机端口和容器内部端口进行了映射,访问本机端口就可以获得服务,这个时候在服务器配置中开放端口就可以访问到你在对应端口开放的服务。
- 思考问题:每次改动配置文件都需要进入容器内部十分麻烦。我们要是可以在容器外部提供映射路径,达到在容器外的修改可以同步到容器内,就十分的方便嗷!!!-v 数据卷的技术。
小作业2(部署Tomcat):
- 官方文档中提供的安装Tomcat的命令
1 |
|
我们发现容器跑起来和在Tomcat部署上的一摸一样,这个时候
ctrl+c
停掉Tomcat服务,docker ps -a
显示一下容器我们发现它就没有了!!!我们这儿不这么跑哈,不太好嗷!!!直接pull , run 起来好一点嗷!!!
docker pull tomcat
docker run -d -p 3344:8080 --name tomcat01 tomcat
本地的curl命令和远程访问3344端口都没问题:
可以看到Apache服务器已经部署成功了!!!
- 进入容器进行查看:
1 |
|
- 发现问题:
- 命令被阉割了,类似于ll这样的命令都没有了
- webapps底下啥都没有,原因是默认是最小的镜像,所有不必要的就都剔除掉,保证最小可运行的环境。
- 实际文件藏在webapps.dist文件里面,就是基本的页面,把其复制到webapps中就可以正常跑起来啦!!!
1 |
|
这个时候无论是本地curl还是远程:3344,都能够访问到apache的初始页面了嗷!!!
思考问题:我们以后部署项目,每次进入容器是不是很麻烦?我要是可以提供一个映射路径:webapps,我们在外部放置项目,就自动同步到内部就好了。
小作业3(部署ES+Kibana):
- 比较耗费资源和内存,我这儿不用自己的虚拟机做演示了嗷!!!老师部署的都裂开来!!!
- elasticsearch就是我们要下载部署的东西嗷!!!
- 部署了服务器都顶不住,直接卡住了,一核2G根本顶不住。解决方法:
- 停整个docker
- 服务器直接重启orz
- 等服务器缓过来
- 查看状态:
docker stats
,这是一个比较耗资源的操作嗷:
- 增加内存的限制才可以嗷!!!
- 这里的是-Xms , -Xmx限制的是最大和最小内存。
- 它的前面的这部分代码上dockerhub去看官网文档的用法嗷!!!
- 作业:如何使用Kibana去连接ES呢?两者是相互隔离的,就非常顶???解决:通过Linux的内网地址,以Linux为中介,去连接ES。
可视化工具:
portainer(先用这个):
- docker的图形化管理工具,提供一个后台面板供我们操作
- 操作指令:
1 |
|
- 然后访问3344端口就能够访问到:
- 创建用户之后使用本地的就好啦,很方便嗷!
进入后,可以看到我们的主面板:
- 可视化面板,挺好用的,就是一般不会用orz。
Rancher(CI/CD再用)
Docker镜像
镜像是什么
- 所有的引用直接打包为docker镜像,就可以直接跑起来
- 得到镜像:
- 远程仓库下载
- 朋友拷贝给你
- 自己制作一个镜像dockerfile
镜像加载原理(层级的概念)
Union File System
,联合文件系统,是一种分层,轻量级并且高性能的文件系统,它支持对于文件系统的修改作为一次提交来一层层叠加。同时可以把不同目录挂载到同一个虚拟文件系统下。镜像可以通过分层来进行集成,基于基础镜像,可以制作各种具体的应用镜像。- 精简的OS,所以可以很小,底层使用的是Host的kernel,因此为秒级启动。
- 有点像windows里面的更新补丁,盖中盖。
- 分层下载可以复用相同的层。这里注意一下,下面这个很重要,我们不可以写只读的镜像,我们只可以操作启动的容器,相当于在镜像上面多加了一层容器层进行操作,新的这一整个整体可以被打包为一个全新的镜像嗷!!!
commit镜像
docker commit -m="提交的信息" -a="作者" 容器id 目标镜像名: [TAG]
命令和git类似
实战测试:
- 启动一个默认的Tomcat
- 没有webapps应用,官方默认webapps里面是没有东西的
- 我自己向webapps里面拷贝了webapps.disk里面的全部文件。
- 这个时候提交一下我们修改的内容打包成一个镜像嗷!!!
docker commit -a="tuzi" -m="add webapps app" 7e119b82cff6 tomcat02:1.0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
- 这个时候就从容器创建了一个镜像,docker images是可以看到你这里生成的镜像的嗷!!!我们以后就可以使用我们自己修改过的镜像。这个就相当于我们学习过的概念snapshot。
- 先理解概念,然后概念和实践相互集合一把拿下。以后项目开发就可以通过commit不断向已有的镜像中添加新的容器层再打包为新的镜像。
# Docker精通
## Docker数据卷
### 什么是容器数据卷
- 将应用和环境打包为一个镜像。
- 数据?如果数据都在容器中,我们删除容器数据就会丢失。**需求:数据持久化**。
- MySQL之类的数据在容器中是不安全的,需要数据共享,将容器中的数据可以导出来保存嗷!!!
- 容器之间可以有一个数据共享的技术!Docker容器中产生的数据同步到本地!!!
- 卷技术,本质上是目录的挂载,将容器内的目录挂载在Linux上。
![image-20210524095038844](https://cdn.jsdelivr.net/gh/alexanderliu-creator/cloudimg/20210524095046.png)
容器中的数据自动同步到Linux文件夹上。
- 总结一句话:
- 容器的持久化和同步操作
- 容器间也是可以数据共享的
### 使用数据卷
> 方式一:使用命令来挂载
- 命令格式:
`docker run -it -v 主机目录:容器内目录`
这个和上面学的-p也很类似哦,-p是端口映射,-v是目录映射。挂在完成之后,以后容器内目录中的内容都会自动和主机目录的内容同步嗷!!!
- 为了查看挂载是否成功,可以使用docker inspect 容器id来查看容器状态,里面有个属性说明了挂载的内容的状态:
![image-20210524095842507](https://cdn.jsdelivr.net/gh/alexanderliu-creator/cloudimg/20210524095842.png)
- 可以理解为双向绑定???? ---> 对,就是这么理解的
- 好处:
- 修改只需要在本地修改即可,不需要进入容器中修改
### 实战:安装MySQL
- MySQL数据持久化的问题
- 注意:MySQL配置的时候需要账号和密码嗷!!!具体怎么设置的话,可以上官网去康康嗷!!!
![image-20210524102556491](https://cdn.jsdelivr.net/gh/alexanderliu-creator/cloudimg/20210524102603.png)
- 启动成功之后,可以通过你云服务器主机的ip和密码访问到远程的mysql,就和你本地的Database建立连接没啥区别。IDEA里面的Database就提供了这样的连接功能,VSCode也有嗷!!!
- 本地测试一个新的数据库,映射路径都是ok的嗷!!!
- 就算删掉MySQL容器的话,挂载到本地的数据卷中的数据还在哈!!!
### 具名挂载和匿名挂载
- docker volume:
```shell
[root@VM-12-10-centos ~]# docker volume --help
Usage: docker volume COMMAND
Manage volumes
Commands:
create Create a volume
inspect Display detailed information on one or more volumes
ls List volumes
prune Remove all unused local volumes
rm Remove one or more volumes
Run 'docker volume COMMAND --help' for more information on a command.
这个volume就是我们所说的卷 -v 的来源
查看所有卷的情况:
- docker volume ls
匿名挂载:
- -v的时候,只指定了指定容器里内目录,不指定容器外目录。
docker run -d -P --name nginx02 -v /etc/nginx nginx
具名挂载:
-v的时候,没有给路径,只给了个名字
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
卷名:容器内路径
docker volume ls,是可以看到这个名字的相关信息的嗷!!!
Summary:
- 所有docker内的卷,没有指定目录的情况下,都是在
/var/lib/docker/volumes/xxxx/_data
下的。 - 这个xxxx如果是匿名挂载就是一个id,如果是具名挂载就是你的命名。
- 具名挂载是最常用的,可以方便找到我们的一个卷,大多情况在使用具名挂载。
- 如何确定是具名挂载还是匿名挂载,还是指定路径挂载?
- -v 容器内路径
- -v 卷名:容器内路径
- -v 宿主机路径:容器内路径
- 同时甚至可以设置权限:
- 注意哈,权限是对于容器中的内容来说的,例如ro说明这个路径只能通过宿主机来操作,容器内是无法操作的嗷!!!
初识DockerFile
采用Dockerfile进行挂载:
- commit是通过容器生成镜像,如果我想自己从头生成一个镜像呢???
- DockerFile就是用来构造docker镜像的构建文件,命令脚本。镜像是一层一层的,脚本就是一个一个的命令。
1 |
|
- 上面这里是个例子,第一行指定环境,第二行指定挂载的卷,就是其实就是匿名指定嗷!!!这里只说明了容器内的名字嘛!!!
docker build -f /home/tuzi/dockerfile1 -t tuzi/centos:1.0 .
- 上面这里-f是指文件的位置,-t指的是target,也就是生成的目标位置,最后的.表示当前目录下。
- 注意这里的名字前面不能有/哈,dockerfile文件名字最好为Dockerfile。文件中的内容,指令大写嗷。
- 这里的每个命令是镜像的一层!!!
- 这种方式使用的非常多!!!一般都构建自己的镜像,如果没有的话就需要我们手动镜像挂载!!!
数据卷容器:
多个MySQL数据同步:
- 下面这个就是一个例子:
- 甚至可以多个容器之间采用同样的方式进行挂载。只要通过这种方式就能够实现容器之间的数据共享。
- 删除了其中一个容器,其他的容器还使用着卷,这其他卷中的数据是不会丢失的嗷!!!
- 结论:容器之间,可以配置信息的传递。容器卷的生命周期一致持续到没有容器使用为止。一旦持久化到了本地,本地的数据就是持久化的,不会随着容器被删除完而消失嗷!!!
Dockerfile介绍:
构建步骤:
- 构建dockerfile 文件
- docker build 构建一个镜像
- docker run 运行镜像
- docker push 发布镜像(DockerHub , 阿里云镜像仓库)
很多官方镜像都是基础包,很多功能没有,我们通常需要自己来配置我们的环境!!!
基础知识:
- 每个保留关键字必须是大写字母
- 执行从上往下执行
- # 表示注释
- 每一个指令都会提交一个新的镜像层,并且提交。
整体结构:
- 面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单。镜像就是我们要最终发布和运行的产品。
- Docker容器就是镜像运行起来提供服务的嗷!!!
Dockerfile指令说明:
FROM
- 基础镜像,一切从这里开始
MAINTAINER
- 镜像是谁写的,姓名+邮箱
RUN
- 镜像构建的时候运行的命令
ADD
- 步骤:添加Tomcat镜像:
- Centos有了,Tomcat呢?
- 加入Tomcat包才能用哇!!!
WORKDIR
- 镜像的工作目录,指定工作的目录
VOLUME
- 挂载的目录
EXPOSE
- 暴露端口,端口配置
CMD
指定容器启动的时候要运行的命令
只有最后一个会生效,可被替代
ENTRYPOINT
- 指定容器启动的时候要运行的命令
- 可以追加命令
ONBUILD
- 构建一个被继承的时候,Dockerfile会运行ONBUILD指令,触发指令。
COPY
- 类似于add,将我们的文件拷贝到镜像中
ENV
- 构建的时候设置环境变量
实战测试:
- 非常基础的镜像:scratch , 连CentOS系统都是由它构建的嗷!!!Docker Hub中99%的镜像都是由这个镜像过来的。
创建一个自己的CentOS
- 由于原来的镜像中很多指令类似于pwd , vim都没有,我们创建一个有这些东西的镜像。
- 编写配置文件:
1 |
|
- 构建镜像:
1 |
|
注意build最后有个点哈!!!有的它就直接使用,没有的它就去下载。
验证过后发现,vim , ifconfig , pwd都是设置正确的嗷!
解锁新指令:docker history imageID:
1
2
3
4
5
6
7
8
9
10
11
12
13
14[root@VM-12-10-centos dockerfile]# docker history 8eb39247efa4
IMAGE CREATED CREATED BY SIZE COMMENT
8eb39247efa4 6 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
095dbd389dcc 6 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
e990f552ebff 6 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
24a3cf5703dd 6 minutes ago /bin/sh -c #(nop) EXPOSE 3344 0B
5aa957293560 6 minutes ago /bin/sh -c yum -y install net-tools 23.3MB
77e4b03443f6 6 minutes ago /bin/sh -c yum -y install vim 58MB
aeb1cad8b76e 7 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B
a93da34898df 7 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B
b7b887b8d1d9 7 minutes ago /bin/sh -c #(nop) MAINTAINER tuzi<263274647… 0B
300e315adb2f 5 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 5 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 5 months ago /bin/sh -c #(nop) ADD file:bd7a2aed6ede423b7… 209MB- 通过history可以看看镜像是怎么做出来的嗷!!!
CMD和ENTRYPOINT的区别:
- CMD可以执行多个的嗷:
CMD ["ls","-a"]
在你run的时候,只有最后一个cmd指令生效
CMD中,如果你想用
docker run test -l
这种形式的话,-l会替换掉上面的ls -a,指令出错,无法拼接在指令后面orz。ENTRYPOINT则可以让它在我们编写的内容后面添加。
ENTRYPOINT ["ls","-a"]
这个时候如果你要和上面一样跑起来,这个指令则添加到我们的ENTRYPOINT后面,变为ls -al,这就是这两者的区别。
DOCKERFILE中很多相似的命令,最好的方法就是去实践并且对比结果。
实例:Tomcat镜像
这个我没有实操嗷,因为我这儿没有Tomcat和JDK的压缩包,这儿就没有再去下载完成这个任务!!!
步骤:
- 准备镜像文件tomcat压缩包,jdk压缩包
- 编写dockerfile压缩包(官方命名为Dockerfile,如果是这个名字的话-f就可以不需要这个参数,会默认去寻找这个名字的文件来进行build)。
注意哈,在dockerfile里面使用add添加文件后,如果它的压缩包,docker会自动帮你解压嗷!!!
注意最后那个.哈,比如你要add导入一些文件,你可以先切到对应的文件目录之下,然后直接用文件名导入即可。这样做非常简单,最后的 . 其实就指定了在当前目录下去寻找文件。
1 |
|
- 创建镜像:
docker build -t diytomcat .
- dockerfile文件的名字为标准的Dockerfile的话,-f就不用自己设置了,系统会导入的嗷!!!
- docker run的时候如果没有指定版本的话,用的就是默认版本,也就是最新版,因此这里要注意一下嗷!!!
- 启动镜像:
进行一些挂载,例如发布的时候的目录挂载到Linux虚拟机中嗷!!!
- 例如上面这个,将这个容器的webapps挂载到了本地的test目录,将日志目录也挂载到了本地。这里我们。
测试访问
发布项目(由于我们做了挂载,可以直接对于本地的文件进行修改就可以实现发布)
例如webapps/test挂载到了本地的目录,那么我们就可以去test里面新建WEB-INF啊,新建web.xml啊,新建index.jsp啊之类的,都可以新建的。然后访问对应端口
- 以后的项目都是这个流程嗷!!!
发布镜像:
发布到docker hub:
先去DockerHub的注册一个账号
服务器上提交自己的镜像
docker push 账户名(liututu)/镜像名(diytomcat:1.0)
docker login:
- 登录远程的dockerhub
- 登录完毕之后就可以提交镜像了。
- 登录之后就可以docker push了。
docker login -u liututu
- 然后输入密码即可以登录
docker tag:
- 用于添加标签
docker tag 镜像id tag的名字和版本号
- e.g.
docker tag xxx tuzi/tomcat:1.0
发布到腾讯云:
- 有点麻烦,暂不考虑
Docker全流程小结:
- 流程图如下:
docker save:
- 可以使用–help去看使用方法很简单的嗷
- -o 参数,用于指定输出路径
docker load:
- 可以使用–help去看使用方法很简单的嗷
- - i参数,用于指定输入读取的路径
Docker网络
理解网络
ip addr:
- docker中的网络是docker0
- docker中先清空,比较方便,rmi and rm
三个网络,有点乱嗷!!!
查看容器内部网络地址,就是上面那幅图:ip addr。
docker exec -it tomcat01 ip addr
可以使用命令连接直接查看ip addr。下面这幅图你可以看到,Linux宿主机是可以Ping通docker容器的。
原理:
- 每启动一个docker容器,docker就会为容器分配一个ip。
- 只要安装了docker,就会有一个docker网卡。这个网卡使用的是evth-pair桥接模式。
- 多启动了一个容器之后,在宿主机内使用ip addr可以看到多了一个网卡!!!
- 容器带来的网卡是一对儿的,容器里面有一个,宿主机外面有一个,这两个网卡是相互绑定可以通信的。这样一对儿一对儿网卡存在的技术就叫做evth-pair技术。一端连着协议,一端彼此相连,他们之间就可以通信。
- 因此我们经常使用evth-pair来充当一个桥梁,连接各种网络设备的。
- OpenStac , Docker容器之间的连接,OVS的连接,都是使用 evth-pair技术。
- 容器和容器之间也是可以相互ping通的嗷!!!
- 网络通信流程图:
结论:Tomcat01和Tomcat02共用一个路由器 , docker0
- 在所有容器不指定网络的情况下,默认使用的都是docker0,docker会给我们容器分配一个默认的可用ip
小结:
Docker使用的Linux中的桥接模式嗷!!!
概念图,宿主机中式一个Docker容器的网桥:
- Docker中的所有的网络接口都是虚拟的,虚拟的转发效率高!!!
- 只要容器删除了,容器的一堆网卡就都没了。
- 思考场景
思考一个场景,我们编写了一个微服务,database url = ip; 项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以使用名字来访问容器。
docker link:
- 用名字取ping , 容器之间ping不通:
- 解决问题的样式:
- 3 ping 2可以ping通,2 ping 3通不了,因为你只对于3做了配置
docker network ls:
docker network inspect 容器id:
- 查看容器的网络连接情况。
- 其实tomcat03是配置了tomcat02
看看配置:
- 这里进入了tomcat03中的host配置文件,查看到了tomcat03关于tomcat02的网络配置。
- 原理:
- 在启动容器的时候,对于tomcat02进行了一个绑定,其实就算不绑定,用容器id也能够ping通。
- 未进行配置的tomcat02配置文件中的内容:
真实玩docker的时候,使用自定义的网络,就很方便嗷!!!不适用docker0嗷!!!
docker0的问题:
- 不支持容器名访问嗷!!!
自定义yyds!!!
自定义网络
- 容器互联作用
移除网络:
- docker network ls可以显示所有的网络
- docker network rm 网络id , 可以移除一个或多个网络
- docker network rm $(docker network ls -q)这样就可以递归删除所有网络嗷!!!
网络模式:
- bridge:在docker上面搭桥。(默认,自己创建也是使用桥接模式的嗷!!!)
- none:不配置网络
- host:和宿主机共享网络
- container:容器内网络联通(用的少,局限很大)
1 |
|
- 上面这三个是docker为我们默认配置好的三个嗷!!!
使用create创建网络:
- 我们直接启动镜像的命令,实际上是默认有个:
--net bridge
参数的,这里实际上就指定了使用docker默认为我们提供的docker0桥接模式也就是我们上面这一段代码中的第一个也就是名字为bridge的这个网络。 - docker0默认名字不能访问 ,可以使用link进行打通,但是比较麻烦嗷!!!
- 可以调用帮助文档:
docker network create --help
- 创建一个网络:
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
- 上面这个相当于新建了一个router
- 我们创建了网络之后进行查看:
1 |
|
- 这个时候启动容器的时候,就可以加上参数:
--net mynet
,这样就完成了router
的指定。 - 当创建了新的容器之后,我们再执行这个inspect mynet的命令,就可以看到我们上面这一坨里面的多了容器!!!为了验证容器间可以进行交互,我们这里创建了tomcat01和tomcat02,作为示例:
1 |
|
- 上面就可以看到我们的两个容器嗷!!!自创建的网络非常完善,带了很多的功能嗷!!!不管是ping id还是ping name都能够ping通嗷!!!
1 |
|
- 不适用–link也可以ping名字,我们自定义的网络,docker都已经帮我们维护好了对应的关系。
网络联通:
- 不同的网段是ping不通的嗷!!!
docker network connect NETWORK CONTAINER
- 上面用于不同的网段之间的连接,联通就是将tomcat容器放到了mynet网络下。官方叫做:一个容器,两个ip地址。(一个公网ip , 一个私网ip)。
- 网卡和网卡之间正常是不能打通的,但是容器和网卡之间可以嗷!!!
- 只有01和mynet打通了,可以和它交互,但是02不可以嗷!!!!
实战(部署redis集群):
- 分片+高可用+负载均衡
- 这一块儿可以后面再看嗷!!!
- 目前还没学redis,以及集群还没学,这个狂神的课程还有进阶版本的docker,目前这个教程就到这里嗷!!!
小技巧
Docker开机后跑不了的问题
- 由于docker默认没有开启开机自动重启,这个时候你的虚拟机重新开机就会导致docker用不了,如何解决?那就再开启一次docker服务就好了哇!!!
systemctl restart docker.service
Docker映射端口在服务器打开
- 此外,比如你想开放3344端口,你需要去腾讯云服务器配置的那个位置配置新的安全组:
- 配置完成之后可能需要重启实例才能使得服务生效嗷!!!
博客的nginx重启之后记得开
systemctl start nginx.service
- Nginx服务器解决方案
远程访问的问题:
- 比如我开放了3344端口,直接通过域名:3344是能够访问到我监听3344端口的程序的。
- 突然让我想起了blog的搭建。我搭建blog的时候,使用nginx监听的是80端口。浏览器访问我的域名的话,默认访问的就是80端口,因此我的nginx能够为其提供服务。
- 域名:端口号就可以根据你自己的喜好,访问到部署在不同端口的应用程序。
/bin/bash
- 一般和-it这个选项用来一起使用的嗷,这里是指定交互的终端为bash,不然你怎么和内部容器进行交互嘛!!!