docker--Dockerfile

网友投稿 816 2022-09-09

docker--Dockerfile

docker--Dockerfile

前戏

镜像是容器的基础,每次执行 docker run 的时候都会指定哪个镜像作为容器运行的基础,我们之前的例子都是使用来自 docker hub 的镜像。直接使用这些镜像只能满足一定的需求,当镜像无法满足我们的需求时,就得自定制这些镜像。

镜像的定制就是定制每一层所添加的配置、文件。如果把每一层修改,安装,构建,操作的命令都写入到一个脚本,用脚本来构建、定制镜像,这个脚本就是 Dockerfile。

Dockerfile 是一个文本文件,其内部包含一条条指令, 每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建

Dockerfile 可以说是一种可以被 Docker 程序解释的脚本,Dockerfile 是由一条条的命令组成的,每条命令对应 linux 下面的一条命令,Docker 程序将这些 Dockerfile 指令在翻译成真正的 linux 命令,其有自己的书写方式和支持的命令,docker 程序读取 Dockerfile 并根据指令生成 Docker 镜像,相比手动制作镜像的方式,Dockerfile 更能直观的展示镜像是怎么产生的。有了写好的各种各样的 Dockerfile 文件,当后期某个镜像有额外的需求时,只要在之前的 Dockerfile 添加或者修改相应的操作即可重新生成新的 Docker 镜像,避免了重复手动制作镜像的麻烦

Dockerfile的命令

FROM centos # 使用基础镜像 centos。在整个 dockerfile 文件中,除了注释之外的第一行,要是 FROM,用于指定父镜像FROM ubuntu:14.04 # 带有 tag 的 base imageLABEL version=“1.0” # 容器元信息,帮助信息,Metadata,类似于代码注释LABEL maintainer=“zouzou0214"# 对于复杂的RUN命令,避免无用的分层,多条命令用反斜线换行,合成一条命令!RUN yum update && yum install -y vim \ Python-dev #反 斜线换行RUN /bin/bash -c "source $HOME/.bashrc;echo $HOME”WORKDIR /root # 相当于 linux 的 cd 命令,改变目录,尽量使用绝对路径!!!不要用 RUN cdWORKDIR /test # 如果没有就自动创建WORKDIR demo # 再进入 demo 文件夹RUN pwd # 打印结果是 /test/demoADD and COPY ADD hello / # 把本地文件添加到镜像中(和 Dockerfile 同级),把本地的 hello 可执行文件拷贝到镜像的/目录ADD test.tar.gz / # 添加到根目录并解压WORKDIR /rootADD hello test/ # 进入 /root/ 添加 hello 可执行命令到 test 目录下,也就是 /root/test/hello 一个绝对路径COPY hello test/ # 等同于上述 ADD 效果'''ADD 与COPY - 优先使用 ADD 命令 -ADD 除了COPY 功能还有解压功能添加远程文件/目录使用 curl 或 wget'''ENV # 环境变量,尽可能使用 ENV 增加可维护性ENV MYSQL_VERSION 5.6 #设置一个 mysql 常量RUN yum install -y mysql-server=“${MYSQL_VERSION}” ------这里需要稍微理解一下了-------中级知识---VOLUME and EXPOSE 存储和网络RUN and CMD and ENTRYPOINTRUN:执行命令并创建新的 Image LayerCMD:设置容器启动后默认执行的命令和参数ENTRYPOINT:设置容器启动时运行的命令Shell 格式和 Exec 格式RUN yum install -y vimCMD echo ”hello docker”ENTRYPOINT echo “hello docker”Exec 格式RUN [“apt-get”,”install”,”-y”,”vim”]CMD [“/bin/echo”,”hello docker”]ENTRYPOINT [“/bin/echo”,”hello docker”]通过 shell 格式去运行命令,会读取 $name 指令,而 exec 格式是仅仅的执行一个命令,而不是 shell 指令cat Dockerfile FROM centos ENV name Docker ENTRYPOINT [“/bin/echo”,”hello $name”]# 这个仅仅是执行 echo 命令,读取不了 shell 变量 ENTRYPOINT [“/bin/bash”,”-c”,”echo hello $name"]CMD容器启动时默认执行的命令如果docker run指定了其他命令(docker run -it [image] /bin/bash ),CMD命令被忽略如果定义多个CMD,只有最后一个执行ENTRYPOINT让容器以应用程序或服务形式运行不会被忽略,一定会执行最佳实践:写一个shell脚本作为entrypointCOPY docker-entrypoint.sh /usr/local/binENTRYPOINT [“docker-entrypoint.sh]EXPOSE 27017CMD [“mongod”][root@master home]# more DockerfileFROm centosENV name Docker#CMD ["/bin/bash","-c","echo hello $name"]ENTRYPOINT ["/bin/bash","-c","echo hello $name”]

创建自己的容器镜像

1.先准备一段flask代码

myflask.py

from flask import Flask app=Flask(__name__) @app.route('/') def hello(): return "hello docker,i am is zouzou" if __name__=="__main__": app.run(host='0.0.0.0',port=8080)

2.准备传到docker容器里的文件

[root@HH tmp]# ls

3.制作Dockerfile

FROM centosLABEL maintainer="zouzou0214"ADD CentOS-Base.repo /etc/yum.repos.d/ADD epel.repo /etc/yum.repos.d/RUN yum clean allRUN yum install python-pip -yRUN pip install -i flaskCOPY myflask.py /app/WORKDIR /app/EXPOSE 8081CMD

1.引入一个 centos 镜像,为基础镜像2.作者注释信息3.添加本地的两个 yum 文件,到容器的 /etc/yum.repos.d/ 底下4.清空 yum 缓存5.yum 安装 pip 工具6.pip 安装 flask 模块,指定清华源7.拷贝本地的 flask 代码,到容器的 /app/ 目录下8.切换工作目录,到 /app 底下9.暴露容器的 8081 端口,然后在运行镜像时候,加上 -p 参数,指定端口映射10.执行命令,运行 flask

4.构建 docker 镜像

docker build -t zouzu0214/my-docker-flask .

注意:最后面有个.(点)代表从当前目录build

构建当前目录的 Dcokerfile,然后构建出一个名为 zouzou0214/my-docker-flask 这个的镜像文件-t tag 参数,给镜像加上标记名dockerhub 账户名:zouzou0214,dockerhub账户名/镜像名 ,是为了后面讲 docker 镜像,推送到 dockerhub

5.查看镜像是否构建成功:docker images

[root@HH tmp]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEzouzu0214/my-docker-flask latest 845652a3022e 12 seconds ago 346MBcentos latest 67fa590cfc1c 5 weeks ago 202MB

我本地是没有 centos 镜像的,会去先-一个 centos 镜像,然后基于该镜像构建

6.运行镜像

[root@HH tmp]# docker run -d -p 9000:8081 8456

docker run -p 9000:8081 -d 8456

-p 映射 9000 端口到容器的 8081

-d 后台运行

8456  镜像id

7.查看已经运行的docker实例

[root@HH tmp]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES44a53f62f533 76a7 "/sbin/tini -- /usr/…"

RUN、CMD、ENTRYPOINT 之间的区别

这三个命令都是执行命令的,那它们之间有什么区别呢?先来熟悉两个概念

shell 命令格式:RUN yum install -y pythonexec 命令格式:RUN [ "yum","install" ,"-y" ,"python"]

我们有一个centos:7的基础镜像

案例一:写一个 dockerfile,内容如下

FROM centos:7RUN echo "my is run..."CMD ["echo","my","is","cmd"]ENTRYPOINT

构建镜像

docker build -t centos:v1 .

启动这个镜像

[root@WC ~]# docker run centos:v1my is entrypoint echo my is

由上面的例子我们可以看出来,RUN 命令是作用于镜像的,在构建镜像的时候会执行 RUN 命令

而 CMD 和 ENTRYPOINT 是作用于容器的,在容器启动时执行的,会将 CMD 做为一个参数传递给 ENTRYPOINT ,所以上面输出的是 my is entrypoint echo my is cmd

案例二:修改 dockerfile,修改后的如下

FROM centos:7CMD ["echo","my","is","cmd1"]CMD ["echo","my","is","cmd2"]ENTRYPOINT ["echo","my","is","entrypoint1"]ENTRYPOINT

构建镜像

[root@WC ~]# docker build -t centos:v2 .Sending build context to Docker daemon 854kBStep 1/5 : FROM centos:7 ---> 5e35e350adedStep 2/5 : CMD ["echo","my","is","cmd1"] ---> Running in a5a50c279343Removing intermediate container a5a50c279343 ---> 580f6c1ca1d8Step 3/5 : CMD ["echo","my","is","cmd2"] ---> Running in bda45cc4de5fRemoving intermediate container bda45cc4de5f ---> 98daa774b962Step 4/5 : ENTRYPOINT ["echo","my","is","entrypoint1"] ---> Running in f181f49673e7Removing intermediate container f181f49673e7 ---> f477e3841a4aStep 5/5 : ENTRYPOINT ["echo","my","is","entrypoint2"] ---> Running in cc4b61298119Removing intermediate container cc4b61298119 ---> c7f3fbb0365aSuccessfully built c7f3fbb0365aSuccessfully tagged centos:v2

还是没有执行 CMD 和 ENTRYPOINT,启动容器

[root@WC ~]# docker run centos:v2my is entrypoint2 echo my is

结果:有多个 CMD 和 ENTRYPOINT 时,只执行最后的一个,会将最后一个的 CMD 作为最后一个 ENTRYPOINT 的参数

案例三:修改 dockerfile,修改后的如下

FROM centos:7CMD ["-ef"]ENTRYPOINT ["ps"]

构建镜像

[root@WC ~]# docker build -t centos:v3 .Sending build context to Docker daemon 854.5kBStep 1/3 : FROM centos:7 ---> 5e35e350adedStep 2/3 : CMD ["-ef"] ---> Running in 3c10444a83a0Removing intermediate container 3c10444a83a0 ---> 36d8da189295Step 3/3 : ENTRYPOINT ["ps"] ---> Running in e7751f2f9c64Removing intermediate container e7751f2f9c64 ---> ba96ea2aebf5Successfully built ba96ea2aebf5Successfully tagged centos:v3

启动镜像

可以看出会将 ENTRYPOINT 和 CMD 的执行结果显示出来,我们还可以在启动容器的时候加上参数,会替换掉 CMD 的参数

总结:

RUN:在构建镜像的时候执行,作用于镜像层面ENTRYPOINT:在容器启动的时候执行,作用于容器层,dockerfile 里有多条时只允许执行最后一条CMD:在容器启动的时候执行,作用于容器层,dockerfile 里有多条时只允许执行最后一条,容器启动后执行默认的命令或者参数,允许被修改

注意:如果 ENTRYPOINT 使用的是 exec 的格式,则会将 CMD 当做参数,如果是 shell,则不会将 CMD 当做参数

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Python os 模块(python能做什么)
下一篇:数据清洗之 分组对象与apply函数
相关文章

 发表评论

暂时没有评论,来抢沙发吧~