命令如下:
01 、搜索镜像 search 建议大家去docker搜索,可以看到帮助文档
02、下载镜像 pull
03、运行测试
参数说明
-d 后台运行
–name 给容器命名
-p 宿主机端口:容器内部端口
端口暴露的概念
官方使用:
docker run -it --rm tomcat:9.0
注:我们之前的启动都是后台,停止容器之后,容器还是可以查到,docker run -it --rm tomcat:9.0 一般用来测试,用完即删,
1、下载启动
docker pull tomcat
2、启动运行
docker run -d -p 3355:8080 --name tomcat01 tomcat
3、测试外网访问没有问题,报错404,只是不完整
4、进入容器
docker exec -it tomcat01 /bin/bash
5、发现问题,
a、linux命令少了,
b、没有webapps. 阿里云镜像的原因,默认是最小的镜像,所有不必要的都剔除掉
root@a1f3af4f9f22:/usr/local/tomcat/webapps# cp …/webapps.dist/* .
思考问题:我们以后要部署项目,如果每次都 要进入容器是不是十分麻烦,我们要是可以在容器外部提供一个映射路径,webapps, 我们在外部放置项目就自动同步到内部就好了,
** 启动了 linux就卡住了, docker stats 查看cpu状态
** es是十分耗内存,
** 查看docker stats
** 测试一下es 是够成功了,
** 赶紧关闭,增加内存的限制
@@内存限制: -e ES_JAVA_OPTS="-Xms64m -Xms512m"
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e “discovery.type=single-node” -e ES_JAVA_OPTS="-Xms64m -Xms512m" elasticsearch:7.9.3
UnionFS(联合文件系统)
我们下载的时候看到的一层层就是这个!
UnionFS(联合文件系统) :Union(联合文件系统)是一种分层,轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem). 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等等
平时我们安装进虚拟机的CentOS都好几个G,为什么Docker这里才200M
对于一个精简的OS , rootfs可以很小,只需要包含最基本的命令,工具和程序库就可以了因为底层直接用Host的kernel,自己只需要提供rootfs就可以了,由此可见对于不同的Linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行生版可以公用bootfs
虚拟机是分钟级别的,容器是秒级的!
------思考:为什么Docker镜像要采用这种分层的结构呢?
最大的好处,我觉得莫过于是资源共享了比如有多个镜像都 从桢的Base镜像构建而来,寻么宿主机只需要在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的第每一层可以被共享
------理解:所有的Docker镜像都起始于一个基础镜像层,当时行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层,举一个简单的例子,假如基于Ubuntu Linux16.04创建一个新的镜像,这就是新镜像的第一层,如果在该镜像中添加Python包,就会在基础镜像之上创建第二个镜像层,如果继续添加一个安全补丁,就会创建第三个镜像层,
该镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)
在添加额外的镜像层的同时,镜像始终保持是当前所有的镜像组合,这一点非常重要,下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件
上图中的镜像层跟之前的图中略有区别,主要目的是便于展示文件
下图中展示了一个稍微复杂的三层镜像,在外部看一整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本
这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件,这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。
------ Docker通存储引擎(新版本采用快照机制)的试来实现镜像层规栈,并保证多镜像层对外展示为统一的文件系统。
------ Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
------ Docker在Windows上仅支持windowsfilter 一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW[1]
下图展示了与系统显示相同的三层镜像,所有镜像层堆叠并合并,对外提供统一的视图
—特点—
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部,这一层就是我们通常说的容器层,容器之下都叫镜像层
docker commit 提交容器成了一个新的副本
命令和git原理类似
docker commit -m=“提交的描述信息” -a=“作者” 容器id 目标镜像名,[TAG]
1、启动一个默认的tomcat
2、发现这个默认的tomcat 是没有webapps应用,镜像的原因官方的镜像默认webapps下面是没有文件 的
3、我自己拷贝进去了基本的文件
4、将我们操作过的容器通过commit 提交为一个镜像,我们以的一就使用我们修改过的镜像即可,这就是我们自己的一个修改的镜像
学习方式说明: 理解概念,但是一定要实践,最后实践和理论相结合一次搞定这个知识
如果你想要保存当前容器的状态,就可以通赤commit来提交,获得一个镜像,就好比我们以前学习过的VM快照
到了这里才算是入门
方式一:直接使用命令来挂载 -v
docker run -it -v 主机目录:容器目录 -p 主机端口:容器内端口
好处:我们以后修改只需要在本地修改即可,容器内会自动同步!
思考:MySQL的数据持久化的问题
------ 1、获取镜像:
[root@joboy home]# docker pull mysql:5.7
------2 、运行容器,需要做数据挂载! 安装启动mysql, 需要配置密码,这是要注意点!
这是官方文档---->官方命令:
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
参数说明:
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置
–name 容器名字
------ 3、启动我们的mysql
[root@joboy home]#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
------ 4、启动之后我们在本地使用 sqlyog 来不接测试一下, sqlyog连接到服务器3310—3310和容器内的3306映射,这个时候我们就可以连接上了,本在测试创建一个数据库,查看一下我们映射的路径是否ok
------ 匿名挂载
docker run -d -P --name nginx01 -v /etc/nginx nginx
------ 查看所有的volume 卷的情况
docker volume ls
------ 这里发现,这种就是匿名挂载,我们在-v只写了容器内的路径,没有写容器外的路径!
docker volume inspect juming_nginx
所有的docker 容器内的卷,沿岸有指定目录的情况下都是在 /var/lib/docker/volumes/****/_data
我们通过具名挂载可以方便的找到我们的一个卷,大多数情况我们使用的是: 具名挂载
----- 如何确定是具名挂载还是匿名挂载,还是指定路径挂载
1、-v 容器内路径-------------------------------- # 匿名挂载
2、-v 卷名:容器内路径----------------------- # 具名挂载
3、-v /宿主机路径::容器内路径--------------- # 指定路径挂载!
拓展:
通过 -v 容器内路径: ro rw 改变读写权限
ro: readonly # 只读
rw readwrite # 可读可写
注:一但这个设置了容器权限,容器对我们挂载出来的内容就有限定了
docker run -d -P --name nginx03 -v juming_nginx:/etc/nginx nginx:ro
docker run -d -P --name nginx03 -v juming_nginx:/etc/nginx nginx:rw
# ro 只要看到ro 就说明这个路径只能通过宿主机来操作,容器内部是无法操作的!
Dockerfile 就是用来构建docker镜像的构建文件! 命令脚本,先体验一下
--------通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个个的命令,每个命令都是一层!
方式二 : 直接写Dockerfile:
----------自己写的容器
这个卷和外部一定有一个同步目录
测试一下刚才的文件是否同步出去了
这种方式我们未来使用的十分多,因为我们通常会构建自己的镜像,假设构建镜像的时候没有挂载卷,要手动镜像挂载, -v 卷名:容器内路径
–多个mysql同步数据
先看下面的例子:两个docker 及以前数据同步
docker run -it --name docker02 --volumes-from docker01 80297b784621
—# 测试:可以删除docker01 , 查看一下docker02 和docker03是否还可以访问这个文件
—# 测试结果:测试结果依旧可以访问
下面来实现多个mysql现实数据共享
[root@joboy ~]# 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
[root@joboy ~]# docker run -d -p 3310:3306 l -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
– # 这个时候可以实现两个容器数据同步
结论: 容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止,但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的!
dockerfile 是用来构建docker镜像的文件,命令参数脚本
构建步骤:
1、 编写一个dockfile文件
2、docker build 构建成了一个镜像
3、docker run 运行镜像
4、docker push 发布镜像(DockerHub 、阿里云镜像仓库)
查看一下我们的官方是怎么做的?
很多官方镜像都是基础包很多功能都没有,我们通常会自己搭建自己的镜像,
官方既然可以制作镜像,那我人也可以!
1、每个保留关键字(指令)都是必须是大写字母
2、执行从上到下顺序执行
3、#表示注释
4、每一个指令都会创建提交一个新的镜像层,并提交!
5、dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockfile文件,这个文件十分简单!
Dock镜像逐渐成为企业交付的标准,,必须掌握,!
开发步骤: 开发、部署、运维。。。。 缺一不可
FROM--------------- # 基础镜像,一切从这里开始构建
MAINTAINER---- # 镜像是谁写的,姓名+邮箱
RUN --------------- # 镜像构建的时候需要运行的命令
ADD --------------- # 步骤:tomcat镜像,这个tomcat压缩包,添加内容
WORKDIR--------- #镜像的工作目录
VOLUME---------- #挂载的目录
EXPOST----------- # 保留端口配置
CMD----------------- # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT---- # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD----------- # 当构建一个被继承 DockerFile 这个时候就会运行 ONBUILD 的命令,触发指令
COPY-----------------# 类似ADD 将我们文件拷贝到镜像中
ENV-------------------# 构建的时候设置环境变量
Docker Hub中,99% 镜像都是从这个基础镜像过来的 FROM scratch, 然后配置需要的软件和配置来进行的构建
------ 自己创建一个centos
1、 编写自己的镜像
代码如下:
FROM centos
MAINTAINER [email protected]
ENV MYPATH /uer/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo “----end----”
CMD /bin/bash
2、 通过这个文件构建镜像
命令 docker build -f dockerfile文件路径 -t 镜像名:[tag]
[root@joboy dockerfile]# docker build -f mydockerfile_centos -t mycentos:1.0
注释:最后一个点 “.” 不要忘记
3、测试运行
CMD -------------- # 指定这个容器启动的时候要运行的命令只有最后一个会生效,可被替代
ENTRYPOINT —#指定这个家口 启动的时候要运行的命令,可以追加命令
# 测试CMD:
编写dockerfile 文件
[root@joboy dockerfile]# vim dockerfile_cmd_test
FROM centos
CMD ["ls","-a"]
# 构建镜像
[root@joboy dockerfile]# docker build -f dockerfile_cmd_test -t cmdtest .
# run运行,发现我们的ls -a 命令生效
[root@joboy dockerfile]# docker run 5efed9aee7dc
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 想追加一个命令 -l ls -al
[root@joboy dockerfile]# docker run 5efed9aee7dc -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\": executable file not found in $PATH": unknown.
# cmd 情况下 -l 替换了CMD [ "ls" , "-a" ] 命令,-l 不是命令所以报错
root@joboy dockerfile]# docker run 5efed9aee7dc ls -al
total 56
drwxr-xr-x 1 root root 4096 Nov 20 11:59 .
drwxr-xr-x 1 root root 4096 Nov 20 11:59 ..
-rwxr-xr-x 1 root root 0 Nov 20 11:59 .dockerenv
lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin
drwxr-xr-x 5 root root 340 Nov 20 11:59 dev
drwxr-xr-x 1 root root 4096 Nov 20 11:59 etc
drwxr-xr-x 2 root root 4096 May 11 2019 home
lrwxrwxrwx 1 root root 7 May 11 2019 lib -> usr/lib
lrwxrwxrwx 1 root root 9 May 11 2019 lib64 -> usr/lib64
drwx------ 2 root root 4096 Aug 9 21:40 lost+found
drwxr-xr-x 2 root root 4096 May 11 2019 media
drwxr-xr-x 2 root root 4096 May 11 2019 mnt
drwxr-xr-x 2 root root 4096 May 11 2019 opt
dr-xr-xr-x 94 root root 0 Nov 20 11:59 proc
dr-xr-x--- 2 root root 4096 Aug 9 21:40 root
drwxr-xr-x 11 root root 4096 Aug 9 21:40 run
lrwxrwxrwx 1 root root 8 May 11 2019 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 May 11 2019 srv
dr-xr-xr-x 13 root root 0 Nov 20 11:59 sys
drwxrwxrwt 7 root root 4096 Aug 9 21:40 tmp
drwxr-xr-x 12 root root 4096 Aug 9 21:40 usr
drwxr-xr-x 20 root root 4096 Aug 9 21:40 var
[root@joboy dockerfile]#
测试ENTRYPOINT:
[root@joboy dockerfile]# docker build -f dockerfile_cmd_entrypoint -t
Sending build context to Docker daemon 4.096kB
Step 1/2 : FROM centos
---> 0d120b6ccaa8
Step 2/2 : ENTRYPOINT ["ls","-a"]
---> Running in d2bc5a1555d7
Removing intermediate container d2bc5a1555d7
---> 8bc56be759ad
Successfully built 8bc56be759ad
Successfully tagged entrypoint_test:latest
[root@joboy dockerfile]# docker run 8bc56be759ad
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 我们的追加命令, 是直接拼接在我们的 ENTRYPOINT 命令后面的
[root@joboy dockerfile]# docker run 8bc56be759ad -l
total 56
drwxr-xr-x 1 root root 4096 Nov 20 12:07 .
drwxr-xr-x 1 root root 4096 Nov 20 12:07 ..
-rwxr-xr-x 1 root root 0 Nov 20 12:07 .dockerenv
lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin
drwxr-xr-x 5 root root 340 Nov 20 12:07 dev
drwxr-xr-x 1 root root 4096 Nov 20 12:07 etc
drwxr-xr-x 2 root root 4096 May 11 2019 home
lrwxrwxrwx 1 root root 7 May 11 2019 lib -> usr/lib
lrwxrwxrwx 1 root root 9 May 11 2019 lib64 -> usr/lib64
drwx------ 2 root root 4096 Aug 9 21:40 lost+found
drwxr-xr-x 2 root root 4096 May 11 2019 media
drwxr-xr-x 2 root root 4096 May 11 2019 mnt
drwxr-xr-x 2 root root 4096 May 11 2019 opt
dr-xr-xr-x 94 root root 0 Nov 20 12:07 proc
dr-xr-x--- 2 root root 4096 Aug 9 21:40 root
drwxr-xr-x 11 root root 4096 Aug 9 21:40 run
lrwxrwxrwx 1 root root 8 May 11 2019 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 May 11 2019 srv
dr-xr-xr-x 13 root root 0 Nov 20 12:07 sys
drwxrwxrwt 7 root root 4096 Aug 9 21:40 tmp
drwxr-xr-x 12 root root 4096 Aug 9 21:40 usr
drwxr-xr-x 20 root root 4096 Aug 9 21:40 var
[root@joboy dockerfile]#
总结:Dockerfile中很多命令都十分的相似,我们想要了解他们的区别,我们最好的学习就是对比他们然后测试结果!
1、准备镜像文件,tomcat 压缩包,jdk的压缩包
2、编写dockerfile文件,官方命名Dockerfile
, buld会自动寻找这个文件,就不需要 -f 指定了
FROM centos
MAINTAINER pengpeng<[email protected]>
COPY readme.txt /uer/local/readme.txt
ADD jdk-8u11-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.40.tar.gz /usr/local
RUN yum -y update --nogpgcheck
RUN yum -y makecache --nogpgcheck
RUN yum -y install vim --nogpgcheck
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.40
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.40
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.40/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.40/bin/logs/catalina.out
3、构建镜像
[root@joboy pengpeng]# docker build -t diytomcat .
4、启动镜像
docker run -d -p 9090:8080 --name pengpengcomcat2 -v /home/pengpeng/build/tomcat/test:/usr/local/apache-tomcat-9.0.40/webapps/test -v /home/pengpeng/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.40/logs diytomcat
5、访问测试
6、发布项目(由于做了卷挂载,我们直接在本地编写项目就可以发布了!)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
</web-app>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
Hello 朋朋(runoob.com)
Hello World!
<%
System.out.println("-------Hello The World Hello pengpeng---------")
%>