赞
踩
docker的理念回顾:
将我们的应用和运行环境打包成镜像发布,之后启动以容器运行。
数据怎么保存呢?如果数据存储在容器中,容器删除的时候,数据就会丢失。这肯定是不合理的。
需求:数据持久化
容器之间应该有一个数据共享的技术。docker容器中产生的数据,可以同步到本地!
这就是卷技术!
——目录的挂载:将我们容器内的目录,挂载到Linux上面!
总结一句话:
- 容器的持久化和同步操作!
- 容器间也是可以数据共享的
方式一:使用命令挂载
docker run -it -v 主机目录:容器内目录 # 可以类比 -p 端口的映射
# 测试
docker run -it -v /home/ceshi:/home centos /bin/bash
挂载之后,容器内的/home目录和Linux的/home/ceshi目录就共享了!
容器内/home目录资源的变化,Linux目录可以共享;
容器外Linux目录资源的变化,容器内目录可以共享!
好处:我们以后修改只需要在本地修改就好,容器内会自动同步!
实战测试
思考:MySQL的数据持久化问题!
# 下载mysql docker pull mysql:5.7 # 启动容器+数据挂载! # 安装启动mysql,需要密码 docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql --name mysql01 -e MYSQL_ROOT_PASSWORD=root mysql:5.7 # 解释 -d # 后台运行 -p # 端口映射 -v # 卷挂载 -e # 环境配置 --name # 容器命名 # 启动成功,本地通过workbench测试连接 # workbench---> 连接到服务器的 3306 映射到容器的3306 # 在本地创建一个数据库 test,查看是否同步成功 # 将mysql容器删除,发现挂载到本地的数据为丢失,这就实现了容器数据的持久化
# 匿名挂载 -v 容器内路径 docker run -d -P --name nginx01 -v /etc/nginx nginx # 查看所有的 volume local 1ee598ebd27a034a9724b33fdf94f912b77983055aeca17902440db67a5edbe9 local e87a415937e57a9c0ee21c08e3407d705487d8b0ffd1c3d4a347b2112012f16d local ee5e212634a4da79f10b3f607c4e9455cf231e7d2ae72e6a6abbffcb4381c1ce # 这里发现,这种就是匿名挂载,我们在 -v 只写了容器内路径,没有写容器外路径 # 具名挂载 -v 卷名:容器内路径 docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx # 查看一下所有的 volume DRIVER VOLUME NAME local 1ee598ebd27a034a9724b33fdf94f912b77983055aeca17902440db67a5edbe9 local e87a415937e57a9c0ee21c08e3407d705487d8b0ffd1c3d4a347b2112012f16d local ee5e212634a4da79f10b3f607c4e9455cf231e7d2ae72e6a6abbffcb4381c1ce local juming-nginx 发现多了一个juming-nginx
所有的docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx/_data。
我们通过具名挂载,可以方便的找到一个卷,大多数情况下似乎该种方式,不适用匿名挂载。
# 如何确定是具名还是匿名挂载,还是指定路径挂载
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载
拓展:
# 通过 -v 容器内路径:ro(rw) 改变读写权限
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
# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作的
DockerFile 就是用来构建docker镜像的构建文件!命令脚本!
通过这个脚本可以生成镜像,镜像是一层一层的,脚本是一个个的命令,每个命令都是一层。
# dockerfile 指令(大写) 参数 每一步就是一层
FROM centos
VOLUME ["volume01", "volume02"]
CMD echo "----end----"
CMD /bin/bash
# 启动一下自己生成的容器
volume01,volume02是我们生成镜像的时候自动挂载的,数据卷目录。
这个卷和外部一定有一个同步的目录!
发现主机确实有被同步挂载的目录,匿名挂载方式。
在volume01新建了一个container.txt文件,看是否被同步。
这种方式我们使用很多,因为通常情况下我们会构建自己的镜像。
假设构建镜像的时候没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径(具名挂载,常用)
容器间同步数据。
test
通过 --volumes-from docker01 将docker02挂载docker01
在docker02的volume01内创建一个文件docker01,发现在docker02容器内可见
说明数据同步成功
注意
一旦各容器之间互相挂载,只要有一个容器被使用,那么他们之间的数据共享关系就还在,哪怕父容器被删除,其他容器的共享关系也依然存在。
好处:mysql,redis数据共享。
比如两个数据库的数据共享
# 启动父容器 mysql01,匿名挂载目录
docker run -d -p 3301:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT-PASSWORD=root --name mysql01 mysql:5.7
# 启动子容器 mysql02,同步挂载mysql01
docker run -d -p 3302:3306 -e MYSQL_ROOT_PASSWORD=root --name mysql02 --volumes-from mysql01 mysql:5.7
结论
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。(除非所有容器都停止)
dockerfile是用来构建docker镜像的文件!命令参数脚本!
构建步骤:
基础知识
dockerfile是面向开发的,发布项目,做镜像,就需要编写dockerfile文件!
DockerFile:构建文件,定义了一切的步骤,好比源代码。
DockerImages:通过DockerFile构建生成的镜像,这就是最终要发布运行的产品。
Docker容器:容器就是镜像运行起来提供服务的。
From # 基础镜像,镜像从这里开始构建,最底层 centos
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤:tomcat镜像,tomcat压缩包,添加内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录位置
EXPOSE # 保留端口暴露的配置
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承的DockerFile 这个时候会运行ONBUILD的指令。触发指令。
COPY # 类似ADD,将我们的文件拷贝到镜像中
ENV # 构建的时候设置环境变量
Docker Hub中 大多数的镜像都是从这个基础镜像构建的:FROM scratch,然后配置需要的软件和配置来进行的构建。
创建一个自己的centos:包含centos,增加vim,ifconfig命令
# 1. 编写自己的dockerfile文件 # 基于centos镜像编写 FROM centos # 作者 MAINTAINER zhangtong<mail@163.com> # 环境变量:工作路径 ENV MYPATH /usr/local WORKDIR $MYPATH # 下载基础命令vim,net-tools RUN yum -y install vim RUN yum -y install net-tools # 暴露80端口 EXPOSE 80 # 执行一些打印的命令 CMD echo $MYPATH CMD echo -----end----- # 使用/bin/bash解析 CMD /bin/bash # 2.通过这个文件构建镜像 # docker build -f dockerfile文件路径 -t 镜像名[:tag] . # 注意末尾有小数点 Successfully built 4a911b3865b1 Successfully tagged mycentos:1.0 # 3.测试运行 docker run -it mycentos:1.0 # 会发现几点: # 1. 跳转到了工作目录 /usr/local # 2. 新下载的命令vim,ifconfig可以使用了
我们可以列出本地镜像变更的历史:
docker history 镜像名[:tag]/镜像id
我们可以通过这个命令去查看镜像的变更记录,可以查到具体镜像层的变更和命令的执行。
测试cmd:
# 编写dockerfile-cmd-test FROM centos CMD ["ls", "-a"] # 构建镜像 docker build -f dockerfile-cmd-test -t cmdtest . # 运行镜像容器 docker run cmdtest . .. .dockerenv bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var # 发现 ls -a执行成功的 # 想追加一个命令 -l 想执行 ls -al docker tun cmdtest -l docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "-l": executable file not found in $PATH: unknown. # cmd的前提下,-l替换了CMD ["ls","-a"]命令,执行-l 不是命令,所以报错 # 必须使用完整的命令 docker run cmdtest ls -al # 因为他把docker的cmd给覆盖掉了
测试entrypoint:
# 编写dockerfile-entrypoint-test FROM centos ENTRYPOINT ["ls","-a"] # 构建之后执行测试 docker run entrypoint-test -l total 56 drwxr-xr-x 1 root root 4096 Mar 8 16:19 . drwxr-xr-x 1 root root 4096 Mar 8 16:19 .. -rwxr-xr-x 1 root root 0 Mar 8 16:19 .dockerenv lrwxrwxrwx 1 root root 7 Nov 3 15:22 bin -> usr/bin drwxr-xr-x 5 root root 340 Mar 8 16:19 dev drwxr-xr-x 1 root root 4096 Mar 8 16:19 etc drwxr-xr-x 2 root root 4096 Nov 3 15:22 home lrwxrwxrwx 1 root root 7 Nov 3 15:22 lib -> usr/lib lrwxrwxrwx 1 root root 9 Nov 3 15:22 lib64 -> usr/lib64 drwx------ 2 root root 4096 Dec 4 17:37 lost+found drwxr-xr-x 2 root root 4096 Nov 3 15:22 media drwxr-xr-x 2 root root 4096 Nov 3 15:22 mnt drwxr-xr-x 2 root root 4096 Nov 3 15:22 opt dr-xr-xr-x 105 root root 0 Mar 8 16:19 proc dr-xr-x--- 2 root root 4096 Dec 4 17:37 root drwxr-xr-x 11 root root 4096 Dec 4 17:37 run lrwxrwxrwx 1 root root 8 Nov 3 15:22 sbin -> usr/sbin drwxr-xr-x 2 root root 4096 Nov 3 15:22 srv dr-xr-xr-x 13 root root 0 Mar 8 16:19 sys drwxrwxrwt 7 root root 4096 Dec 4 17:37 tmp drwxr-xr-x 12 root root 4096 Dec 4 17:37 usr drwxr-xr-x 20 root root 4096 Dec 4 17:37 var # 发现 -l追加成功了
总结
cmd永远你只执行最后一条命令,新来的cmd会覆盖掉之前的cmd
entrypoint其实如果在同一个dockerfile中出现的话,他也是只执行最后一条命令的。但是entrypoint在运行容器的时候,可以增加参数。使用cmd,参数会把命> 令给覆盖掉
且entrypoint优先级高于cmd,如果同时存在的话,cmd无法覆盖entrypoint,但是entrypoint会覆盖cmd。
准备镜像文件 tomcat压缩包,jdk的压缩包
编写dockerfile文件:Dockerfile
FROM centos MAINTAINER zhangtong<mail@163.com> COPY README.md /usr/local/README.md ADD jdk-8u281-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-9.0.43.tar.gc /usr/local/ RUN yum -y install vim ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk1.8.0_281 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.43 ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.43 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-9.0.43/bin/startup.sh && tail -F /url/local/apache-tomcat-9.0.43/bin/logs/catalina.out
# 由于文件名是官方推荐 Dockerfile,因此不再需要指定文件,会默认找寻目录下该文件
docker build -t mytomcat .
# 后台启动mytomcat镜像容器
# 服务器端口开放8080,映射容器端口8080
# 容器命名mytomcat
# 挂载两个目录,test和logs
# 可以在容器外部test目录编写项目即可同步到容器内了
docker run -d -p 8080:8080 --name mytomcat -v /home/zhangtong/build/tomcat/test:/url/local/apache-tomcat-9.0.43/webapps/test -v /home/zhangtong/build/tomcat/tomcatlogs:/url/local/apache-tomcat-9.0.43/logs mytomcat
curl localhost:8080
# 得到html回显
浏览器访问 ip:8080,得到tomcat页面回显。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。