Docker
前景
为什么需要Docker
- 一个技术的产生,必然有它的因果!
- 一款产品从开发到上线,从操作系统,到运行环境,再到应用配置。
作为开发 运维之间的协作我们需要关心很多东西
这是很多互联网公司,不得不面对的问题! 特别是各个迭代之后,不同版本的环境兼容性是对运维人员不小的考验!
- 在传统开发中,我们通常都会遇到这种场景: 我们开发项目的时候,会有两套环境,开发环境和上线环境 同一段代码在,我们开发人员的电脑里面项目运行的好好的,跑到运维人员那里就不行了 这个就是环境不同造成的原因
这时候Docker
出现了并解决了此问题!
- 环境配置如此麻烦,换一台机器,就要重来一次,费力费时。 很多人想到,能不能从根本上解决问题:
- 软件可以带环境安装?
也就是说,安装的时候,把原始环境一模一样地复制过来.
开发人员利用 Docker 可以消除协作编码时
在我的机器上可正常工作
的问题。
Docker 介绍:
- Docker 是一个开源的应用容器引擎,
基于
Go语言,并遵从
Apache2.0 协议开源。 - Docker的主要目标是
Build,Ship and Run Any App, Anywhere (在任何地方构建、发布和运行任何应用程序)
一次封装,到处运行! - Docker 技术,从
Linux容器技术
上衍生出来, 将应用即环境,封装成镜像,生成Docker容器, 运行在 Docker上面。 - 而Docker 容器在任何操作系统上都是一致的,这就实现了跨平台、跨服务器。 (就向Java虚拟机一样!) 只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化了操作,解决了运行环境和配置问题软件容器
虚拟机技术:
虚拟机(virtual machine)就是 带环境安装
的一种解决方案。
- 它可以在一种操作系统里面运行另一种操作系统 比如在Windows 系统里面运行Linux 系统。
- 应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样 而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。
- 虚拟机看上去跟真实系统一模一样, 这类虚拟机完美的运行了另一套系统,能够使应用程序,操作系统和硬件三者之间的逻辑不变。
虚拟机的缺点:
- 1 资源占用多
- 2 冗余步骤多
- 3 启动慢
Linux容器技术:
Linux 容器不是模拟一个完整的操作系统 而是对进程进行隔离
- 通过容器,将软件运行所需的所有资源打包到一个隔离的容器中。
- 容器与虚拟机不同,不需要捆绑一整套操作系统,
只需要软件工作所需的库资源和设置。
- 系统因此而变得高效轻量并保证部署在任何环境中的软件都能始终如一地运行。
容器技术 和 传统虚拟机 的不同之处
传统虚拟机技术是虚拟出一套硬件后
- 在其上运行一个完整操作系统,在该系统上再运行所需应用进程;
容器技术
- 容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核
因此容器要比传统虚拟机更为轻便。
- 每个容器之间互相隔离,每个容器有自己的文件系统 容器之间进程不会相互影响,能区分计算资源。
Docker工作原理:
Client 客户端:
- Docker 是一个客户端-服务器(C/S)架构程序
- Docker 客户端只需要向 Docker 服务器/守护进程
Docker daemon
发出请求,服务器/守护进程将完成所有工作并返回结果。 - Docker 提供了一个命令行工具 Docker 以及一整套 RESTful API。
Docker host主机引擎:
- 一个物理或者虚拟的机器用于执行 Docker 守护进程和容器
- 在Windows 或 linux 操作系统上安装 Docker服务…
Docker 本质上也可以理解为一个 虚拟机运行者很多程序 (容器)...
image 镜像
- docker镜像就好比是一个目标,可以通过这个目标来创建容器服务
tomcat镜像==>run==>容器(提供服务器)
通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)
Container 容器
- Docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建的
- 目前就可以把这个容器理解为就是一个简易的
操作系统
运行环境
Registry
- Registry:在Docker中称为镜像仓库,Docker的镜像仓库有点类似与yum源仓库
为什么Docker比较比VM快
- Docker有着比虚拟机更少的抽象层,由于Docker不需要Hypervisor实现硬件资源虚拟化 运行在Docker容器上的程序直接使用的都是实际物理机的硬件资源,因此在Cpu、内存利用率上Docker将会在效率上有明显优势。
- Docker利用的是宿主机的内核,而不需要Guest OS 因此,当新建一个容器时,Docker不需要和虚拟机一样重新加载一个操作系统
Docker容器 | 虚拟机(VM) | |
---|---|---|
操作系统 | 与宿主机共享OS | 宿主机OS上运行宿主机OS |
存储大小 | 镜像小,便于存储与传输 | 镜像庞大(vmdk等) |
运行性能 | 几乎无额外性能损失 | 操作系统额外的cpu、内存消耗 |
移植性 | 轻便、灵活、适用于Linux | 笨重、与虚拟化技术耦合度高 |
硬件亲和性 | 面向软件开发者 | 面向硬件运维者 |
GuestOS和HostOS是什么?
- GuestOS
VM(虚拟机)里的的系统(OS)
- HostOS
物理机里的系统(OS)
Docker安装
- 本人是Linux 版本的安装…
以下命令一一执行即可!
参考官方:https://docs.docker.com/engine/install/centos/ 1) 卸载旧版本(如果以前安装过旧版本可以先卸载)
代码语言:javascript复制yum remove docker
docker-client
docker-client-latest
docker-common
docker-latest
docker-latest-logrotate
docker-logrotate
docker-engine
2) 安装docker工具
代码语言:javascript复制yum install -y yum-utils
3) 设置镜像仓库
代码语言:javascript复制#官方默认的镜像仓库地址
yum-config-manager
--add-repo
https://download.docker.com/linux/centos/docker-ce.repo #默认是国外的非常慢!
#改为阿里云的镜像仓库地址
yum-config-manager
--add-repo
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
4) 安装docker引擎
代码语言:javascript复制yum install docker-ce docker-ce-cli containerd.io
5) 启动docker服务
代码语言:javascript复制#启动服务
systemctl start docker
#检查版本
docker version
6) 测试helloworld(helloworld可选)
代码语言:javascript复制docker run hello-world
7) 卸载docker引擎
代码语言:javascript复制#卸载
yum remove docker-ce docker-ce-cli containerd.io
#删除目录
rm -rf /var/lib/docker
配置阿里云镜像加速
- 阿里云
- 选择对应的操作系统,逐行执行下面配置命令即可!
Docker基本命令
官方帮助:https://docs.docker.com/engine/reference/commandline/cli/
管理命令
代码语言:javascript复制#查看版本
docker version
#查看信息
docker info
#查询某个命令的相关帮助
docker xxx --help #这个命令特别实用只要有什么不懂的就可以执行这个命令来,了解参数并使用!
注意:
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
- ///var/run/ Docker .sock. error:是否正在运行docker守护进程? 执行Docker 指令确保服务开启!
镜像相关命令
查看镜像
docker images --help
查看所有镜像的帮助文档!
[root@hadoop1 ~]# docker images --help
Usage: docker images [OPTIONS] [REPOSITORY[:TAG]]
List images
Options:
-a, --all Show all images (default hides intermediate images) #显示所有镜像(默认隐藏中间图像)
--digests Show digests #显示摘要
-f, --filter filter Filter output based on conditions provided #根据提供的条件过滤输出
--format string Pretty-print images using a Go template #漂亮的打印镜像使用一个Go模板
--no-trunc Don't truncate output #不截断输出
-q, --quiet Only show image IDs #只显示图像id
[root@hadoop1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test2_kafkademo latest ed4ebc0ed41c 5 months ago 672MB
app 1.0 02094c567c02 5 months ago 672MB
tomcat 8.5 d5ef56581444 7 months ago 530MB
wurstmeister/kafka latest 40094a582680 8 months ago 435MB
centos 7 7e6257c9f8d8 8 months ago 203MB
logstash 7.6.2 fa5b3b1e9757 12 months ago 813MB
kibana 7.6.2 f70986bc5191 12 months ago 1.01GB
elasticsearch 7.6.2 f29a1ee41030 12 months ago 791MB
wurstmeister/zookeeper latest 3f43f72cb283 2 years ago 510MB
java 8 d23bdf5b1b1b 4 years ago 643MB
REPOSITORY(镜像名) TAG(版本) IMAGE ID(镜像id) CREATED(创建时间) SIZE(大小)
因为是老外,开发的帮助文档都是英文的,可以下载一个 翻译工具(这个也算是开发者必备工具了..)
实在不行就百度, 下面不会一一介绍的了!
也可从官方镜像仓库搜索:http://hub.docker.com/
代码语言:javascript复制docker images #列出本地主机上的镜像
docker images -a #列出本地所有的镜像(含中间映像层)
#-q只显示镜像ID
#--digests :显示镜像的摘要信息
#--no-trunc :显示完整的镜像信息
搜索镜像
代码语言:javascript复制docker search 镜像名
拉取镜像(下载)
- 默认下载的是最新版本的镜像
#默认下载的是最新版本的镜像
docker pull tomcat
#也可以指定版本下载(需要去hub.docker.com搜索版本信息)
docker pull tomcat:8.5
删除镜像
删除指定镜像
代码语言:javascript复制[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat 8.5 34aaa1851899 4 days ago 530MB
tomcat latest 5f47aad0b70e 4 days ago 647MB
hello-world latest bf756fb1ae65 8 months ago 13.3kB
#可根据镜像id或名称删除,也可以在后面用空格分隔一次删除多个镜像
[root@localhost ~]# docker rmi 5f47aad0b70e
Untagged: tomcat:latest
Untagged: tomcat@sha256:c2b033c9cee06d6a3eb5a4d082935bbb8afee7478e97dcd6bc452bb6ab28da4b
Deleted: sha256:5f47aad0b70e1d6a8324543d3b7536f23baaaf09b09661dbf4e52d7b822c0157
Deleted: sha256:34ccbdf0c4b338bbe26a4c349d517fb7662b65611bd02c35f72358838aeac6b1
Deleted: sha256:5bc61859d971832370605e0fb8d1fe41e0550e3841043de1c19d971691efd4c4
Deleted: sha256:a6f52ba4967c48d8aba223ff71a9764d2dacd53490af3d1e73da96cc66f3e05b
Deleted: sha256:b0cb8e4a85df51db4e5fe10dfa149b2b3f1170c7a3a8d33b0c5ef6e104b9a980
Deleted: sha256:6a05ecc17b6c6bc8a97223bf4a04aa5ad34084270d86ca0605bf5a603e1656f4
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat 8.5 34aaa1851899 4 days ago 530MB
hello-world latest bf756fb1ae65 8 months ago 13.3kB
删除所有镜像
代码语言:javascript复制#删除所有镜像
docker rmi $(docker images -qa)
场景再现 已生成容器的镜像无法删除,需要先删除容器,或者用 -f 强制删除
代码语言:javascript复制[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 8 months ago 13.3kB
[root@localhost ~]# docker rmi bf756fb1ae65
Error response from daemon: conflict: unable to delete bf756fb1ae65 (must be forced) - image is being used by stopped container 764b1fdde2be
[root@localhost ~]# docker rmi -f bf756fb1ae65
Untagged: hello-world:latest
Untagged: hello-world@sha256:4cf9c47f86df71d48364001ede3a4fcd85ae80ce02ebad74156906caff5378bc
Deleted: sha256:bf756fb1ae65adf866bd8c456593cd24beb6a0a061dedf42b26a993176745f6b
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
容器相关命令
代码语言:javascript复制#创建并启动容器
#容器由镜像创建....
docker run [参数] 镜像名
--name="xxx" 指定容器名
-i:以交互模式运行容器,通常与 -t 同时使用
-t:为容器重新分配一个伪输入终端,通常与 -i 同时使用
-it 交互模式运行
启动镜像,安装容器并进入容器中去(进入集装箱 可以看到安装环境的目录…),
exit 退出,离开集装箱
ctrl P Q 容器不停止退出
-d 后台运行(如果容器中没有服务运行,则启动后会自动停止)
-p 指定映射端口
-P 随机指定端口(大写P)
-v 数据卷 #后面解释
#查看容器
docker ps #查看docker 上的所有 在运行的容器;
-a :列出当前所有正在运行的容器 历史上运行过的
-l :显示最近创建的容器。
-q :静默模式,只显示容器编号。
--no-trunc :不截断输出。
#删除容器
docker rm 容器id/名
#删除所有容器(-f 强制删除,包括正在运行的容器)
docker rm -f $(docker ps -aq)
#启动容器
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
#docker logs 显示容器持续运行的日志信息
docker logs -f -t --tail 容器ID
-t 是加入时间戳
-f 跟随最新的日志打印
--tail 数字 显示最后多少条
#查看容器内运行的进程信息!
docker top 容器ID
#进入正在运行的容器并以命令行交互
docker exec -it 容器ID /bin/hash
情景再现
容器后台启动并访问:
- 查询所有 镜像
- 根据Tomcat镜像生成一个Tomcat 容器 (因为容器内部是默认启动的,通过暴漏接口进行访问…)
[root@hadoop1 ~]# clear
[root@hadoop1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test2_kafkademo latest ed4ebc0ed41c 5 months ago 672MB
app 1.0 02094c567c02 5 months ago 672MB
tomcat 8.5 d5ef56581444 7 months ago 530MB
wurstmeister/kafka latest 40094a582680 8 months ago 435MB
centos 7 7e6257c9f8d8 8 months ago 203MB
logstash 7.6.2 fa5b3b1e9757 12 months ago 813MB
kibana 7.6.2 f70986bc5191 12 months ago 1.01GB
elasticsearch 7.6.2 f29a1ee41030 12 months ago 791MB
wurstmeister/zookeeper latest 3f43f72cb283 2 years ago 510MB
java 8 d23bdf5b1b1b 4 years ago 643MB
[root@hadoop1 ~]# docker run -d -p 8081:8080 tomcat:8.5
103db4b6b53360a99e100e5e8244c3c76335d60a272ec1cfdfb4f07c03a3e005
[root@hadoop1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
103db4b6b533 tomcat:8.5 "catalina.sh run" About a minute ago Up About a minute 0.0.0.0:8081->8080/tcp, :::8081->8080/tcp kind_margulis
- 注意这里是404 没有找到页面,并不是报错,因为镜像解析的Tomcat是没有默认展示demo的
- 正常的Tomcat 访问之所以有 小猫页面是因为它的 webapps目录下存在一个可以默认访问的root 项目,
Docker镜像生成的是不存在的
- 所以这不是报错,而是成功了!
接下来,可以编写一个,MVC的Demo 上传至容器中Tomcat webapps文件下在进行方法就ok了! 这里就不展示了!
容器 与 宿主机 文件交互:
代码语言:javascript复制#从容器内拷贝文件到宿主机
docker cp 容器id:/目录/,,/文件 /宿主目录
#从宿主机拷贝文件到容器
docker cp 宿主文件容器id:/目录/,,/
场景再现 容器和宿主机互相拷贝文件
代码语言:javascript复制#运行容器
[root@localhost ~]# docker run -it centos:7 /bin/bash
#ctrl p q
[root@c99eecf69910 /]# [root@localhost ~]#
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c99eecf69910 centos:7 "/bin/bash" 9 seconds ago Up 8 seconds focused_kapitsa
#进入容器,创建测试文件
[root@localhost ~]# docker exec -it c99eecf69910 /bin/bash
[root@c99eecf69910 /]# ls
anaconda-post.log bin dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
[root@c99eecf69910 /]# cd /home/
[root@c99eecf69910 home]# touch aaa
[root@c99eecf69910 home]# echo "hello" >> aaa
[root@c99eecf69910 home]# cat aaa
hello
#退出容器
[root@c99eecf69910 home]# exit
exit
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c99eecf69910 centos:7 "/bin/bash" About a minute ago Up About a minute focused_kapitsa
#从容器内拷贝文件到宿主机
[root@localhost ~]# docker cp c99eecf69910:/home/aaa /tmp
[root@localhost ~]# ls /tmp/
aaa vmware-root_626-2697073973 vmware-root_633-3988162919
[root@localhost ~]# cat /tmp/aaa
hello
[root@localhost ~]#
代码语言:javascript复制[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c99eecf69910 centos:7 "/bin/bash" 5 minutes ago Up 5 minutes focused_kapitsa
[root@localhost ~]# ls
anaconda-ks.cfg
#在宿主机创建测试文件
[root@localhost ~]# touch bbb
[root@localhost ~]# ls
anaconda-ks.cfg bbb
#从宿主机拷贝文件到容器
[root@localhost ~]# docker cp bbb c99eecf69910:/home/
#进入容器检查
[root@localhost ~]# docker exec -it c99eecf69910 /bin/bash
[root@c99eecf69910 /]# cd /home/
[root@c99eecf69910 home]# ls
aaa bbb
[root@c99eecf69910 home]#
提交容器为新镜像
代码语言:javascript复制docker commit -a="" -m="" 容器id 镜像名:版本号
-a 指定作者
-m 描述
- ok 到了这儿,相信大家对Docker 有了一定的了解
- Docker 就像是一个鲸鱼,运行在大海
操作系统
上,背上有很多集装箱容器
- 多个集装箱之间,互补干涉,一个集装箱就是一个新的环境…
- 镜像 就是码头,可以生成容器,放在鲸鱼背上…
常用命令:
菜鸟教程
代码语言:javascript复制#docker import : 从归档文件中创建镜像。
docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
#OPTIONS说明:
#-c :应用docker 指令创建镜像;
#-m :提交时的说明文字;
#docker import 导入的文件.tar 镜像名:设置TAG
#docker save : 将指定镜像保存成 tar 归档文件。
docker save [OPTIONS] IMAGE [IMAGE...]
#OPTIONS 说明:
#-o :输出到的文件。
#docker save -o 生成的文件.tar 操作的镜像
#docker load : 导入使用 docker save 命令导出的镜像。
docker load [OPTIONS]
#OPTIONS 说明:
#--input , -i : 指定导入的文件,代替 STDIN。
#--quiet , -q : 精简输出信息。
#docker load --input 输入的文件.tar
镜像分层:
Union 文件系统是 Docker 镜像的基础。
- 镜像可以通过分层来进行继承
- 基于基础镜像
没有父镜像
,可以制作各种具体的应用镜像。
什么是 Union 文件系统
- UnionFS(联合文件系统)
- Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统
- 它支持:
对文件系统的修改作为一次提交来一层层的叠加
, 同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。
- 从上图可以看到,新镜像是从 base 镜像一层一层叠加生成的。
每安装一个软件,就在现有镜像的基础上增加一层。
镜像分层最大的一个好处就是 共享资源
- 比如说有多个镜像都从相同的 base 镜像构建而来
- 那么 Docker Host 只需在磁盘上保存一份 base 镜像; 同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。 而且镜像的每一层都可以被共享。
「Copy-on-Write」 特性。
如果多个容器共享一份基础镜像
- 当某个容器修改了基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc 是不会被修改的
- 修改只会被限制在单个容器内。这就是容器 「Copy-on-Write」 特性。
分层镜像的表现:
- 以我们的pull为例
在下载的过程中我们可以看到docker的镜像好像是在一层一层的在下载
可写容器层:
特点:
- 当容器启动时,
一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”
“容器层”之下的都叫“镜像层”。
- 所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。
「容器层是可写的,容器层下面的所有镜像层都是只读的」
- 镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的
文件系统。
如果不同层中有一个相同路径的文件 比如: /a,上层的 /a 会覆盖下层的 /a,也就是说用户只能访问到上层中的文件 /a在容器层中,用户看到的是一个叠加之后的文件系统。
Docker 容器生成镜像
- 我们都知道,镜像可以生成容器,
容器由镜像生成
- 生成之后的容器,不是镜像,是一个独立存在的一个
运行环境 空间...
多个容器之间是不会相互影响的… - 而,当一个容器,随着时间延迟,慢慢环境稳定,自身扩展了很多新的技术…为了方便开发者 重新部署扩展… 我们可以之间将该 容器生成一个新的镜像,进行使用!
#docker commit
#docker commit提交容器副本使之成为一个新的镜像
docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名/版本号]
#展示一个镜像的生成历史
docker history 镜像id
Docker容器数据卷
数据卷:
- 实际上我们的容器就好像是一个简易版的操作系统
只不过系统中只安装了我们的程序运行所需要的环境
前边说到我们的容器是可以删除的,那如果删除了,容器中的程序产生的需要持久化的数据怎么办呢? 容器运行的时候我们可以进容器去查看,容器一旦删除就什么都没有了。 - 所以数据卷就是来解决这个问题的,是用来将数据持久化到我们宿主机上
与容器间实现数据共享
简单的说就是将宿主机的目录映射到容器中的目录 应用程序在容器中的目录读写数据会同步到宿主机上,这样容器产生的数据就可以持久化了 - 比如我们的数据库容器,就可以把数据存储到我们宿主机上的真实磁盘中。
数据卷的特点:
- 数据卷可在容器之间共享或重用数据
- 卷中文件的更改可以直接生效
- 数据卷中文件的更改不会包含在镜像的更新中
容器的数据卷是与 主宿主机进行交互的,并不会影响到镜像...
- 数据卷的生命周期一直持续到没有容器使用它为止
操作方法
在容器启动时添加
代码语言:javascript复制docker run -it -v /宿主机目录:/容器内目录 centos /bin/bash
#看到没有,这是在容器进行创建时候,进行配置的与宿主机进行的映射...与镜像一点关系都没有!
#而且经过本人测试,就算宿主机目录,不存在 它会自动生成一个!
docker run -it -v 宿主机目录:容器中目录:ro 镜像名
#ro:表示 read only , 配置后可以在容器中挂载目录下添加文件试试,会提示该目录为只读。
- 这里的 /bin/bash目前先暂时忽略…
查看数据卷是否添加成功
代码语言:javascript复制docker inspect 容器ID
测试Mysql
代码语言:javascript复制#拉取镜像
[root@localhost ~]# docker pull mysql:5.7
#创建并启动容器,挂载数据卷
[root@localhost ~]# docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=ok --name mysql01 mysql:5.7
af27e320f780a8c8a0de63abf76fd50a5375d85c1a27cbba7636c47dd830c96e
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
af27e320f780 mysql:5.7 "docker-entrypoint.s…" 7 seconds ago Up 6 seconds 0.0.0.0:3306->3306/tcp, 33060/tcp mysql01
b323eea0dea4 portainer/portainer "/portainer" About an hour ago Up About an hour 0.0.0.0:9000->9000/tcp portainer
[root@localhost ~]#
使用navicate连接后建库测试
查看数据卷在宿主机的挂载点目录下已经有testdb的库文件生成
使用DockerFile添加卷
- 可在Dockerfile中使用VOLUME指令来给镜像添加一个或多个数据卷 出于可移植和分享的考虑,用-v 主机目录:容器目录这种方法不能够直接在Dockerfile中实现。 由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有的宿主机上都存在这样的特定目录。
VOLUME["/容器内目录","/...","/..."]
#多个,数据卷 挂载可以用,逗号进分隔配置!
#这样,生成的数据卷,会默认在主机中创建一个目录,与容器进行 共享数据!
可以通过
docker inspect 容器ID #查看,容器在宿主中的挂载目录!
- Source
宿主目录!
Dockerfile
概念及语法
概念:
Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。 Dockerfile
- Dockerfile定义了进程需要的一切东西。 Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库 操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,
- 这时需要考虑如何设计namespace的权限控制)等等;
Docker镜像
- 在用Dockerfile定义一个文件之后
docker build
- 会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;
Docker容器
- 容器提供服务。
构建三步骤
- 编写Dockerfile文件
- docker build
- docker run
语法:
代码语言:javascript复制FROM # 基础镜像,从这个镜像开始构建
MAINTAINER # 作者信息 镜像维护者的姓名和邮箱地址
RUN # 镜像构建时所运行的命令
ADD # 向镜像中添加文件,比如tomcat的tar.gz包,并且会自动解压
# 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
WORKDIR # 设置工作目录:指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点
VOLUME # 挂载目录:容器数据卷,用于数据保存和持久化工作
EXPOSE # 暴露端口
CMD # 容器启动时要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 容器启动时要运行的命令,可追加
ENTRYPOINT配置容器启动时的执行命令 不会被忽略,一定会被执行,会和 docker run时的指令拼接
COPY # 向镜像中拷贝文件
类似ADD,拷贝文件和目录到镜像中。
将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的<目标路径> 位置
COPY src dest
COPY ["src", "dest"]
ENV # 设置环境变量
ENV MY_PATH /usr/mytest
这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了 环境变量前缀一样
也可以在其它指令中直接使用这些环境变量 比如:WORKDIR $MY_PATH
ONBUILD #当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发
这条语句会在其他镜像FORM 本镜像时执行
- 每条保留字指令都必须为大写字母,并且随后必须添加参数
- 按照指令从上到下依次执行
- #表示注解
- 每条dockerFile指令都会创建一个新的镜像层,并对镜像进行提交
构建镜像
在编辑好DockerFile如果不使用RUN命令的话需要要进行手动构建容器
代码语言:javascript复制docker build -f Dockerfile -t mycentos:1.0 .
- -f 指定文件名(如文件名就是Dockerfile可以不用写-f)
- -t 指定镜像名:版本
- . 意为在当前路径下, 扫描文件执行
执行流程
- docker从基础镜像运行一个容器
- 执行一条指令并且对容器作出修改
- 执行类似于docker commit的操作提交一个新的镜像层
- docker再基于提交好的镜像运行一个新容器
- 执行dockerfile中的下一条指令直到所有指令完成
CMD/ENTRYPOINT 镜像案例
都是指定一个容器启动时要运行的命令
CMD
- Dockerfile 中可以有多个 CMD 指令
- 但只有最后一个生效,CMD 会被 docker run 之后的参数替换
ENTRYPOINT
- docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合
总结:
- CMD 和 ENTRYPOINT 都是实现一样的功能,可以在运行
docker run
时候添加一些执行命令 - 比如:/bin/bash
/bin/bash 可以理解是执行文件时候,的一种声明,表示这个Linux 运行 shell脚本…
而,很多时候,我们运行docker 命令并没有,指定要
/bin/bash
因为它的 Dockerfile 最后一行已经,通过 CMD 或 ENTRYPOINT 设置号了默认执行! - 很多时候,我们通过镜像创建 Tomcat容器发现
Tomcat容器默认运行,也是因为内部默认执行了
启动Tomcat - 而,我们在使用 CMD 时候后面的命令会覆盖前面的,所以需要进行注意! ENTRYPOINT 会对命令进行拼接在执行,成立就执行,不成立则报错!
情景在现:
代码语言:javascript复制[root@hadoop1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test2_kafkademo latest ed4ebc0ed41c 5 months ago 672MB
app 1.0 02094c567c02 5 months ago 672MB
tomcat 8.5 d5ef56581444 7 months ago 530MB
wurstmeister/kafka latest 40094a582680 8 months ago 435MB
centos 7 7e6257c9f8d8 8 months ago 203MB
logstash 7.6.2 fa5b3b1e9757 12 months ago 813MB
kibana 7.6.2 f70986bc5191 12 months ago 1.01GB
elasticsearch 7.6.2 f29a1ee41030 12 months ago 791MB
wurstmeister/zookeeper latest 3f43f72cb283 2 years ago 510MB
java 8 d23bdf5b1b1b 4 years ago 643MB
[root@hadoop1 ~]# docker run tomcat:8.5 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
- 根据镜像生成容器,结尾执行 ls命令:
- 因为没有使用
-d 后台输出
所以 ls 查看目录的数据打印在前台了,就是容器内部的路径!
测试构建tomcat镜像
代码语言:javascript复制# 步骤1.准备好jdk和tomcat的安装包
[root@localhost test]# ls
apache-tomcat-8.5.38.tar.gz jdk-8u181-linux-x64.tar.gz
# 步骤2.编写Dockerfile
# 注意 tail -F ,容器需要有持续运行的程序,否则运行后会自动退出,-F 代表文件不存在也会创建新文件并持续追踪
[root@localhost test]# vim Dockerfile
FROM centos:7
MAINTAINER catsclaws<catsclaws@126.com>
#将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
#把java与tomcat添加到容器中
ADD jdk-8u181-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.5.38.tar.gz /usr/local/
#安装vim编辑器
#因为,每一个容器内部其实都存在一个操作系统,但并不是完整的... 是一些需要的线程的集合!
#对于一些编辑器 c 环境,都是不存在,如果需要还需要手动进行下载!
RUN yum -y install vim
#设置工作访问时候的WORKDIR路径,登录落脚点
ENV MYPATH /usr/local/
WORKDIR $MYPATH
#配置java与tomcat环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_181
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV TOMCAT_HOME=/usr/local/apache-tomcat-8.5.38
ENV PATH $PATH:$JAVA_HOME/bin:$TOMCAT_HOME/bin
#容器运行时监听的端口
EXPOSE 8080
#启动时运行tomcat
CMD /usr/local/apache-tomcat-8.5.38/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.38/bin/logs/catalina.out
# 步骤3.构建为镜像
[root@localhost test]# docker build -t mytomcat .
Sending build context to Docker daemon 195.3MB
Step 1/12 : FROM centos:7
---> 7e6257c9f8d8
Step 2/12 : MAINTAINER catsclaws<catsclaws@126.com>
---> Running in 5f89b3881e12
Removing intermediate container 5f89b3881e12
---> cf22c92da005
Step 3/12 : ADD jdk-8u181-linux-x64.tar.gz /usr/local/
---> 50f5ef2f286c
Step 4/12 : ADD apache-tomcat-8.5.38.tar.gz /usr/local/
---> 6b6bd289bcde
Step 5/12 : ENV MYPATH /usr/local/
---> Running in 9bb834171f88
Removing intermediate container 9bb834171f88
---> 2cba2c45a677
Step 6/12 : WORKDIR $MYPATH
---> Running in b626f42cb13d
Removing intermediate container b626f42cb13d
---> 5b3b73fd71ef
Step 7/12 : ENV JAVA_HOME /usr/local/jdk1.8.0_181
---> Running in 1f90acfbd2b5
Removing intermediate container 1f90acfbd2b5
---> b597d1ff634e
Step 8/12 : ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
---> Running in 0cc5759756cf
Removing intermediate container 0cc5759756cf
---> 179c75a85468
Step 9/12 : ENV TOMCAT_HOME=/usr/local/apache-tomcat-8.5.38
---> Running in 2ae699d63461
Removing intermediate container 2ae699d63461
---> 5d8a712332d5
Step 10/12 : ENV PATH $PATH:$JAVA_HOME/bin:$TOMCAT_HOME/bin
---> Running in b943a17b5c1f
Removing intermediate container b943a17b5c1f
---> 031d203be8ac
Step 11/12 : EXPOSE 8080
---> Running in 24ecbae3cc82
Removing intermediate container 24ecbae3cc82
---> 5643c4502f47
Step 12/12 : CMD /usr/local/apache-tomcat-8.5.38/bin/startup.sh && tail -f /usr/local/apache-tomcat-8.5.38/bin/logs/catalina.out
---> Running in 77dfe4769086
Removing intermediate container 77dfe4769086
---> a3a08f0320e9
Successfully built a3a08f0320e9
Successfully tagged mytomcat:latest
[root@localhost test]#
[root@localhost test]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mytomcat latest cd9be136ba5d 16 minutes ago 599MB
tomcat 9.0 f796d3d2c195 3 weeks ago 647MB
nginx latest 7e4d58f0e5f3 3 weeks ago 133MB
mysql 5.7 ef08065b0a30 4 weeks ago 448MB
centos 7 7e6257c9f8d8 8 weeks ago 203MB
[root@localhost test]#
# 步骤4.启动容器,并测试
# 注意:数据卷不要直接挂载到 webapps 目录,宿主机的目录为空会导致容器内目录也为空,也就没有ROOT等目录了
[root@localhost test]# docker run -d -p 9090:8080 -v /home/tomcat/webapps/myweb:/usr/local/apache-tomcat-8.5.38/webapps/myweb -v /home/tomcat/logs:/usr/local/apache-tomcat-8.5.38/logs --name tomcat01 mytomcat
af8d166de32e2b9f09c22320b825bc625df32371a07fce25eea48d58e19c3a00
[root@localhost test]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
af8d166de32e mytomcat "/bin/sh -c '/usr/lo…" 3 seconds ago Up 2 seconds 0.0.0.0:9090->8080/tcp tomcat01
[root@localhost test]#