docker的文件流处理_docker 常见操作(下)

太久了,甚至一度以为自己已经上传了另一部分内容,哈哈哈。今天更新下。发现直接从 Typora 复制过来我的代码部分和图片都没了,一条条粘贴上去了,如果有错误,先说声抱歉,欢迎评论告诉我,谢谢

docker 镜像

镜像是可以执行的独立轻量软件包,可以用于打包软件运行环境和对应开发的软件,包括了代码,库,环境变量等等。

docker 镜像的基础是 Union 文件系统,支持对文件系统的下去该作为一次提交来叠加,将不同目录挂载到同一个虚拟文件系统下,所以外部看上去只能看到一个文件系统,实际上一次同事加载了多个文件系统。

这样的号出就是共享,例如有多个镜像从相同的 base 镜像构建而来,那么宿主机只需要在存一份 base 镜像即可。镜像的每一层都可以被共用。

容器启动的时候新的可写层被加载到镜像的顶部,被称作容器层,下面的层被称作镜像层,docker 的镜像都是只读的。

打包镜像

运行从 docker hub 上下载的镜像:

docker run -it -p 8080:8080 tomcat

访问最新版 tomcat 首页可以看到会提示 404:

image-20200304134442907.png

因为文件都处于 webapps.dist 中而不是默认的 webapps 中。

使用 docker exec -it 636c0b8b498a /bin/bash重新进入到 tomcat 对应的容器中,使用cp -r webapps.dist/* webapps复制 webapps.dist 中的文件到 webapps 中

刷新浏览器就能看到正常的 tomcat 首页了

image-20200304135623974.png

以修改过的容器为模板生成一个新的镜像,并命名为 iot/tomcat

docker commit -a="iot" -m="move webapps.dist to webapps" 636c0b8b498a iot/tomcat:8.5.51

查看现有镜像可以看到一个为 iot/tomcat 的镜像,然后运行他:

docker run -it -p 8081:8080 iot/tomcat:8.5.51

访问 8081 端口,正常访问

docker 数据卷

docker 容器中产生的数据如果不通过 commit 生成新的镜像,使得数据成为镜像的一部分,那么当容器删除以后数据就消失了。为了保存数据,可以使用数据卷的方式。数据卷使得 docker 做到荣期间继承和共享数据。

命令添加方式

运行容器时添加 -v 参数可以指定数据卷:

docker run -it -v /宿主机绝对路径:/容器内目录 镜像名

运行后会自动创建目录,也可以选择已有目录进行挂载。挂载后可以通过docker inspect 容器ID 的方式进行查看,如下:

image-20200304163622516.png

通过 dockerfile 添加

在dockerfile 中添加目录

在/mydocker中新建文件 Dockerfile 文件

在 dockerfile 中添加

VOLUME ["/dataContainer","/dataContainer2","/dataContainer3"]

表示容器内的 "/dataContainer","/dataContainer2","/dataContainer3" 与宿主机绑定。最简单的 dockerfile 可以是:

# volume test

FROM centos

VOLUME ["/dataContainer","/dataContainer2","/dataContainer3"]

CMD echo "Hello world!!!"

CMD /bin/bash

由于考虑到 dockerfile 的移植性考虑,不能使用类似-v /宿主机绝对路径:容器路径的方式在 dockerfile 中实现

build 生成镜像

通过

docker build -f /mydocker/Dockerfile -t iot/centos .

生成新的镜像,注意最后有个点。然后运行他:

docker run -it iot/centos /bin/bash

值得注意的是:在 Dockerfile 中使用 VOLUME 指令之后的代码,如果尝试对这个数据卷进行修改,这些修改都不会生效!

权限

容器向挂载的目录写入文件或者增加目录以后,主机上可能会遇到没有访问权限的问题,因为 docker 内部默认使用的是 root 用户。例如使用如下命令创建一个容器,同时挂载当前目录到容器内,并再容器内创建文件 tmp.txt

docker run -rm -v "$PWD":/project centos bash -c "touch /project/tmp.txt"

查看 tmp.txt 的文件信息:

image-20200305100505569.png

权限、用户,组都是 root,其他用户只能 read,切换其他用户尝试向里面写入东西:

image-20200305100947924.png

命令添加 user 参数方式

docker 提供了 --user 参数,可以指定用户名或者 UID,修改命令如下:

docker run --rm --user=$UID:$(id -g $USER) -v "$PWD":/project centos bash -c "touch /project/tmp.txt"

执行后发现已经可以正常在里面写入东西了:

image-20200305105534948.png

但是使用 user 参数会有两个缺陷:

指定的用户不存在于容器内的 /etc/passwd 中,shell 无法显示用户名。

user 参数会指定容器运行时刻的用户和主机一致,因此持有主机挂载的用户目录,但容器内非挂载的目录均无权限。

image-20200305111457611.png

为了解决这个问题可以编写一个 docker-entrypoint.sh 脚本作为 Dockerfile 的 ENTRYPOINT,在脚本中创建一个和宿主机上相同 UID 的用户,并用用 gosu 切换到还用户执行命令,UID 需要在 docker run 阶段通过参数传入

如果是希望容器只能访问宿主机上的目录,则可以在容器内路径后面加上 ro,如下:

docker run -it -v /datahost/:/datacontainer:ro centos

数据卷容器

命名的容器挂载数据卷,其它容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器。

以 iot/centos为模板,分别启动三个容器,container1,container2,container3。container2 、container3 均继承自 container1。如下:

image-20200305144518769.png

这三个容器都拥有容器卷 dataVolumeContainer0、dataVolumeContainer1。可以通过docker inspect 看到他们指向宿主机上的同一个目录。

分别在 container2 与 container3 中新增文件:

image-20200305145202825.png

image-20200305145300403.png

可以看到 container3 新增的文件在 container2 中同样能看到。

回到 container1,子容器中添加的内容在父容器中同样可以看到。

image-20200305145513404.png

在父容器中删除 c2_add.txt 同时在 c3_add.txt 中添加 "c1 hello world"。

image-20200305151119932.png

回到 container2 中查看,并且修改 c1_add.txt 与 c3_add.txt:

image-20200305151414993.png

回到 container3 中查看:

image-20200305151531320.png

现在删除 container1 ,然后查看 container 修改 c1_add.txt ,在 container3 中是否可以访问:

image-20200305151951645.png

image-20200305152039580.png

可见即使父容器被删除了,其新建的文件其他子容器仍然能修改,读取。

新建容器 container4 ,继承自 container3,然后删除 container2 和 container3,查看在 container4 中是否还能查看之前的文件

image-20200305154418348.png

image-20200305154451715.png

可知:容器之间配置信息可以互相传递,数据卷的生命周期一直持续到没有容器使用它为止。

dockerfile

dockerfile 是用来构建 docker 镜像的文件。

dockerfile 要求每条保留字指令必须为大写字母且后面要跟至少一个参数

指令从上到下执行

用于添加注释

每条指令都会创造一个新的镜像层(临时),并对镜像进行提交

dockerfile 构建流程

docker 从基础镜像运行一个容器

执行一条指令并对容器做出修改

执行类似 docker commit 的操作并且提交一个新的镜像层

docker 再鲸鱼刚提交的镜像层运行一个新的的容器

执行 dockerfile 中下一条指令知道所有指令都执行完成

dockerfile、镜像、容器三者关系.png

dockerfile 关键字

关键字

含义

FROM

基础镜像,表示新镜像是基于那个镜像的

MAINTAINER

镜像维护者的姓名和邮箱地址

RUN

容器构建是需要运行的命令

EXPOSE

当前容器对外暴露的端口

WORKDIR

创建容器后终端登录的默认路径

ENV

用来构建镜像过程中设置环境变量

ADD

将宿主机目录下的文件拷贝进镜像且 ADD 命令会自动处理 URL 与解压 tar 压缩包

COPY

类似 ADD

VOLUME

容器数据卷

CMD

指定容器启动时要运行的命令

ENTRYPOINT

指定容器启动时要运行的命令

ONBUILD

当构建一个被继承的 dockerfile 时运行的命令,父镜像被子继承后父镜像的 ONBUILD 被触发

备注:

ENV 设置环境变量以后再后续的指令中可以直接使用,例如:

ENV TEST /usr/test

WORKDIR $TEST

WORKDIR $TEST

COPY 拷贝有两种形式,COPY src dest 或者 COPY ["src","dest"]

ENTRYPOINT 在 docker run 镜像之后的参数会被当作参数传递给 ENTRYPOINT

CMD 也有两种形式

shell 格式:CMD

exec 格式:CMD ["可执行文件", "参数1", "参数2"]

参数列表格式:类似 exec 格式,CMD ["参数1", "参数2"...] 但是不传入可执行文件,可以用在 ENTRYPOINT指令之后,用于指定参数

编写 dockerfile 文件

FROM centos

MAINTAINER djz

# 把宿主机当前上下文的c.txt拷贝到容器/usr/local/路径下

COPY c.txt /usr/local/cincontainer.txt

# 把 test.tar.gz 添加到容器中

ADD test.tar.gz /usr/local/

# 安装vim编辑器

RUN yum -y install vim

# 设置工作访问时候的WORKDIR路径,登录目录

ENV WORKSPACE /usr/local

WORKDIR $WORKSPACE

# 容器运行时监听的端口

EXPOSE 80

CMD echo $MYPATH

CMD echo "success--------------ok"

CMD /bin/bash

保存然后运行:

docker build -f Dockerfile -t iotvim/centos:7.1 .

即可生成镜像,然按照正常镜像运行方式即可运行

docker run -it iotvim/centos:7.1

会发现默认处在 /usr/local下,且可以使用 vim

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值